hc
2024-09-20 a36159eec6ca17402b0e146b86efaf76568dc353
kernel/fs/cifs/smb2inode.c
....@@ -37,96 +37,475 @@
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
+ if (cfile) {
240
+ rc = SMB2_set_info_init(tcon, server,
241
+ &rqst[num_rqst],
242
+ cfile->fid.persistent_fid,
243
+ cfile->fid.volatile_fid,
244
+ current->tgid,
245
+ FILE_END_OF_FILE_INFORMATION,
246
+ SMB2_O_INFO_FILE, 0,
247
+ data, size);
248
+ } else {
249
+ rc = SMB2_set_info_init(tcon, server,
250
+ &rqst[num_rqst],
251
+ COMPOUND_FID,
252
+ COMPOUND_FID,
253
+ current->tgid,
254
+ FILE_END_OF_FILE_INFORMATION,
255
+ SMB2_O_INFO_FILE, 0,
256
+ data, size);
257
+ if (!rc) {
258
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
259
+ smb2_set_related(&rqst[num_rqst]);
260
+ }
261
+ }
262
+ if (rc)
263
+ goto finished;
264
+ num_rqst++;
265
+ trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
112266 break;
113267 case SMB2_OP_SET_INFO:
114
- tmprc = SMB2_set_info(xid, tcon, fid.persistent_fid,
115
- fid.volatile_fid,
116
- (FILE_BASIC_INFO *)data);
268
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
269
+ rqst[num_rqst].rq_nvec = 1;
270
+
271
+
272
+ size[0] = sizeof(FILE_BASIC_INFO);
273
+ data[0] = ptr;
274
+
275
+ if (cfile)
276
+ rc = SMB2_set_info_init(tcon, server,
277
+ &rqst[num_rqst],
278
+ cfile->fid.persistent_fid,
279
+ cfile->fid.volatile_fid, current->tgid,
280
+ FILE_BASIC_INFORMATION,
281
+ SMB2_O_INFO_FILE, 0, data, size);
282
+ else {
283
+ rc = SMB2_set_info_init(tcon, server,
284
+ &rqst[num_rqst],
285
+ COMPOUND_FID,
286
+ COMPOUND_FID, current->tgid,
287
+ FILE_BASIC_INFORMATION,
288
+ SMB2_O_INFO_FILE, 0, data, size);
289
+ if (!rc) {
290
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
291
+ smb2_set_related(&rqst[num_rqst]);
292
+ }
293
+ }
294
+
295
+ if (rc)
296
+ goto finished;
297
+ num_rqst++;
298
+ trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid,
299
+ full_path);
300
+ break;
301
+ case SMB2_OP_RENAME:
302
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
303
+ rqst[num_rqst].rq_nvec = 2;
304
+
305
+ len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
306
+
307
+ vars->rename_info.ReplaceIfExists = 1;
308
+ vars->rename_info.RootDirectory = 0;
309
+ vars->rename_info.FileNameLength = cpu_to_le32(len);
310
+
311
+ size[0] = sizeof(struct smb2_file_rename_info);
312
+ data[0] = &vars->rename_info;
313
+
314
+ size[1] = len + 2 /* null */;
315
+ data[1] = (__le16 *)ptr;
316
+
317
+ if (cfile)
318
+ rc = SMB2_set_info_init(tcon, server,
319
+ &rqst[num_rqst],
320
+ cfile->fid.persistent_fid,
321
+ cfile->fid.volatile_fid,
322
+ current->tgid, FILE_RENAME_INFORMATION,
323
+ SMB2_O_INFO_FILE, 0, data, size);
324
+ else {
325
+ rc = SMB2_set_info_init(tcon, server,
326
+ &rqst[num_rqst],
327
+ COMPOUND_FID, COMPOUND_FID,
328
+ current->tgid, FILE_RENAME_INFORMATION,
329
+ SMB2_O_INFO_FILE, 0, data, size);
330
+ if (!rc) {
331
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
332
+ smb2_set_related(&rqst[num_rqst]);
333
+ }
334
+ }
335
+ if (rc)
336
+ goto finished;
337
+ num_rqst++;
338
+ trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
339
+ break;
340
+ case SMB2_OP_HARDLINK:
341
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
342
+ rqst[num_rqst].rq_nvec = 2;
343
+
344
+ len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
345
+
346
+ vars->link_info.ReplaceIfExists = 0;
347
+ vars->link_info.RootDirectory = 0;
348
+ vars->link_info.FileNameLength = cpu_to_le32(len);
349
+
350
+ size[0] = sizeof(struct smb2_file_link_info);
351
+ data[0] = &vars->link_info;
352
+
353
+ size[1] = len + 2 /* null */;
354
+ data[1] = (__le16 *)ptr;
355
+
356
+ rc = SMB2_set_info_init(tcon, server,
357
+ &rqst[num_rqst], COMPOUND_FID,
358
+ COMPOUND_FID, current->tgid,
359
+ FILE_LINK_INFORMATION,
360
+ SMB2_O_INFO_FILE, 0, data, size);
361
+ if (rc)
362
+ goto finished;
363
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
364
+ smb2_set_related(&rqst[num_rqst++]);
365
+ trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path);
117366 break;
118367 default:
119368 cifs_dbg(VFS, "Invalid command\n");
120
- break;
369
+ rc = -EINVAL;
370
+ }
371
+ if (rc)
372
+ goto finished;
373
+
374
+ /* We already have a handle so we can skip the close */
375
+ if (cfile)
376
+ goto after_close;
377
+ /* Close */
378
+ flags |= CIFS_CP_CREATE_CLOSE_OP;
379
+ rqst[num_rqst].rq_iov = &vars->close_iov[0];
380
+ rqst[num_rqst].rq_nvec = 1;
381
+ rc = SMB2_close_init(tcon, server,
382
+ &rqst[num_rqst], COMPOUND_FID,
383
+ COMPOUND_FID, false);
384
+ smb2_set_related(&rqst[num_rqst]);
385
+ if (rc)
386
+ goto finished;
387
+ after_close:
388
+ num_rqst++;
389
+
390
+ if (cfile) {
391
+ rc = compound_send_recv(xid, ses, server,
392
+ flags, num_rqst - 2,
393
+ &rqst[1], &resp_buftype[1],
394
+ &rsp_iov[1]);
395
+ } else
396
+ rc = compound_send_recv(xid, ses, server,
397
+ flags, num_rqst,
398
+ rqst, resp_buftype,
399
+ rsp_iov);
400
+
401
+ finished:
402
+ if (cfile)
403
+ cifsFileInfo_put(cfile);
404
+
405
+ SMB2_open_free(&rqst[0]);
406
+ if (rc == -EREMCHG) {
407
+ pr_warn_once("server share %s deleted\n", tcon->treeName);
408
+ tcon->need_reconnect = true;
121409 }
122410
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);
411
+ switch (command) {
412
+ case SMB2_OP_QUERY_INFO:
413
+ if (rc == 0) {
414
+ qi_rsp = (struct smb2_query_info_rsp *)
415
+ rsp_iov[1].iov_base;
416
+ rc = smb2_validate_and_copy_iov(
417
+ le16_to_cpu(qi_rsp->OutputBufferOffset),
418
+ le32_to_cpu(qi_rsp->OutputBufferLength),
419
+ &rsp_iov[1], sizeof(struct smb2_file_all_info),
420
+ ptr);
421
+ }
422
+ if (rqst[1].rq_iov)
423
+ SMB2_query_info_free(&rqst[1]);
424
+ if (rqst[2].rq_iov)
425
+ SMB2_close_free(&rqst[2]);
426
+ if (rc)
427
+ trace_smb3_query_info_compound_err(xid, ses->Suid,
428
+ tcon->tid, rc);
429
+ else
430
+ trace_smb3_query_info_compound_done(xid, ses->Suid,
431
+ tcon->tid);
432
+ break;
433
+ case SMB2_OP_POSIX_QUERY_INFO:
434
+ if (rc == 0) {
435
+ qi_rsp = (struct smb2_query_info_rsp *)
436
+ rsp_iov[1].iov_base;
437
+ rc = smb2_validate_and_copy_iov(
438
+ le16_to_cpu(qi_rsp->OutputBufferOffset),
439
+ le32_to_cpu(qi_rsp->OutputBufferLength),
440
+ &rsp_iov[1], sizeof(struct smb311_posix_qinfo) /* add SIDs */, ptr);
441
+ }
442
+ if (rqst[1].rq_iov)
443
+ SMB2_query_info_free(&rqst[1]);
444
+ if (rqst[2].rq_iov)
445
+ SMB2_close_free(&rqst[2]);
446
+ if (rc)
447
+ trace_smb3_posix_query_info_compound_err(xid, ses->Suid, tcon->tid, rc);
448
+ else
449
+ trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid);
450
+ break;
451
+ case SMB2_OP_DELETE:
452
+ if (rc)
453
+ trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc);
454
+ else
455
+ trace_smb3_delete_done(xid, ses->Suid, tcon->tid);
456
+ if (rqst[1].rq_iov)
457
+ SMB2_close_free(&rqst[1]);
458
+ break;
459
+ case SMB2_OP_MKDIR:
460
+ if (rc)
461
+ trace_smb3_mkdir_err(xid, ses->Suid, tcon->tid, rc);
462
+ else
463
+ trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid);
464
+ if (rqst[1].rq_iov)
465
+ SMB2_close_free(&rqst[1]);
466
+ break;
467
+ case SMB2_OP_HARDLINK:
468
+ if (rc)
469
+ trace_smb3_hardlink_err(xid, ses->Suid, tcon->tid, rc);
470
+ else
471
+ trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid);
472
+ free_set_inf_compound(rqst);
473
+ break;
474
+ case SMB2_OP_RENAME:
475
+ if (rc)
476
+ trace_smb3_rename_err(xid, ses->Suid, tcon->tid, rc);
477
+ else
478
+ trace_smb3_rename_done(xid, ses->Suid, tcon->tid);
479
+ free_set_inf_compound(rqst);
480
+ break;
481
+ case SMB2_OP_RMDIR:
482
+ if (rc)
483
+ trace_smb3_rmdir_err(xid, ses->Suid, tcon->tid, rc);
484
+ else
485
+ trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid);
486
+ free_set_inf_compound(rqst);
487
+ break;
488
+ case SMB2_OP_SET_EOF:
489
+ if (rc)
490
+ trace_smb3_set_eof_err(xid, ses->Suid, tcon->tid, rc);
491
+ else
492
+ trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid);
493
+ free_set_inf_compound(rqst);
494
+ break;
495
+ case SMB2_OP_SET_INFO:
496
+ if (rc)
497
+ trace_smb3_set_info_compound_err(xid, ses->Suid,
498
+ tcon->tid, rc);
499
+ else
500
+ trace_smb3_set_info_compound_done(xid, ses->Suid,
501
+ tcon->tid);
502
+ free_set_inf_compound(rqst);
503
+ break;
504
+ }
505
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
506
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
507
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
508
+ kfree(vars);
130509 return rc;
131510 }
132511
....@@ -143,29 +522,56 @@
143522 int
144523 smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
145524 struct cifs_sb_info *cifs_sb, const char *full_path,
146
- FILE_ALL_INFO *data, bool *adjust_tz, bool *symlink)
525
+ FILE_ALL_INFO *data, bool *adjust_tz, bool *reparse)
147526 {
148527 int rc;
149528 struct smb2_file_all_info *smb2_data;
529
+ __u32 create_options = 0;
530
+ bool no_cached_open = tcon->nohandlecache;
531
+ struct cifsFileInfo *cfile;
532
+ struct cached_fid *cfid = NULL;
150533
151534 *adjust_tz = false;
152
- *symlink = false;
535
+ *reparse = false;
153536
154537 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
155538 GFP_KERNEL);
156539 if (smb2_data == NULL)
157540 return -ENOMEM;
158541
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);
542
+ /* If it is a root and its handle is cached then use it */
543
+ if (!strlen(full_path) && !no_cached_open) {
544
+ rc = open_shroot(xid, tcon, cifs_sb, &cfid);
545
+ if (rc)
546
+ goto out;
547
+
548
+ if (tcon->crfid.file_all_info_is_valid) {
549
+ move_smb2_info_to_cifs(data,
550
+ &tcon->crfid.file_all_info);
551
+ } else {
552
+ rc = SMB2_query_info(xid, tcon,
553
+ cfid->fid->persistent_fid,
554
+ cfid->fid->volatile_fid, smb2_data);
555
+ if (!rc)
556
+ move_smb2_info_to_cifs(data, smb2_data);
557
+ }
558
+ close_shroot(cfid);
559
+ goto out;
560
+ }
561
+
562
+ cifs_get_readable_path(tcon, full_path, &cfile);
563
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
564
+ FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
565
+ ACL_NO_MODE, smb2_data, SMB2_OP_QUERY_INFO, cfile);
162566 if (rc == -EOPNOTSUPP) {
163
- *symlink = true;
567
+ *reparse = true;
568
+ create_options |= OPEN_REPARSE_POINT;
569
+
164570 /* 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);
571
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
572
+ FILE_READ_ATTRIBUTES, FILE_OPEN,
573
+ create_options, ACL_NO_MODE,
574
+ smb2_data, SMB2_OP_QUERY_INFO, NULL);
169575 }
170576 if (rc)
171577 goto out;
....@@ -176,13 +582,68 @@
176582 return rc;
177583 }
178584
585
+
179586 int
180
-smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
587
+smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
588
+ struct cifs_sb_info *cifs_sb, const char *full_path,
589
+ struct smb311_posix_qinfo *data, bool *adjust_tz, bool *reparse)
590
+{
591
+ int rc;
592
+ __u32 create_options = 0;
593
+ struct cifsFileInfo *cfile;
594
+ struct smb311_posix_qinfo *smb2_data;
595
+
596
+ *adjust_tz = false;
597
+ *reparse = false;
598
+
599
+ /* BB TODO: Make struct larger when add support for parsing owner SIDs */
600
+ smb2_data = kzalloc(sizeof(struct smb311_posix_qinfo),
601
+ GFP_KERNEL);
602
+ if (smb2_data == NULL)
603
+ return -ENOMEM;
604
+
605
+ /*
606
+ * BB TODO: Add support for using the cached root handle.
607
+ * Create SMB2_query_posix_info worker function to do non-compounded query
608
+ * when we already have an open file handle for this. For now this is fast enough
609
+ * (always using the compounded version).
610
+ */
611
+
612
+ cifs_get_readable_path(tcon, full_path, &cfile);
613
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
614
+ FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
615
+ ACL_NO_MODE, smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile);
616
+ if (rc == -EOPNOTSUPP) {
617
+ /* BB TODO: When support for special files added to Samba re-verify this path */
618
+ *reparse = true;
619
+ create_options |= OPEN_REPARSE_POINT;
620
+
621
+ /* Failed on a symbolic link - query a reparse point info */
622
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
623
+ FILE_READ_ATTRIBUTES, FILE_OPEN,
624
+ create_options, ACL_NO_MODE,
625
+ smb2_data, SMB2_OP_POSIX_QUERY_INFO, NULL);
626
+ }
627
+ if (rc)
628
+ goto out;
629
+
630
+ /* TODO: will need to allow for the 2 SIDs when add support for getting owner UID/GID */
631
+ memcpy(data, smb2_data, sizeof(struct smb311_posix_qinfo));
632
+
633
+out:
634
+ kfree(smb2_data);
635
+ return rc;
636
+}
637
+
638
+int
639
+smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
640
+ struct cifs_tcon *tcon, const char *name,
181641 struct cifs_sb_info *cifs_sb)
182642 {
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);
643
+ return smb2_compound_op(xid, tcon, cifs_sb, name,
644
+ FILE_WRITE_ATTRIBUTES, FILE_CREATE,
645
+ CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR,
646
+ NULL);
186647 }
187648
188649 void
....@@ -192,6 +653,7 @@
192653 {
193654 FILE_BASIC_INFO data;
194655 struct cifsInodeInfo *cifs_i;
656
+ struct cifsFileInfo *cfile;
195657 u32 dosattrs;
196658 int tmprc;
197659
....@@ -199,9 +661,11 @@
199661 cifs_i = CIFS_I(inode);
200662 dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
201663 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);
664
+ cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
665
+ tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
666
+ FILE_WRITE_ATTRIBUTES, FILE_CREATE,
667
+ CREATE_NOT_FILE, ACL_NO_MODE,
668
+ &data, SMB2_OP_SET_INFO, cfile);
205669 if (tmprc == 0)
206670 cifs_i->cifsAttrs = dosattrs;
207671 }
....@@ -210,24 +674,25 @@
210674 smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
211675 struct cifs_sb_info *cifs_sb)
212676 {
213
- return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
214
- CREATE_NOT_FILE,
215
- NULL, SMB2_OP_RMDIR);
677
+ return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
678
+ CREATE_NOT_FILE, ACL_NO_MODE,
679
+ NULL, SMB2_OP_RMDIR, NULL);
216680 }
217681
218682 int
219683 smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
220684 struct cifs_sb_info *cifs_sb)
221685 {
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);
686
+ return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
687
+ CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
688
+ ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL);
225689 }
226690
227691 static int
228692 smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
229693 const char *from_name, const char *to_name,
230
- struct cifs_sb_info *cifs_sb, __u32 access, int command)
694
+ struct cifs_sb_info *cifs_sb, __u32 access, int command,
695
+ struct cifsFileInfo *cfile)
231696 {
232697 __le16 *smb2_to_name = NULL;
233698 int rc;
....@@ -237,9 +702,9 @@
237702 rc = -ENOMEM;
238703 goto smb2_rename_path;
239704 }
240
-
241
- rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, access,
242
- FILE_OPEN, 0, smb2_to_name, command);
705
+ rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
706
+ FILE_OPEN, 0, ACL_NO_MODE, smb2_to_name,
707
+ command, cfile);
243708 smb2_rename_path:
244709 kfree(smb2_to_name);
245710 return rc;
....@@ -250,8 +715,12 @@
250715 const char *from_name, const char *to_name,
251716 struct cifs_sb_info *cifs_sb)
252717 {
253
- return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
254
- DELETE, SMB2_OP_RENAME);
718
+ struct cifsFileInfo *cfile;
719
+
720
+ cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
721
+
722
+ return smb2_set_path_attr(xid, tcon, from_name, to_name,
723
+ cifs_sb, DELETE, SMB2_OP_RENAME, cfile);
255724 }
256725
257726 int
....@@ -260,7 +729,8 @@
260729 struct cifs_sb_info *cifs_sb)
261730 {
262731 return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
263
- FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK);
732
+ FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK,
733
+ NULL);
264734 }
265735
266736 int
....@@ -269,9 +739,10 @@
269739 struct cifs_sb_info *cifs_sb, bool set_alloc)
270740 {
271741 __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);
742
+
743
+ return smb2_compound_op(xid, tcon, cifs_sb, full_path,
744
+ FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE,
745
+ &eof, SMB2_OP_SET_EOF, NULL);
275746 }
276747
277748 int
....@@ -291,9 +762,9 @@
291762 if (IS_ERR(tlink))
292763 return PTR_ERR(tlink);
293764
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);
765
+ rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path,
766
+ FILE_WRITE_ATTRIBUTES, FILE_OPEN,
767
+ 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, NULL);
297768 cifs_put_tlink(tlink);
298769 return rc;
299770 }