Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

CIFS: Store lease state itself rather than a mapped oplock value

and separate smb20_operations struct.

Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: Steve French <smfrench@gmail.com>

authored by

Pavel Shilovsky and committed by
Steve French
53ef1016 18cceb6a

+174 -62
+9 -7
fs/cifs/cifsglob.h
··· 367 367 /* generate new lease key */ 368 368 void (*new_lease_key)(struct cifs_fid *fid); 369 369 int (*generate_signingkey)(struct cifs_ses *); 370 - int (*calc_signature)(struct smb_rqst *rqst, 371 - struct TCP_Server_Info *server); 372 - int (*query_mf_symlink)(const unsigned char *path, char *pbuf, 373 - unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, 374 - unsigned int xid); 370 + int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); 371 + int (*query_mf_symlink)(const unsigned char *, char *, unsigned int *, 372 + struct cifs_sb_info *, unsigned int); 373 + /* if we can do cache read operations */ 374 + bool (*is_read_op)(__u32); 375 + /* set oplock level for the inode */ 376 + void (*set_oplock_level)(struct cifsInodeInfo *, __u32); 375 377 }; 376 378 377 379 struct smb_version_values { ··· 391 389 unsigned int cap_unix; 392 390 unsigned int cap_nt_find; 393 391 unsigned int cap_large_files; 394 - unsigned int oplock_read; 395 392 __u16 signing_enabled; 396 393 __u16 signing_required; 397 394 }; ··· 1037 1036 #define CIFS_CACHE_WRITE_FLG 4 1038 1037 1039 1038 #define CIFS_CACHE_READ(cinode) (cinode->oplock & CIFS_CACHE_READ_FLG) 1039 + #define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG) 1040 1040 #define CIFS_CACHE_WRITE(cinode) (cinode->oplock & CIFS_CACHE_WRITE_FLG) 1041 1041 1042 1042 /* ··· 1509 1507 extern struct smb_version_operations smb1_operations; 1510 1508 extern struct smb_version_values smb1_values; 1511 1509 #define SMB20_VERSION_STRING "2.0" 1512 - /*extern struct smb_version_operations smb20_operations; */ /* not needed yet */ 1510 + extern struct smb_version_operations smb20_operations; 1513 1511 extern struct smb_version_values smb20_values; 1514 1512 #define SMB21_VERSION_STRING "2.1" 1515 1513 extern struct smb_version_operations smb21_operations;
+1 -1
fs/cifs/connect.c
··· 1116 1116 break; 1117 1117 #ifdef CONFIG_CIFS_SMB2 1118 1118 case Smb_20: 1119 - vol->ops = &smb21_operations; /* currently identical with 2.1 */ 1119 + vol->ops = &smb20_operations; 1120 1120 vol->vals = &smb20_values; 1121 1121 break; 1122 1122 case Smb_21:
+1 -2
fs/cifs/file.c
··· 313 313 * If the server returned a read oplock and we have mandatory brlocks, 314 314 * set oplock level to None. 315 315 */ 316 - if (oplock == server->vals->oplock_read && 317 - cifs_has_mand_locks(cinode)) { 316 + if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) { 318 317 cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n"); 319 318 oplock = 0; 320 319 }
+7 -1
fs/cifs/smb1ops.c
··· 912 912 return rc; 913 913 } 914 914 915 + static bool 916 + cifs_is_read_op(__u32 oplock) 917 + { 918 + return oplock == OPLOCK_READ; 919 + } 920 + 915 921 struct smb_version_operations smb1_operations = { 916 922 .send_cancel = send_nt_cancel, 917 923 .compare_fids = cifs_compare_fids, ··· 983 977 .mand_unlock_range = cifs_unlock_range, 984 978 .push_mand_locks = cifs_push_mandatory_locks, 985 979 .query_mf_symlink = open_query_close_cifs_symlink, 980 + .is_read_op = cifs_is_read_op, 986 981 }; 987 982 988 983 struct smb_version_values smb1_values = { ··· 999 992 .cap_unix = CAP_UNIX, 1000 993 .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND, 1001 994 .cap_large_files = CAP_LARGE_FILES, 1002 - .oplock_read = OPLOCK_READ, 1003 995 .signing_enabled = SECMODE_SIGN_ENABLED, 1004 996 .signing_required = SECMODE_SIGN_REQUIRED, 1005 997 };
-23
fs/cifs/smb2file.c
··· 34 34 #include "fscache.h" 35 35 #include "smb2proto.h" 36 36 37 - void 38 - smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) 39 - { 40 - oplock &= 0xFF; 41 - if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) 42 - return; 43 - if (oplock == SMB2_OPLOCK_LEVEL_BATCH) { 44 - cinode->oplock = CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG | 45 - CIFS_CACHE_HANDLE_FLG; 46 - cifs_dbg(FYI, "Batch Oplock granted on inode %p\n", 47 - &cinode->vfs_inode); 48 - } else if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) { 49 - cinode->oplock = CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG; 50 - cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n", 51 - &cinode->vfs_inode); 52 - } else if (oplock == SMB2_OPLOCK_LEVEL_II) { 53 - cinode->oplock = CIFS_CACHE_READ_FLG; 54 - cifs_dbg(FYI, "Level II Oplock granted on inode %p\n", 55 - &cinode->vfs_inode); 56 - } else 57 - cinode->oplock = 0; 58 - } 59 - 60 37 int 61 38 smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, 62 39 __u32 *oplock, FILE_ALL_INFO *buf)
+11 -19
fs/cifs/smb2misc.c
··· 380 380 __le32 381 381 smb2_get_lease_state(struct cifsInodeInfo *cinode) 382 382 { 383 - if (CIFS_CACHE_WRITE(cinode)) 384 - return SMB2_LEASE_WRITE_CACHING | SMB2_LEASE_READ_CACHING; 385 - else if (CIFS_CACHE_READ(cinode)) 386 - return SMB2_LEASE_READ_CACHING; 387 - return 0; 388 - } 383 + __le32 lease = 0; 389 384 390 - __u8 smb2_map_lease_to_oplock(__le32 lease_state) 391 - { 392 - if (lease_state & SMB2_LEASE_WRITE_CACHING) { 393 - if (lease_state & SMB2_LEASE_HANDLE_CACHING) 394 - return SMB2_OPLOCK_LEVEL_BATCH; 395 - else 396 - return SMB2_OPLOCK_LEVEL_EXCLUSIVE; 397 - } else if (lease_state & SMB2_LEASE_READ_CACHING) 398 - return SMB2_OPLOCK_LEVEL_II; 399 - return 0; 385 + if (CIFS_CACHE_WRITE(cinode)) 386 + lease |= SMB2_LEASE_WRITE_CACHING; 387 + if (CIFS_CACHE_HANDLE(cinode)) 388 + lease |= SMB2_LEASE_HANDLE_CACHING; 389 + if (CIFS_CACHE_READ(cinode)) 390 + lease |= SMB2_LEASE_READ_CACHING; 391 + return lease; 400 392 } 401 393 402 394 struct smb2_lease_break_work { ··· 425 433 int ack_req = le32_to_cpu(rsp->Flags & 426 434 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED); 427 435 428 - lease_state = smb2_map_lease_to_oplock(rsp->NewLeaseState); 436 + lease_state = le32_to_cpu(rsp->NewLeaseState); 429 437 430 438 list_for_each(tmp, &tcon->openFileList) { 431 439 cfile = list_entry(tmp, struct cifsFileInfo, tlist); ··· 439 447 cifs_dbg(FYI, "lease key match, lease break 0x%d\n", 440 448 le32_to_cpu(rsp->NewLeaseState)); 441 449 442 - smb2_set_oplock_level(cinode, lease_state); 450 + tcon->ses->server->ops->set_oplock_level(cinode, lease_state); 443 451 444 452 if (ack_req) 445 453 cfile->oplock_break_cancelled = false; ··· 574 582 else 575 583 cfile->oplock_break_cancelled = false; 576 584 577 - smb2_set_oplock_level(cinode, 585 + server->ops->set_oplock_level(cinode, 578 586 rsp->OplockLevel ? SMB2_OPLOCK_LEVEL_II : 0); 579 587 580 588 queue_work(cifsiod_wq, &cfile->oplock_break);
+140 -6
fs/cifs/smb2ops.c
··· 377 377 smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock) 378 378 { 379 379 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); 380 + struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; 381 + 380 382 cfile->fid.persistent_fid = fid->persistent_fid; 381 383 cfile->fid.volatile_fid = fid->volatile_fid; 382 - smb2_set_oplock_level(cinode, oplock); 384 + server->ops->set_oplock_level(cinode, oplock); 383 385 cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode); 384 386 } 385 387 ··· 650 648 return rc; 651 649 } 652 650 651 + static void 652 + smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) 653 + { 654 + oplock &= 0xFF; 655 + if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) 656 + return; 657 + if (oplock == SMB2_OPLOCK_LEVEL_BATCH) { 658 + cinode->oplock = CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG | 659 + CIFS_CACHE_HANDLE_FLG; 660 + cifs_dbg(FYI, "Batch Oplock granted on inode %p\n", 661 + &cinode->vfs_inode); 662 + } else if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) { 663 + cinode->oplock = CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG; 664 + cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n", 665 + &cinode->vfs_inode); 666 + } else if (oplock == SMB2_OPLOCK_LEVEL_II) { 667 + cinode->oplock = CIFS_CACHE_READ_FLG; 668 + cifs_dbg(FYI, "Level II Oplock granted on inode %p\n", 669 + &cinode->vfs_inode); 670 + } else 671 + cinode->oplock = 0; 672 + } 673 + 674 + static void 675 + smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) 676 + { 677 + char message[5] = {0}; 678 + 679 + oplock &= 0xFF; 680 + if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) 681 + return; 682 + 683 + cinode->oplock = 0; 684 + if (oplock & SMB2_LEASE_READ_CACHING_HE) { 685 + cinode->oplock |= CIFS_CACHE_READ_FLG; 686 + strcat(message, "R"); 687 + } 688 + if (oplock & SMB2_LEASE_HANDLE_CACHING_HE) { 689 + cinode->oplock |= CIFS_CACHE_HANDLE_FLG; 690 + strcat(message, "H"); 691 + } 692 + if (oplock & SMB2_LEASE_WRITE_CACHING_HE) { 693 + cinode->oplock |= CIFS_CACHE_WRITE_FLG; 694 + strcat(message, "W"); 695 + } 696 + if (!cinode->oplock) 697 + strcat(message, "None"); 698 + cifs_dbg(FYI, "%s Lease granted on inode %p\n", message, 699 + &cinode->vfs_inode); 700 + } 701 + 702 + static bool 703 + smb2_is_read_op(__u32 oplock) 704 + { 705 + return oplock == SMB2_OPLOCK_LEVEL_II; 706 + } 707 + 708 + static bool 709 + smb21_is_read_op(__u32 oplock) 710 + { 711 + return (oplock & SMB2_LEASE_READ_CACHING_HE) && 712 + !(oplock & SMB2_LEASE_WRITE_CACHING_HE); 713 + } 714 + 715 + struct smb_version_operations smb20_operations = { 716 + .compare_fids = smb2_compare_fids, 717 + .setup_request = smb2_setup_request, 718 + .setup_async_request = smb2_setup_async_request, 719 + .check_receive = smb2_check_receive, 720 + .add_credits = smb2_add_credits, 721 + .set_credits = smb2_set_credits, 722 + .get_credits_field = smb2_get_credits_field, 723 + .get_credits = smb2_get_credits, 724 + .get_next_mid = smb2_get_next_mid, 725 + .read_data_offset = smb2_read_data_offset, 726 + .read_data_length = smb2_read_data_length, 727 + .map_error = map_smb2_to_linux_error, 728 + .find_mid = smb2_find_mid, 729 + .check_message = smb2_check_message, 730 + .dump_detail = smb2_dump_detail, 731 + .clear_stats = smb2_clear_stats, 732 + .print_stats = smb2_print_stats, 733 + .is_oplock_break = smb2_is_valid_oplock_break, 734 + .need_neg = smb2_need_neg, 735 + .negotiate = smb2_negotiate, 736 + .negotiate_wsize = smb2_negotiate_wsize, 737 + .negotiate_rsize = smb2_negotiate_rsize, 738 + .sess_setup = SMB2_sess_setup, 739 + .logoff = SMB2_logoff, 740 + .tree_connect = SMB2_tcon, 741 + .tree_disconnect = SMB2_tdis, 742 + .is_path_accessible = smb2_is_path_accessible, 743 + .can_echo = smb2_can_echo, 744 + .echo = SMB2_echo, 745 + .query_path_info = smb2_query_path_info, 746 + .get_srv_inum = smb2_get_srv_inum, 747 + .query_file_info = smb2_query_file_info, 748 + .set_path_size = smb2_set_path_size, 749 + .set_file_size = smb2_set_file_size, 750 + .set_file_info = smb2_set_file_info, 751 + .mkdir = smb2_mkdir, 752 + .mkdir_setinfo = smb2_mkdir_setinfo, 753 + .rmdir = smb2_rmdir, 754 + .unlink = smb2_unlink, 755 + .rename = smb2_rename_path, 756 + .create_hardlink = smb2_create_hardlink, 757 + .query_symlink = smb2_query_symlink, 758 + .open = smb2_open_file, 759 + .set_fid = smb2_set_fid, 760 + .close = smb2_close_file, 761 + .flush = smb2_flush_file, 762 + .async_readv = smb2_async_readv, 763 + .async_writev = smb2_async_writev, 764 + .sync_read = smb2_sync_read, 765 + .sync_write = smb2_sync_write, 766 + .query_dir_first = smb2_query_dir_first, 767 + .query_dir_next = smb2_query_dir_next, 768 + .close_dir = smb2_close_dir, 769 + .calc_smb_size = smb2_calc_size, 770 + .is_status_pending = smb2_is_status_pending, 771 + .oplock_response = smb2_oplock_response, 772 + .queryfs = smb2_queryfs, 773 + .mand_lock = smb2_mand_lock, 774 + .mand_unlock_range = smb2_unlock_range, 775 + .push_mand_locks = smb2_push_mandatory_locks, 776 + .get_lease_key = smb2_get_lease_key, 777 + .set_lease_key = smb2_set_lease_key, 778 + .new_lease_key = smb2_new_lease_key, 779 + .calc_signature = smb2_calc_signature, 780 + .is_read_op = smb2_is_read_op, 781 + .set_oplock_level = smb2_set_oplock_level, 782 + }; 783 + 653 784 struct smb_version_operations smb21_operations = { 654 785 .compare_fids = smb2_compare_fids, 655 786 .setup_request = smb2_setup_request, ··· 848 713 .set_lease_key = smb2_set_lease_key, 849 714 .new_lease_key = smb2_new_lease_key, 850 715 .calc_signature = smb2_calc_signature, 716 + .is_read_op = smb21_is_read_op, 717 + .set_oplock_level = smb21_set_oplock_level, 851 718 }; 852 - 853 719 854 720 struct smb_version_operations smb30_operations = { 855 721 .compare_fids = smb2_compare_fids, ··· 919 783 .new_lease_key = smb2_new_lease_key, 920 784 .generate_signingkey = generate_smb3signingkey, 921 785 .calc_signature = smb3_calc_signature, 786 + .is_read_op = smb21_is_read_op, 787 + .set_oplock_level = smb21_set_oplock_level, 922 788 }; 923 789 924 790 struct smb_version_values smb20_values = { ··· 938 800 .cap_unix = 0, 939 801 .cap_nt_find = SMB2_NT_FIND, 940 802 .cap_large_files = SMB2_LARGE_FILES, 941 - .oplock_read = SMB2_OPLOCK_LEVEL_II, 942 803 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, 943 804 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, 944 805 }; ··· 957 820 .cap_unix = 0, 958 821 .cap_nt_find = SMB2_NT_FIND, 959 822 .cap_large_files = SMB2_LARGE_FILES, 960 - .oplock_read = SMB2_OPLOCK_LEVEL_II, 961 823 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, 962 824 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, 963 825 }; ··· 976 840 .cap_unix = 0, 977 841 .cap_nt_find = SMB2_NT_FIND, 978 842 .cap_large_files = SMB2_LARGE_FILES, 979 - .oplock_read = SMB2_OPLOCK_LEVEL_II, 980 843 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, 981 844 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, 982 845 }; ··· 995 860 .cap_unix = 0, 996 861 .cap_nt_find = SMB2_NT_FIND, 997 862 .cap_large_files = SMB2_LARGE_FILES, 998 - .oplock_read = SMB2_OPLOCK_LEVEL_II, 999 863 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, 1000 864 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, 1001 865 };
+1 -1
fs/cifs/smb2pdu.c
··· 963 963 if (!found) 964 964 return 0; 965 965 966 - return smb2_map_lease_to_oplock(lc->lcontext.LeaseState); 966 + return le32_to_cpu(lc->lcontext.LeaseState); 967 967 } 968 968 969 969 static int
+4
fs/cifs/smb2pdu.h
··· 476 476 __u8 Buffer[0]; 477 477 } __packed; 478 478 479 + #define SMB2_LEASE_READ_CACHING_HE 0x01 480 + #define SMB2_LEASE_HANDLE_CACHING_HE 0x02 481 + #define SMB2_LEASE_WRITE_CACHING_HE 0x04 482 + 479 483 #define SMB2_LEASE_NONE __constant_cpu_to_le32(0x00) 480 484 #define SMB2_LEASE_READ_CACHING __constant_cpu_to_le32(0x01) 481 485 #define SMB2_LEASE_HANDLE_CACHING __constant_cpu_to_le32(0x02)
-2
fs/cifs/smb2proto.h
··· 53 53 struct TCP_Server_Info *server); 54 54 extern void smb2_echo_request(struct work_struct *work); 55 55 extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode); 56 - extern __u8 smb2_map_lease_to_oplock(__le32 lease_state); 57 56 extern bool smb2_is_valid_oplock_break(char *buffer, 58 57 struct TCP_Server_Info *srv); 59 58 ··· 86 87 extern int smb2_open_file(const unsigned int xid, 87 88 struct cifs_open_parms *oparms, 88 89 __u32 *oplock, FILE_ALL_INFO *buf); 89 - extern void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock); 90 90 extern int smb2_unlock_range(struct cifsFileInfo *cfile, 91 91 struct file_lock *flock, const unsigned int xid); 92 92 extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);