forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/fs/cifs/smb2inode.c
....@@ -37,96 +37,458 @@
3737 #include "smb2pdu.h"
3838 #include "smb2proto.h"
3939
40
-static int
41
-smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
42
- struct cifs_sb_info *cifs_sb, const char *full_path,
43
- __u32 desired_access, __u32 create_disposition,
44
- __u32 create_options, void *data, int command)
40
+static void
41
+free_set_inf_compound(struct smb_rqst *rqst)
4542 {
46
- int rc, tmprc = 0;
43
+ if (rqst[1].rq_iov)
44
+ SMB2_set_info_free(&rqst[1]);
45
+ if (rqst[2].rq_iov)
46
+ SMB2_close_free(&rqst[2]);
47
+}
48
+
49
+
50
+struct cop_vars {
51
+ struct cifs_open_parms oparms;
52
+ struct kvec rsp_iov[3];
53
+ struct smb_rqst rqst[3];
54
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
55
+ struct kvec qi_iov[1];
56
+ struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
57
+ struct kvec close_iov[1];
58
+ struct smb2_file_rename_info rename_info;
59
+ struct smb2_file_link_info link_info;
60
+};
61
+
62
+static int
63
+smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
64
+ struct cifs_sb_info *cifs_sb, const char *full_path,
65
+ __u32 desired_access, __u32 create_disposition,
66
+ __u32 create_options, umode_t mode, void *ptr, int command,
67
+ struct cifsFileInfo *cfile)
68
+{
69
+ struct cop_vars *vars = NULL;
70
+ struct kvec *rsp_iov;
71
+ struct smb_rqst *rqst;
72
+ int rc;
4773 __le16 *utf16_path = NULL;
4874 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
49
- struct cifs_open_parms oparms;
5075 struct cifs_fid fid;
51
- bool use_cached_root_handle = false;
76
+ struct cifs_ses *ses = tcon->ses;
77
+ struct TCP_Server_Info *server;
78
+ int num_rqst = 0;
79
+ int resp_buftype[3];
80
+ struct smb2_query_info_rsp *qi_rsp = NULL;
81
+ int flags = 0;
82
+ __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0};
83
+ unsigned int size[2];
84
+ void *data[2];
85
+ int len;
5286
53
- if ((strcmp(full_path, "") == 0) && (create_options == 0) &&
54
- (desired_access == FILE_READ_ATTRIBUTES) &&
55
- (create_disposition == FILE_OPEN) &&
56
- (tcon->nohandlecache == false)) {
57
- rc = open_shroot(xid, tcon, &fid);
58
- if (rc == 0)
59
- use_cached_root_handle = true;
87
+ vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
88
+ if (vars == NULL)
89
+ return -ENOMEM;
90
+ rqst = &vars->rqst[0];
91
+ rsp_iov = &vars->rsp_iov[0];
92
+
93
+ server = cifs_pick_channel(ses);
94
+
95
+ if (smb3_encryption_required(tcon))
96
+ flags |= CIFS_TRANSFORM_REQ;
97
+
98
+ resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
99
+
100
+ /* We already have a handle so we can skip the open */
101
+ if (cfile)
102
+ goto after_open;
103
+
104
+ /* Open */
105
+ utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
106
+ if (!utf16_path) {
107
+ rc = -ENOMEM;
108
+ goto finished;
60109 }
61110
62
- if (use_cached_root_handle == false) {
63
- utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
64
- if (!utf16_path)
65
- return -ENOMEM;
111
+ vars->oparms.tcon = tcon;
112
+ vars->oparms.desired_access = desired_access;
113
+ vars->oparms.disposition = create_disposition;
114
+ vars->oparms.create_options = cifs_create_options(cifs_sb, create_options);
115
+ vars->oparms.fid = &fid;
116
+ vars->oparms.reconnect = false;
117
+ vars->oparms.mode = mode;
118
+ vars->oparms.cifs_sb = cifs_sb;
66119
67
- oparms.tcon = tcon;
68
- oparms.desired_access = desired_access;
69
- oparms.disposition = create_disposition;
70
- oparms.create_options = create_options;
71
- oparms.fid = &fid;
72
- oparms.reconnect = false;
120
+ rqst[num_rqst].rq_iov = &vars->open_iov[0];
121
+ rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE;
122
+ rc = SMB2_open_init(tcon, server,
123
+ &rqst[num_rqst], &oplock, &vars->oparms,
124
+ utf16_path);
125
+ kfree(utf16_path);
126
+ if (rc)
127
+ goto finished;
73128
74
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
75
- NULL);
76
- if (rc) {
77
- kfree(utf16_path);
78
- return rc;
79
- }
80
- }
129
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
130
+ after_open:
131
+ num_rqst++;
132
+ rc = 0;
81133
134
+ /* Operation */
82135 switch (command) {
83
- case SMB2_OP_DELETE:
84
- break;
85136 case SMB2_OP_QUERY_INFO:
86
- tmprc = SMB2_query_info(xid, tcon, fid.persistent_fid,
87
- fid.volatile_fid,
88
- (struct smb2_file_all_info *)data);
137
+ rqst[num_rqst].rq_iov = &vars->qi_iov[0];
138
+ rqst[num_rqst].rq_nvec = 1;
139
+
140
+ if (cfile)
141
+ rc = SMB2_query_info_init(tcon, server,
142
+ &rqst[num_rqst],
143
+ cfile->fid.persistent_fid,
144
+ cfile->fid.volatile_fid,
145
+ FILE_ALL_INFORMATION,
146
+ SMB2_O_INFO_FILE, 0,
147
+ sizeof(struct smb2_file_all_info) +
148
+ PATH_MAX * 2, 0, NULL);
149
+ else {
150
+ rc = SMB2_query_info_init(tcon, server,
151
+ &rqst[num_rqst],
152
+ COMPOUND_FID,
153
+ COMPOUND_FID,
154
+ FILE_ALL_INFORMATION,
155
+ SMB2_O_INFO_FILE, 0,
156
+ sizeof(struct smb2_file_all_info) +
157
+ PATH_MAX * 2, 0, NULL);
158
+ if (!rc) {
159
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
160
+ smb2_set_related(&rqst[num_rqst]);
161
+ }
162
+ }
163
+
164
+ if (rc)
165
+ goto finished;
166
+ num_rqst++;
167
+ trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
168
+ full_path);
169
+ break;
170
+ case SMB2_OP_POSIX_QUERY_INFO:
171
+ rqst[num_rqst].rq_iov = &vars->qi_iov[0];
172
+ rqst[num_rqst].rq_nvec = 1;
173
+
174
+ if (cfile)
175
+ rc = SMB2_query_info_init(tcon, server,
176
+ &rqst[num_rqst],
177
+ cfile->fid.persistent_fid,
178
+ cfile->fid.volatile_fid,
179
+ SMB_FIND_FILE_POSIX_INFO,
180
+ SMB2_O_INFO_FILE, 0,
181
+ /* TBD: fix following to allow for longer SIDs */
182
+ sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) +
183
+ (sizeof(struct cifs_sid) * 2), 0, NULL);
184
+ else {
185
+ rc = SMB2_query_info_init(tcon, server,
186
+ &rqst[num_rqst],
187
+ COMPOUND_FID,
188
+ COMPOUND_FID,
189
+ SMB_FIND_FILE_POSIX_INFO,
190
+ SMB2_O_INFO_FILE, 0,
191
+ sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) +
192
+ (sizeof(struct cifs_sid) * 2), 0, NULL);
193
+ if (!rc) {
194
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
195
+ smb2_set_related(&rqst[num_rqst]);
196
+ }
197
+ }
198
+
199
+ if (rc)
200
+ goto finished;
201
+ num_rqst++;
202
+ trace_smb3_posix_query_info_compound_enter(xid, ses->Suid, tcon->tid, full_path);
203
+ break;
204
+ case SMB2_OP_DELETE:
205
+ trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);
89206 break;
90207 case SMB2_OP_MKDIR:
91208 /*
92209 * Directories are created through parameters in the
93210 * SMB2_open() call.
94211 */
212
+ trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path);
95213 break;
96214 case SMB2_OP_RMDIR:
97
- tmprc = SMB2_rmdir(xid, tcon, fid.persistent_fid,
98
- fid.volatile_fid);
99
- break;
100
- case SMB2_OP_RENAME:
101
- tmprc = SMB2_rename(xid, tcon, fid.persistent_fid,
102
- fid.volatile_fid, (__le16 *)data);
103
- break;
104
- case SMB2_OP_HARDLINK:
105
- tmprc = SMB2_set_hardlink(xid, tcon, fid.persistent_fid,
106
- fid.volatile_fid, (__le16 *)data);
215
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
216
+ rqst[num_rqst].rq_nvec = 1;
217
+
218
+ size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
219
+ data[0] = &delete_pending[0];
220
+
221
+ rc = SMB2_set_info_init(tcon, server,
222
+ &rqst[num_rqst], COMPOUND_FID,
223
+ COMPOUND_FID, current->tgid,
224
+ FILE_DISPOSITION_INFORMATION,
225
+ SMB2_O_INFO_FILE, 0, data, size);
226
+ if (rc)
227
+ goto finished;
228
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
229
+ smb2_set_related(&rqst[num_rqst++]);
230
+ trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path);
107231 break;
108232 case SMB2_OP_SET_EOF:
109
- tmprc = SMB2_set_eof(xid, tcon, fid.persistent_fid,
110
- fid.volatile_fid, current->tgid,
111
- (__le64 *)data, false);
233
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
234
+ rqst[num_rqst].rq_nvec = 1;
235
+
236
+ size[0] = 8; /* sizeof __le64 */
237
+ data[0] = ptr;
238
+
239
+ rc = SMB2_set_info_init(tcon, server,
240
+ &rqst[num_rqst], COMPOUND_FID,
241
+ COMPOUND_FID, current->tgid,
242
+ FILE_END_OF_FILE_INFORMATION,
243
+ SMB2_O_INFO_FILE, 0, data, size);
244
+ if (rc)
245
+ goto finished;
246
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
247
+ smb2_set_related(&rqst[num_rqst++]);
248
+ trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
112249 break;
113250 case SMB2_OP_SET_INFO:
114
- tmprc = SMB2_set_info(xid, tcon, fid.persistent_fid,
115
- fid.volatile_fid,
116
- (FILE_BASIC_INFO *)data);
251
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
252
+ rqst[num_rqst].rq_nvec = 1;
253
+
254
+
255
+ size[0] = sizeof(FILE_BASIC_INFO);
256
+ data[0] = ptr;
257
+
258
+ if (cfile)
259
+ rc = SMB2_set_info_init(tcon, server,
260
+ &rqst[num_rqst],
261
+ cfile->fid.persistent_fid,
262
+ cfile->fid.volatile_fid, current->tgid,
263
+ FILE_BASIC_INFORMATION,
264
+ SMB2_O_INFO_FILE, 0, data, size);
265
+ else {
266
+ rc = SMB2_set_info_init(tcon, server,
267
+ &rqst[num_rqst],
268
+ COMPOUND_FID,
269
+ COMPOUND_FID, current->tgid,
270
+ FILE_BASIC_INFORMATION,
271
+ SMB2_O_INFO_FILE, 0, data, size);
272
+ if (!rc) {
273
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
274
+ smb2_set_related(&rqst[num_rqst]);
275
+ }
276
+ }
277
+
278
+ if (rc)
279
+ goto finished;
280
+ num_rqst++;
281
+ trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid,
282
+ full_path);
283
+ break;
284
+ case SMB2_OP_RENAME:
285
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
286
+ rqst[num_rqst].rq_nvec = 2;
287
+
288
+ len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
289
+
290
+ vars->rename_info.ReplaceIfExists = 1;
291
+ vars->rename_info.RootDirectory = 0;
292
+ vars->rename_info.FileNameLength = cpu_to_le32(len);
293
+
294
+ size[0] = sizeof(struct smb2_file_rename_info);
295
+ data[0] = &vars->rename_info;
296
+
297
+ size[1] = len + 2 /* null */;
298
+ data[1] = (__le16 *)ptr;
299
+
300
+ if (cfile)
301
+ rc = SMB2_set_info_init(tcon, server,
302
+ &rqst[num_rqst],
303
+ cfile->fid.persistent_fid,
304
+ cfile->fid.volatile_fid,
305
+ current->tgid, FILE_RENAME_INFORMATION,
306
+ SMB2_O_INFO_FILE, 0, data, size);
307
+ else {
308
+ rc = SMB2_set_info_init(tcon, server,
309
+ &rqst[num_rqst],
310
+ COMPOUND_FID, COMPOUND_FID,
311
+ current->tgid, FILE_RENAME_INFORMATION,
312
+ SMB2_O_INFO_FILE, 0, data, size);
313
+ if (!rc) {
314
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
315
+ smb2_set_related(&rqst[num_rqst]);
316
+ }
317
+ }
318
+ if (rc)
319
+ goto finished;
320
+ num_rqst++;
321
+ trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
322
+ break;
323
+ case SMB2_OP_HARDLINK:
324
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
325
+ rqst[num_rqst].rq_nvec = 2;
326
+
327
+ len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
328
+
329
+ vars->link_info.ReplaceIfExists = 0;
330
+ vars->link_info.RootDirectory = 0;
331
+ vars->link_info.FileNameLength = cpu_to_le32(len);
332
+
333
+ size[0] = sizeof(struct smb2_file_link_info);
334
+ data[0] = &vars->link_info;
335
+
336
+ size[1] = len + 2 /* null */;
337
+ data[1] = (__le16 *)ptr;
338
+
339
+ rc = SMB2_set_info_init(tcon, server,
340
+ &rqst[num_rqst], COMPOUND_FID,
341
+ COMPOUND_FID, current->tgid,
342
+ FILE_LINK_INFORMATION,
343
+ SMB2_O_INFO_FILE, 0, data, size);
344
+ if (rc)
345
+ goto finished;
346
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
347
+ smb2_set_related(&rqst[num_rqst++]);
348
+ trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path);
117349 break;
118350 default:
119351 cifs_dbg(VFS, "Invalid command\n");
120
- break;
352
+ rc = -EINVAL;
353
+ }
354
+ if (rc)
355
+ goto finished;
356
+
357
+ /* We already have a handle so we can skip the close */
358
+ if (cfile)
359
+ goto after_close;
360
+ /* Close */
361
+ flags |= CIFS_CP_CREATE_CLOSE_OP;
362
+ rqst[num_rqst].rq_iov = &vars->close_iov[0];
363
+ rqst[num_rqst].rq_nvec = 1;
364
+ rc = SMB2_close_init(tcon, server,
365
+ &rqst[num_rqst], COMPOUND_FID,
366
+ COMPOUND_FID, false);
367
+ smb2_set_related(&rqst[num_rqst]);
368
+ if (rc)
369
+ goto finished;
370
+ after_close:
371
+ num_rqst++;
372
+
373
+ if (cfile) {
374
+ rc = compound_send_recv(xid, ses, server,
375
+ flags, num_rqst - 2,
376
+ &rqst[1], &resp_buftype[1],
377
+ &rsp_iov[1]);
378
+ } else
379
+ rc = compound_send_recv(xid, ses, server,
380
+ flags, num_rqst,
381
+ rqst, resp_buftype,
382
+ rsp_iov);
383
+
384
+ finished:
385
+ if (cfile)
386
+ cifsFileInfo_put(cfile);
387
+
388
+ SMB2_open_free(&rqst[0]);
389
+ if (rc == -EREMCHG) {
390
+ pr_warn_once("server share %s deleted\n", tcon->treeName);
391
+ tcon->need_reconnect = true;
121392 }
122393
123
- if (use_cached_root_handle)
124
- close_shroot(&tcon->crfid);
125
- else
126
- rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
127
- if (tmprc)
128
- rc = tmprc;
129
- kfree(utf16_path);
394
+ switch (command) {
395
+ case SMB2_OP_QUERY_INFO:
396
+ if (rc == 0) {
397
+ qi_rsp = (struct smb2_query_info_rsp *)
398
+ rsp_iov[1].iov_base;
399
+ rc = smb2_validate_and_copy_iov(
400
+ le16_to_cpu(qi_rsp->OutputBufferOffset),
401
+ le32_to_cpu(qi_rsp->OutputBufferLength),
402
+ &rsp_iov[1], sizeof(struct smb2_file_all_info),
403
+ ptr);
404
+ }
405
+ if (rqst[1].rq_iov)
406
+ SMB2_query_info_free(&rqst[1]);
407
+ if (rqst[2].rq_iov)
408
+ SMB2_close_free(&rqst[2]);
409
+ if (rc)
410
+ trace_smb3_query_info_compound_err(xid, ses->Suid,
411
+ tcon->tid, rc);
412
+ else
413
+ trace_smb3_query_info_compound_done(xid, ses->Suid,
414
+ tcon->tid);
415
+ break;
416
+ case SMB2_OP_POSIX_QUERY_INFO:
417
+ if (rc == 0) {
418
+ qi_rsp = (struct smb2_query_info_rsp *)
419
+ rsp_iov[1].iov_base;
420
+ rc = smb2_validate_and_copy_iov(
421
+ le16_to_cpu(qi_rsp->OutputBufferOffset),
422
+ le32_to_cpu(qi_rsp->OutputBufferLength),
423
+ &rsp_iov[1], sizeof(struct smb311_posix_qinfo) /* add SIDs */, ptr);
424
+ }
425
+ if (rqst[1].rq_iov)
426
+ SMB2_query_info_free(&rqst[1]);
427
+ if (rqst[2].rq_iov)
428
+ SMB2_close_free(&rqst[2]);
429
+ if (rc)
430
+ trace_smb3_posix_query_info_compound_err(xid, ses->Suid, tcon->tid, rc);
431
+ else
432
+ trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid);
433
+ break;
434
+ case SMB2_OP_DELETE:
435
+ if (rc)
436
+ trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc);
437
+ else
438
+ trace_smb3_delete_done(xid, ses->Suid, tcon->tid);
439
+ if (rqst[1].rq_iov)
440
+ SMB2_close_free(&rqst[1]);
441
+ break;
442
+ case SMB2_OP_MKDIR:
443
+ if (rc)
444
+ trace_smb3_mkdir_err(xid, ses->Suid, tcon->tid, rc);
445
+ else
446
+ trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid);
447
+ if (rqst[1].rq_iov)
448
+ SMB2_close_free(&rqst[1]);
449
+ break;
450
+ case SMB2_OP_HARDLINK:
451
+ if (rc)
452
+ trace_smb3_hardlink_err(xid, ses->Suid, tcon->tid, rc);
453
+ else
454
+ trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid);
455
+ free_set_inf_compound(rqst);
456
+ break;
457
+ case SMB2_OP_RENAME:
458
+ if (rc)
459
+ trace_smb3_rename_err(xid, ses->Suid, tcon->tid, rc);
460
+ else
461
+ trace_smb3_rename_done(xid, ses->Suid, tcon->tid);
462
+ free_set_inf_compound(rqst);
463
+ break;
464
+ case SMB2_OP_RMDIR:
465
+ if (rc)
466
+ trace_smb3_rmdir_err(xid, ses->Suid, tcon->tid, rc);
467
+ else
468
+ trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid);
469
+ free_set_inf_compound(rqst);
470
+ break;
471
+ case SMB2_OP_SET_EOF:
472
+ if (rc)
473
+ trace_smb3_set_eof_err(xid, ses->Suid, tcon->tid, rc);
474
+ else
475
+ trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid);
476
+ free_set_inf_compound(rqst);
477
+ break;
478
+ case SMB2_OP_SET_INFO:
479
+ if (rc)
480
+ trace_smb3_set_info_compound_err(xid, ses->Suid,
481
+ tcon->tid, rc);
482
+ else
483
+ trace_smb3_set_info_compound_done(xid, ses->Suid,
484
+ tcon->tid);
485
+ free_set_inf_compound(rqst);
486
+ break;
487
+ }
488
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
489
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
490
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
491
+ kfree(vars);
130492 return rc;
131493 }
132494
....@@ -143,29 +505,56 @@
143505 int
144506 smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
145507 struct cifs_sb_info *cifs_sb, const char *full_path,
146
- FILE_ALL_INFO *data, bool *adjust_tz, bool *symlink)
508
+ FILE_ALL_INFO *data, bool *adjust_tz, bool *reparse)
147509 {
148510 int rc;
149511 struct smb2_file_all_info *smb2_data;
512
+ __u32 create_options = 0;
513
+ bool no_cached_open = tcon->nohandlecache;
514
+ struct cifsFileInfo *cfile;
515
+ struct cached_fid *cfid = NULL;
150516
151517 *adjust_tz = false;
152
- *symlink = false;
518
+ *reparse = false;
153519
154520 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
155521 GFP_KERNEL);
156522 if (smb2_data == NULL)
157523 return -ENOMEM;
158524
159
- rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path,
160
- FILE_READ_ATTRIBUTES, FILE_OPEN, 0,
161
- smb2_data, SMB2_OP_QUERY_INFO);
525
+ /* If it is a root and its handle is cached then use it */
526
+ if (!strlen(full_path) && !no_cached_open) {
527
+ rc = open_shroot(xid, tcon, cifs_sb, &cfid);
528
+ if (rc)
529
+ goto out;
530
+
531
+ if (tcon->crfid.file_all_info_is_valid) {
532
+ move_smb2_info_to_cifs(data,
533
+ &tcon->crfid.file_all_info);
534
+ } else {
535
+ rc = SMB2_query_info(xid, tcon,
536
+ cfid->fid->persistent_fid,
537
+ cfid->fid->volatile_fid, smb2_data);
538
+ if (!rc)
539
+ move_smb2_info_to_cifs(data, smb2_data);
540
+ }
541
+ close_shroot(cfid);
542
+ goto out;
543
+ }
544
+
545
+ cifs_get_readable_path(tcon, full_path, &cfile);
546
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
547
+ FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
548
+ ACL_NO_MODE, smb2_data, SMB2_OP_QUERY_INFO, cfile);
162549 if (rc == -EOPNOTSUPP) {
163
- *symlink = true;
550
+ *reparse = true;
551
+ create_options |= OPEN_REPARSE_POINT;
552
+
164553 /* Failed on a symbolic link - query a reparse point info */
165
- rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path,
166
- FILE_READ_ATTRIBUTES, FILE_OPEN,
167
- OPEN_REPARSE_POINT, smb2_data,
168
- SMB2_OP_QUERY_INFO);
554
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
555
+ FILE_READ_ATTRIBUTES, FILE_OPEN,
556
+ create_options, ACL_NO_MODE,
557
+ smb2_data, SMB2_OP_QUERY_INFO, NULL);
169558 }
170559 if (rc)
171560 goto out;
....@@ -176,13 +565,68 @@
176565 return rc;
177566 }
178567
568
+
179569 int
180
-smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
570
+smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
571
+ struct cifs_sb_info *cifs_sb, const char *full_path,
572
+ struct smb311_posix_qinfo *data, bool *adjust_tz, bool *reparse)
573
+{
574
+ int rc;
575
+ __u32 create_options = 0;
576
+ struct cifsFileInfo *cfile;
577
+ struct smb311_posix_qinfo *smb2_data;
578
+
579
+ *adjust_tz = false;
580
+ *reparse = false;
581
+
582
+ /* BB TODO: Make struct larger when add support for parsing owner SIDs */
583
+ smb2_data = kzalloc(sizeof(struct smb311_posix_qinfo),
584
+ GFP_KERNEL);
585
+ if (smb2_data == NULL)
586
+ return -ENOMEM;
587
+
588
+ /*
589
+ * BB TODO: Add support for using the cached root handle.
590
+ * Create SMB2_query_posix_info worker function to do non-compounded query
591
+ * when we already have an open file handle for this. For now this is fast enough
592
+ * (always using the compounded version).
593
+ */
594
+
595
+ cifs_get_readable_path(tcon, full_path, &cfile);
596
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
597
+ FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
598
+ ACL_NO_MODE, smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile);
599
+ if (rc == -EOPNOTSUPP) {
600
+ /* BB TODO: When support for special files added to Samba re-verify this path */
601
+ *reparse = true;
602
+ create_options |= OPEN_REPARSE_POINT;
603
+
604
+ /* Failed on a symbolic link - query a reparse point info */
605
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
606
+ FILE_READ_ATTRIBUTES, FILE_OPEN,
607
+ create_options, ACL_NO_MODE,
608
+ smb2_data, SMB2_OP_POSIX_QUERY_INFO, NULL);
609
+ }
610
+ if (rc)
611
+ goto out;
612
+
613
+ /* TODO: will need to allow for the 2 SIDs when add support for getting owner UID/GID */
614
+ memcpy(data, smb2_data, sizeof(struct smb311_posix_qinfo));
615
+
616
+out:
617
+ kfree(smb2_data);
618
+ return rc;
619
+}
620
+
621
+int
622
+smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
623
+ struct cifs_tcon *tcon, const char *name,
181624 struct cifs_sb_info *cifs_sb)
182625 {
183
- return smb2_open_op_close(xid, tcon, cifs_sb, name,
184
- FILE_WRITE_ATTRIBUTES, FILE_CREATE,
185
- CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR);
626
+ return smb2_compound_op(xid, tcon, cifs_sb, name,
627
+ FILE_WRITE_ATTRIBUTES, FILE_CREATE,
628
+ CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR,
629
+ NULL);
186630 }
187631
188632 void
....@@ -192,6 +636,7 @@
192636 {
193637 FILE_BASIC_INFO data;
194638 struct cifsInodeInfo *cifs_i;
639
+ struct cifsFileInfo *cfile;
195640 u32 dosattrs;
196641 int tmprc;
197642
....@@ -199,9 +644,11 @@
199644 cifs_i = CIFS_I(inode);
200645 dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
201646 data.Attributes = cpu_to_le32(dosattrs);
202
- tmprc = smb2_open_op_close(xid, tcon, cifs_sb, name,
203
- FILE_WRITE_ATTRIBUTES, FILE_CREATE,
204
- CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO);
647
+ cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
648
+ tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
649
+ FILE_WRITE_ATTRIBUTES, FILE_CREATE,
650
+ CREATE_NOT_FILE, ACL_NO_MODE,
651
+ &data, SMB2_OP_SET_INFO, cfile);
205652 if (tmprc == 0)
206653 cifs_i->cifsAttrs = dosattrs;
207654 }
....@@ -210,24 +657,25 @@
210657 smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
211658 struct cifs_sb_info *cifs_sb)
212659 {
213
- return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
214
- CREATE_NOT_FILE,
215
- NULL, SMB2_OP_RMDIR);
660
+ return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
661
+ CREATE_NOT_FILE, ACL_NO_MODE,
662
+ NULL, SMB2_OP_RMDIR, NULL);
216663 }
217664
218665 int
219666 smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
220667 struct cifs_sb_info *cifs_sb)
221668 {
222
- return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
223
- CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
224
- NULL, SMB2_OP_DELETE);
669
+ return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
670
+ CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
671
+ ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL);
225672 }
226673
227674 static int
228675 smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
229676 const char *from_name, const char *to_name,
230
- struct cifs_sb_info *cifs_sb, __u32 access, int command)
677
+ struct cifs_sb_info *cifs_sb, __u32 access, int command,
678
+ struct cifsFileInfo *cfile)
231679 {
232680 __le16 *smb2_to_name = NULL;
233681 int rc;
....@@ -237,9 +685,9 @@
237685 rc = -ENOMEM;
238686 goto smb2_rename_path;
239687 }
240
-
241
- rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, access,
242
- FILE_OPEN, 0, smb2_to_name, command);
688
+ rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
689
+ FILE_OPEN, 0, ACL_NO_MODE, smb2_to_name,
690
+ command, cfile);
243691 smb2_rename_path:
244692 kfree(smb2_to_name);
245693 return rc;
....@@ -250,8 +698,12 @@
250698 const char *from_name, const char *to_name,
251699 struct cifs_sb_info *cifs_sb)
252700 {
253
- return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
254
- DELETE, SMB2_OP_RENAME);
701
+ struct cifsFileInfo *cfile;
702
+
703
+ cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
704
+
705
+ return smb2_set_path_attr(xid, tcon, from_name, to_name,
706
+ cifs_sb, DELETE, SMB2_OP_RENAME, cfile);
255707 }
256708
257709 int
....@@ -260,7 +712,8 @@
260712 struct cifs_sb_info *cifs_sb)
261713 {
262714 return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
263
- FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK);
715
+ FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK,
716
+ NULL);
264717 }
265718
266719 int
....@@ -269,9 +722,10 @@
269722 struct cifs_sb_info *cifs_sb, bool set_alloc)
270723 {
271724 __le64 eof = cpu_to_le64(size);
272
- return smb2_open_op_close(xid, tcon, cifs_sb, full_path,
273
- FILE_WRITE_DATA, FILE_OPEN, 0, &eof,
274
- SMB2_OP_SET_EOF);
725
+
726
+ return smb2_compound_op(xid, tcon, cifs_sb, full_path,
727
+ FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE,
728
+ &eof, SMB2_OP_SET_EOF, NULL);
275729 }
276730
277731 int
....@@ -291,9 +745,9 @@
291745 if (IS_ERR(tlink))
292746 return PTR_ERR(tlink);
293747
294
- rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path,
295
- FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf,
296
- SMB2_OP_SET_INFO);
748
+ rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path,
749
+ FILE_WRITE_ATTRIBUTES, FILE_OPEN,
750
+ 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, NULL);
297751 cifs_put_tlink(tlink);
298752 return rc;
299753 }