diff options
Diffstat (limited to 'fs/cifs/smb2ops.c')
-rw-r--r-- | fs/cifs/smb2ops.c | 346 |
1 files changed, 345 insertions, 1 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 826209bf3684..4d9dbe0b7385 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -17,11 +17,15 @@ | |||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/pagemap.h> | ||
21 | #include <linux/vfs.h> | ||
20 | #include "cifsglob.h" | 22 | #include "cifsglob.h" |
21 | #include "smb2pdu.h" | 23 | #include "smb2pdu.h" |
22 | #include "smb2proto.h" | 24 | #include "smb2proto.h" |
23 | #include "cifsproto.h" | 25 | #include "cifsproto.h" |
24 | #include "cifs_debug.h" | 26 | #include "cifs_debug.h" |
27 | #include "smb2status.h" | ||
28 | #include "smb2glob.h" | ||
25 | 29 | ||
26 | static int | 30 | static int |
27 | change_conf(struct TCP_Server_Info *server) | 31 | change_conf(struct TCP_Server_Info *server) |
@@ -63,6 +67,17 @@ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add, | |||
63 | server->in_flight--; | 67 | server->in_flight--; |
64 | if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP) | 68 | if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP) |
65 | rc = change_conf(server); | 69 | rc = change_conf(server); |
70 | /* | ||
71 | * Sometimes server returns 0 credits on oplock break ack - we need to | ||
72 | * rebalance credits in this case. | ||
73 | */ | ||
74 | else if (server->in_flight > 0 && server->oplock_credits == 0 && | ||
75 | server->oplocks) { | ||
76 | if (server->credits > 1) { | ||
77 | server->credits--; | ||
78 | server->oplock_credits++; | ||
79 | } | ||
80 | } | ||
66 | spin_unlock(&server->req_lock); | 81 | spin_unlock(&server->req_lock); |
67 | wake_up(&server->request_q); | 82 | wake_up(&server->request_q); |
68 | if (rc) | 83 | if (rc) |
@@ -157,6 +172,42 @@ smb2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
157 | return rc; | 172 | return rc; |
158 | } | 173 | } |
159 | 174 | ||
175 | static unsigned int | ||
176 | smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) | ||
177 | { | ||
178 | struct TCP_Server_Info *server = tcon->ses->server; | ||
179 | unsigned int wsize; | ||
180 | |||
181 | /* start with specified wsize, or default */ | ||
182 | wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE; | ||
183 | wsize = min_t(unsigned int, wsize, server->max_write); | ||
184 | /* | ||
185 | * limit write size to 2 ** 16, because we don't support multicredit | ||
186 | * requests now. | ||
187 | */ | ||
188 | wsize = min_t(unsigned int, wsize, 2 << 15); | ||
189 | |||
190 | return wsize; | ||
191 | } | ||
192 | |||
193 | static unsigned int | ||
194 | smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) | ||
195 | { | ||
196 | struct TCP_Server_Info *server = tcon->ses->server; | ||
197 | unsigned int rsize; | ||
198 | |||
199 | /* start with specified rsize, or default */ | ||
200 | rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE; | ||
201 | rsize = min_t(unsigned int, rsize, server->max_read); | ||
202 | /* | ||
203 | * limit write size to 2 ** 16, because we don't support multicredit | ||
204 | * requests now. | ||
205 | */ | ||
206 | rsize = min_t(unsigned int, rsize, 2 << 15); | ||
207 | |||
208 | return rsize; | ||
209 | } | ||
210 | |||
160 | static int | 211 | static int |
161 | smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, | 212 | smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, |
162 | struct cifs_sb_info *cifs_sb, const char *full_path) | 213 | struct cifs_sb_info *cifs_sb, const char *full_path) |
@@ -164,13 +215,14 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, | |||
164 | int rc; | 215 | int rc; |
165 | __u64 persistent_fid, volatile_fid; | 216 | __u64 persistent_fid, volatile_fid; |
166 | __le16 *utf16_path; | 217 | __le16 *utf16_path; |
218 | __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; | ||
167 | 219 | ||
168 | utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); | 220 | utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); |
169 | if (!utf16_path) | 221 | if (!utf16_path) |
170 | return -ENOMEM; | 222 | return -ENOMEM; |
171 | 223 | ||
172 | rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, | 224 | rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, |
173 | FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0); | 225 | FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL); |
174 | if (rc) { | 226 | if (rc) { |
175 | kfree(utf16_path); | 227 | kfree(utf16_path); |
176 | return rc; | 228 | return rc; |
@@ -190,6 +242,26 @@ smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon, | |||
190 | return 0; | 242 | return 0; |
191 | } | 243 | } |
192 | 244 | ||
245 | static int | ||
246 | smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, | ||
247 | struct cifs_fid *fid, FILE_ALL_INFO *data) | ||
248 | { | ||
249 | int rc; | ||
250 | struct smb2_file_all_info *smb2_data; | ||
251 | |||
252 | smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, | ||
253 | GFP_KERNEL); | ||
254 | if (smb2_data == NULL) | ||
255 | return -ENOMEM; | ||
256 | |||
257 | rc = SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid, | ||
258 | smb2_data); | ||
259 | if (!rc) | ||
260 | move_smb2_info_to_cifs(data, smb2_data); | ||
261 | kfree(smb2_data); | ||
262 | return rc; | ||
263 | } | ||
264 | |||
193 | static char * | 265 | static char * |
194 | smb2_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, | 266 | smb2_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, |
195 | struct cifs_tcon *tcon) | 267 | struct cifs_tcon *tcon) |
@@ -292,7 +364,221 @@ smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon) | |||
292 | #endif | 364 | #endif |
293 | } | 365 | } |
294 | 366 | ||
367 | static void | ||
368 | smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock) | ||
369 | { | ||
370 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | ||
371 | cfile->fid.persistent_fid = fid->persistent_fid; | ||
372 | cfile->fid.volatile_fid = fid->volatile_fid; | ||
373 | smb2_set_oplock_level(cinode, oplock); | ||
374 | cinode->can_cache_brlcks = cinode->clientCanCacheAll; | ||
375 | } | ||
376 | |||
377 | static void | ||
378 | smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon, | ||
379 | struct cifs_fid *fid) | ||
380 | { | ||
381 | SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid); | ||
382 | } | ||
383 | |||
384 | static int | ||
385 | smb2_flush_file(const unsigned int xid, struct cifs_tcon *tcon, | ||
386 | struct cifs_fid *fid) | ||
387 | { | ||
388 | return SMB2_flush(xid, tcon, fid->persistent_fid, fid->volatile_fid); | ||
389 | } | ||
390 | |||
391 | static unsigned int | ||
392 | smb2_read_data_offset(char *buf) | ||
393 | { | ||
394 | struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf; | ||
395 | return rsp->DataOffset; | ||
396 | } | ||
397 | |||
398 | static unsigned int | ||
399 | smb2_read_data_length(char *buf) | ||
400 | { | ||
401 | struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf; | ||
402 | return le32_to_cpu(rsp->DataLength); | ||
403 | } | ||
404 | |||
405 | |||
406 | static int | ||
407 | smb2_sync_read(const unsigned int xid, struct cifsFileInfo *cfile, | ||
408 | struct cifs_io_parms *parms, unsigned int *bytes_read, | ||
409 | char **buf, int *buf_type) | ||
410 | { | ||
411 | parms->persistent_fid = cfile->fid.persistent_fid; | ||
412 | parms->volatile_fid = cfile->fid.volatile_fid; | ||
413 | return SMB2_read(xid, parms, bytes_read, buf, buf_type); | ||
414 | } | ||
415 | |||
416 | static int | ||
417 | smb2_sync_write(const unsigned int xid, struct cifsFileInfo *cfile, | ||
418 | struct cifs_io_parms *parms, unsigned int *written, | ||
419 | struct kvec *iov, unsigned long nr_segs) | ||
420 | { | ||
421 | |||
422 | parms->persistent_fid = cfile->fid.persistent_fid; | ||
423 | parms->volatile_fid = cfile->fid.volatile_fid; | ||
424 | return SMB2_write(xid, parms, written, iov, nr_segs); | ||
425 | } | ||
426 | |||
427 | static int | ||
428 | smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon, | ||
429 | struct cifsFileInfo *cfile, __u64 size, bool set_alloc) | ||
430 | { | ||
431 | __le64 eof = cpu_to_le64(size); | ||
432 | return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, | ||
433 | cfile->fid.volatile_fid, cfile->pid, &eof); | ||
434 | } | ||
435 | |||
436 | static int | ||
437 | smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, | ||
438 | const char *path, struct cifs_sb_info *cifs_sb, | ||
439 | struct cifs_fid *fid, __u16 search_flags, | ||
440 | struct cifs_search_info *srch_inf) | ||
441 | { | ||
442 | __le16 *utf16_path; | ||
443 | int rc; | ||
444 | __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; | ||
445 | __u64 persistent_fid, volatile_fid; | ||
446 | |||
447 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); | ||
448 | if (!utf16_path) | ||
449 | return -ENOMEM; | ||
450 | |||
451 | rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, | ||
452 | FILE_READ_ATTRIBUTES | FILE_READ_DATA, FILE_OPEN, 0, 0, | ||
453 | &oplock, NULL); | ||
454 | kfree(utf16_path); | ||
455 | if (rc) { | ||
456 | cERROR(1, "open dir failed"); | ||
457 | return rc; | ||
458 | } | ||
459 | |||
460 | srch_inf->entries_in_buffer = 0; | ||
461 | srch_inf->index_of_last_entry = 0; | ||
462 | fid->persistent_fid = persistent_fid; | ||
463 | fid->volatile_fid = volatile_fid; | ||
464 | |||
465 | rc = SMB2_query_directory(xid, tcon, persistent_fid, volatile_fid, 0, | ||
466 | srch_inf); | ||
467 | if (rc) { | ||
468 | cERROR(1, "query directory failed"); | ||
469 | SMB2_close(xid, tcon, persistent_fid, volatile_fid); | ||
470 | } | ||
471 | return rc; | ||
472 | } | ||
473 | |||
474 | static int | ||
475 | smb2_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon, | ||
476 | struct cifs_fid *fid, __u16 search_flags, | ||
477 | struct cifs_search_info *srch_inf) | ||
478 | { | ||
479 | return SMB2_query_directory(xid, tcon, fid->persistent_fid, | ||
480 | fid->volatile_fid, 0, srch_inf); | ||
481 | } | ||
482 | |||
483 | static int | ||
484 | smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon, | ||
485 | struct cifs_fid *fid) | ||
486 | { | ||
487 | return SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid); | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * If we negotiate SMB2 protocol and get STATUS_PENDING - update | ||
492 | * the number of credits and return true. Otherwise - return false. | ||
493 | */ | ||
494 | static bool | ||
495 | smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) | ||
496 | { | ||
497 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | ||
498 | |||
499 | if (hdr->Status != STATUS_PENDING) | ||
500 | return false; | ||
501 | |||
502 | if (!length) { | ||
503 | spin_lock(&server->req_lock); | ||
504 | server->credits += le16_to_cpu(hdr->CreditRequest); | ||
505 | spin_unlock(&server->req_lock); | ||
506 | wake_up(&server->request_q); | ||
507 | } | ||
508 | |||
509 | return true; | ||
510 | } | ||
511 | |||
512 | static int | ||
513 | smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid, | ||
514 | struct cifsInodeInfo *cinode) | ||
515 | { | ||
516 | if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) | ||
517 | return SMB2_lease_break(0, tcon, cinode->lease_key, | ||
518 | smb2_get_lease_state(cinode)); | ||
519 | |||
520 | return SMB2_oplock_break(0, tcon, fid->persistent_fid, | ||
521 | fid->volatile_fid, | ||
522 | cinode->clientCanCacheRead ? 1 : 0); | ||
523 | } | ||
524 | |||
525 | static int | ||
526 | smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, | ||
527 | struct kstatfs *buf) | ||
528 | { | ||
529 | int rc; | ||
530 | u64 persistent_fid, volatile_fid; | ||
531 | __le16 srch_path = 0; /* Null - open root of share */ | ||
532 | u8 oplock = SMB2_OPLOCK_LEVEL_NONE; | ||
533 | |||
534 | rc = SMB2_open(xid, tcon, &srch_path, &persistent_fid, &volatile_fid, | ||
535 | FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL); | ||
536 | if (rc) | ||
537 | return rc; | ||
538 | buf->f_type = SMB2_MAGIC_NUMBER; | ||
539 | rc = SMB2_QFS_info(xid, tcon, persistent_fid, volatile_fid, buf); | ||
540 | SMB2_close(xid, tcon, persistent_fid, volatile_fid); | ||
541 | return rc; | ||
542 | } | ||
543 | |||
544 | static bool | ||
545 | smb2_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2) | ||
546 | { | ||
547 | return ob1->fid.persistent_fid == ob2->fid.persistent_fid && | ||
548 | ob1->fid.volatile_fid == ob2->fid.volatile_fid; | ||
549 | } | ||
550 | |||
551 | static int | ||
552 | smb2_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset, | ||
553 | __u64 length, __u32 type, int lock, int unlock, bool wait) | ||
554 | { | ||
555 | if (unlock && !lock) | ||
556 | type = SMB2_LOCKFLAG_UNLOCK; | ||
557 | return SMB2_lock(xid, tlink_tcon(cfile->tlink), | ||
558 | cfile->fid.persistent_fid, cfile->fid.volatile_fid, | ||
559 | current->tgid, length, offset, type, wait); | ||
560 | } | ||
561 | |||
562 | static void | ||
563 | smb2_get_lease_key(struct inode *inode, struct cifs_fid *fid) | ||
564 | { | ||
565 | memcpy(fid->lease_key, CIFS_I(inode)->lease_key, SMB2_LEASE_KEY_SIZE); | ||
566 | } | ||
567 | |||
568 | static void | ||
569 | smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid) | ||
570 | { | ||
571 | memcpy(CIFS_I(inode)->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE); | ||
572 | } | ||
573 | |||
574 | static void | ||
575 | smb2_new_lease_key(struct cifs_fid *fid) | ||
576 | { | ||
577 | get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE); | ||
578 | } | ||
579 | |||
295 | struct smb_version_operations smb21_operations = { | 580 | struct smb_version_operations smb21_operations = { |
581 | .compare_fids = smb2_compare_fids, | ||
296 | .setup_request = smb2_setup_request, | 582 | .setup_request = smb2_setup_request, |
297 | .setup_async_request = smb2_setup_async_request, | 583 | .setup_async_request = smb2_setup_async_request, |
298 | .check_receive = smb2_check_receive, | 584 | .check_receive = smb2_check_receive, |
@@ -301,13 +587,19 @@ struct smb_version_operations smb21_operations = { | |||
301 | .get_credits_field = smb2_get_credits_field, | 587 | .get_credits_field = smb2_get_credits_field, |
302 | .get_credits = smb2_get_credits, | 588 | .get_credits = smb2_get_credits, |
303 | .get_next_mid = smb2_get_next_mid, | 589 | .get_next_mid = smb2_get_next_mid, |
590 | .read_data_offset = smb2_read_data_offset, | ||
591 | .read_data_length = smb2_read_data_length, | ||
592 | .map_error = map_smb2_to_linux_error, | ||
304 | .find_mid = smb2_find_mid, | 593 | .find_mid = smb2_find_mid, |
305 | .check_message = smb2_check_message, | 594 | .check_message = smb2_check_message, |
306 | .dump_detail = smb2_dump_detail, | 595 | .dump_detail = smb2_dump_detail, |
307 | .clear_stats = smb2_clear_stats, | 596 | .clear_stats = smb2_clear_stats, |
308 | .print_stats = smb2_print_stats, | 597 | .print_stats = smb2_print_stats, |
598 | .is_oplock_break = smb2_is_valid_oplock_break, | ||
309 | .need_neg = smb2_need_neg, | 599 | .need_neg = smb2_need_neg, |
310 | .negotiate = smb2_negotiate, | 600 | .negotiate = smb2_negotiate, |
601 | .negotiate_wsize = smb2_negotiate_wsize, | ||
602 | .negotiate_rsize = smb2_negotiate_rsize, | ||
311 | .sess_setup = SMB2_sess_setup, | 603 | .sess_setup = SMB2_sess_setup, |
312 | .logoff = SMB2_logoff, | 604 | .logoff = SMB2_logoff, |
313 | .tree_connect = SMB2_tcon, | 605 | .tree_connect = SMB2_tcon, |
@@ -317,16 +609,68 @@ struct smb_version_operations smb21_operations = { | |||
317 | .echo = SMB2_echo, | 609 | .echo = SMB2_echo, |
318 | .query_path_info = smb2_query_path_info, | 610 | .query_path_info = smb2_query_path_info, |
319 | .get_srv_inum = smb2_get_srv_inum, | 611 | .get_srv_inum = smb2_get_srv_inum, |
612 | .query_file_info = smb2_query_file_info, | ||
613 | .set_path_size = smb2_set_path_size, | ||
614 | .set_file_size = smb2_set_file_size, | ||
615 | .set_file_info = smb2_set_file_info, | ||
320 | .build_path_to_root = smb2_build_path_to_root, | 616 | .build_path_to_root = smb2_build_path_to_root, |
321 | .mkdir = smb2_mkdir, | 617 | .mkdir = smb2_mkdir, |
322 | .mkdir_setinfo = smb2_mkdir_setinfo, | 618 | .mkdir_setinfo = smb2_mkdir_setinfo, |
323 | .rmdir = smb2_rmdir, | 619 | .rmdir = smb2_rmdir, |
620 | .unlink = smb2_unlink, | ||
621 | .rename = smb2_rename_path, | ||
622 | .create_hardlink = smb2_create_hardlink, | ||
623 | .open = smb2_open_file, | ||
624 | .set_fid = smb2_set_fid, | ||
625 | .close = smb2_close_file, | ||
626 | .flush = smb2_flush_file, | ||
627 | .async_readv = smb2_async_readv, | ||
628 | .async_writev = smb2_async_writev, | ||
629 | .sync_read = smb2_sync_read, | ||
630 | .sync_write = smb2_sync_write, | ||
631 | .query_dir_first = smb2_query_dir_first, | ||
632 | .query_dir_next = smb2_query_dir_next, | ||
633 | .close_dir = smb2_close_dir, | ||
634 | .calc_smb_size = smb2_calc_size, | ||
635 | .is_status_pending = smb2_is_status_pending, | ||
636 | .oplock_response = smb2_oplock_response, | ||
637 | .queryfs = smb2_queryfs, | ||
638 | .mand_lock = smb2_mand_lock, | ||
639 | .mand_unlock_range = smb2_unlock_range, | ||
640 | .push_mand_locks = smb2_push_mandatory_locks, | ||
641 | .get_lease_key = smb2_get_lease_key, | ||
642 | .set_lease_key = smb2_set_lease_key, | ||
643 | .new_lease_key = smb2_new_lease_key, | ||
324 | }; | 644 | }; |
325 | 645 | ||
326 | struct smb_version_values smb21_values = { | 646 | struct smb_version_values smb21_values = { |
327 | .version_string = SMB21_VERSION_STRING, | 647 | .version_string = SMB21_VERSION_STRING, |
648 | .protocol_id = SMB21_PROT_ID, | ||
649 | .req_capabilities = 0, /* MBZ on negotiate req until SMB3 dialect */ | ||
650 | .large_lock_type = 0, | ||
651 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | ||
652 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | ||
653 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | ||
654 | .header_size = sizeof(struct smb2_hdr), | ||
655 | .max_header_size = MAX_SMB2_HDR_SIZE, | ||
656 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | ||
657 | .lock_cmd = SMB2_LOCK, | ||
658 | .cap_unix = 0, | ||
659 | .cap_nt_find = SMB2_NT_FIND, | ||
660 | .cap_large_files = SMB2_LARGE_FILES, | ||
661 | }; | ||
662 | |||
663 | struct smb_version_values smb30_values = { | ||
664 | .version_string = SMB30_VERSION_STRING, | ||
665 | .protocol_id = SMB30_PROT_ID, | ||
666 | .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU, | ||
667 | .large_lock_type = 0, | ||
668 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | ||
669 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | ||
670 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | ||
328 | .header_size = sizeof(struct smb2_hdr), | 671 | .header_size = sizeof(struct smb2_hdr), |
329 | .max_header_size = MAX_SMB2_HDR_SIZE, | 672 | .max_header_size = MAX_SMB2_HDR_SIZE, |
673 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | ||
330 | .lock_cmd = SMB2_LOCK, | 674 | .lock_cmd = SMB2_LOCK, |
331 | .cap_unix = 0, | 675 | .cap_unix = 0, |
332 | .cap_nt_find = SMB2_NT_FIND, | 676 | .cap_nt_find = SMB2_NT_FIND, |