diff options
| -rw-r--r-- | fs/cifs/CHANGES | 3 | ||||
| -rw-r--r-- | fs/cifs/README | 16 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 41 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 1 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 8 |
5 files changed, 67 insertions, 2 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index a7255751ffbc..8f528ea24c48 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
| @@ -3,7 +3,8 @@ Version 1.55 | |||
| 3 | Various fixes to make delete of open files behavior more predictable | 3 | Various fixes to make delete of open files behavior more predictable |
| 4 | (when delete of an open file fails we mark the file as "delete-on-close" | 4 | (when delete of an open file fails we mark the file as "delete-on-close" |
| 5 | in a way that more servers accept, but only if we can first rename the | 5 | in a way that more servers accept, but only if we can first rename the |
| 6 | file to a temporary name) | 6 | file to a temporary name). Add experimental support for more safely |
| 7 | handling fcntl(F_SETLEASE). | ||
| 7 | 8 | ||
| 8 | Version 1.54 | 9 | Version 1.54 |
| 9 | ------------ | 10 | ------------ |
diff --git a/fs/cifs/README b/fs/cifs/README index cbe26fe40120..a439dc1739b3 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
| @@ -491,6 +491,19 @@ A partial list of the supported mount options follows: | |||
| 491 | Note that this differs from the sign mount option in that it | 491 | Note that this differs from the sign mount option in that it |
| 492 | causes encryption of data sent over this mounted share but other | 492 | causes encryption of data sent over this mounted share but other |
| 493 | shares mounted to the same server are unaffected. | 493 | shares mounted to the same server are unaffected. |
| 494 | locallease This option is rarely needed. Fcntl F_SETLEASE is | ||
| 495 | used by some applications such as Samba and NFSv4 server to | ||
| 496 | check to see whether a file is cacheable. CIFS has no way | ||
| 497 | to explicitly request a lease, but can check whether a file | ||
| 498 | is cacheable (oplocked). Unfortunately, even if a file | ||
| 499 | is not oplocked, it could still be cacheable (ie cifs client | ||
| 500 | could grant fcntl leases if no other local processes are using | ||
| 501 | the file) for cases for example such as when the server does not | ||
| 502 | support oplocks and the user is sure that the only updates to | ||
| 503 | the file will be from this client. Specifying this mount option | ||
| 504 | will allow the cifs client to check for leases (only) locally | ||
| 505 | for files which are not oplocked instead of denying leases | ||
| 506 | in that case. (EXPERIMENTAL) | ||
| 494 | sec Security mode. Allowed values are: | 507 | sec Security mode. Allowed values are: |
| 495 | none attempt to connection as a null user (no name) | 508 | none attempt to connection as a null user (no name) |
| 496 | krb5 Use Kerberos version 5 authentication | 509 | krb5 Use Kerberos version 5 authentication |
| @@ -641,6 +654,9 @@ requires enabling CONFIG_CIFS_EXPERIMENTAL | |||
| 641 | cifsacl support needed to retrieve approximated mode bits based on | 654 | cifsacl support needed to retrieve approximated mode bits based on |
| 642 | the contents on the CIFS ACL. | 655 | the contents on the CIFS ACL. |
| 643 | 656 | ||
| 657 | lease support: cifs will check the oplock state before calling into | ||
| 658 | the vfs to see if we can grant a lease on a file. | ||
| 659 | |||
| 644 | DNOTIFY fcntl: needed for support of directory change | 660 | DNOTIFY fcntl: needed for support of directory change |
| 645 | notification and perhaps later for file leases) | 661 | notification and perhaps later for file leases) |
| 646 | 662 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index c6aad775dd6d..76919c25acc7 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -618,6 +618,37 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) | |||
| 618 | return generic_file_llseek_unlocked(file, offset, origin); | 618 | return generic_file_llseek_unlocked(file, offset, origin); |
| 619 | } | 619 | } |
| 620 | 620 | ||
| 621 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 622 | static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) | ||
| 623 | { | ||
| 624 | /* note that this is called by vfs setlease with the BKL held | ||
| 625 | although I doubt that BKL is needed here in cifs */ | ||
| 626 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 627 | |||
| 628 | if (!(S_ISREG(inode->i_mode))) | ||
| 629 | return -EINVAL; | ||
| 630 | |||
| 631 | /* check if file is oplocked */ | ||
| 632 | if (((arg == F_RDLCK) && | ||
| 633 | (CIFS_I(inode)->clientCanCacheRead)) || | ||
| 634 | ((arg == F_WRLCK) && | ||
| 635 | (CIFS_I(inode)->clientCanCacheAll))) | ||
| 636 | return generic_setlease(file, arg, lease); | ||
| 637 | else if (CIFS_SB(inode->i_sb)->tcon->local_lease && | ||
| 638 | !CIFS_I(inode)->clientCanCacheRead) | ||
| 639 | /* If the server claims to support oplock on this | ||
| 640 | file, then we still need to check oplock even | ||
| 641 | if the local_lease mount option is set, but there | ||
| 642 | are servers which do not support oplock for which | ||
| 643 | this mount option may be useful if the user | ||
| 644 | knows that the file won't be changed on the server | ||
| 645 | by anyone else */ | ||
| 646 | return generic_setlease(file, arg, lease); | ||
| 647 | else | ||
| 648 | return -EAGAIN; | ||
| 649 | } | ||
| 650 | #endif | ||
| 651 | |||
| 621 | struct file_system_type cifs_fs_type = { | 652 | struct file_system_type cifs_fs_type = { |
| 622 | .owner = THIS_MODULE, | 653 | .owner = THIS_MODULE, |
| 623 | .name = "cifs", | 654 | .name = "cifs", |
| @@ -696,6 +727,7 @@ const struct file_operations cifs_file_ops = { | |||
| 696 | 727 | ||
| 697 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 728 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 698 | .dir_notify = cifs_dir_notify, | 729 | .dir_notify = cifs_dir_notify, |
| 730 | .setlease = cifs_setlease, | ||
| 699 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 731 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 700 | }; | 732 | }; |
| 701 | 733 | ||
| @@ -716,6 +748,7 @@ const struct file_operations cifs_file_direct_ops = { | |||
| 716 | .llseek = cifs_llseek, | 748 | .llseek = cifs_llseek, |
| 717 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 749 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 718 | .dir_notify = cifs_dir_notify, | 750 | .dir_notify = cifs_dir_notify, |
| 751 | .setlease = cifs_setlease, | ||
| 719 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 752 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 720 | }; | 753 | }; |
| 721 | const struct file_operations cifs_file_nobrl_ops = { | 754 | const struct file_operations cifs_file_nobrl_ops = { |
| @@ -736,6 +769,7 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
| 736 | 769 | ||
| 737 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 770 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 738 | .dir_notify = cifs_dir_notify, | 771 | .dir_notify = cifs_dir_notify, |
| 772 | .setlease = cifs_setlease, | ||
| 739 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 773 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 740 | }; | 774 | }; |
| 741 | 775 | ||
| @@ -755,6 +789,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { | |||
| 755 | .llseek = cifs_llseek, | 789 | .llseek = cifs_llseek, |
| 756 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 790 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 757 | .dir_notify = cifs_dir_notify, | 791 | .dir_notify = cifs_dir_notify, |
| 792 | .setlease = cifs_setlease, | ||
| 758 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 793 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 759 | }; | 794 | }; |
| 760 | 795 | ||
| @@ -946,6 +981,12 @@ static int cifs_oplock_thread(void *dummyarg) | |||
| 946 | the call */ | 981 | the call */ |
| 947 | /* mutex_lock(&inode->i_mutex);*/ | 982 | /* mutex_lock(&inode->i_mutex);*/ |
| 948 | if (S_ISREG(inode->i_mode)) { | 983 | if (S_ISREG(inode->i_mode)) { |
| 984 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 985 | if (CIFS_I(inode)->clientCanCacheAll == 0) | ||
| 986 | break_lease(inode, FMODE_READ); | ||
| 987 | else if (CIFS_I(inode)->clientCanCacheRead == 0) | ||
| 988 | break_lease(inode, FMODE_WRITE); | ||
| 989 | #endif | ||
| 949 | rc = filemap_fdatawrite(inode->i_mapping); | 990 | rc = filemap_fdatawrite(inode->i_mapping); |
| 950 | if (CIFS_I(inode)->clientCanCacheRead == 0) { | 991 | if (CIFS_I(inode)->clientCanCacheRead == 0) { |
| 951 | waitrc = filemap_fdatawait( | 992 | waitrc = filemap_fdatawait( |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 178f733a368f..c791e5b5a914 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -285,6 +285,7 @@ struct cifsTconInfo { | |||
| 285 | bool seal:1; /* transport encryption for this mounted share */ | 285 | bool seal:1; /* transport encryption for this mounted share */ |
| 286 | bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol | 286 | bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol |
| 287 | for this mount even if server would support */ | 287 | for this mount even if server would support */ |
| 288 | bool local_lease:1; /* check leases (only) on local system not remote */ | ||
| 288 | /* BB add field for back pointer to sb struct(s)? */ | 289 | /* BB add field for back pointer to sb struct(s)? */ |
| 289 | }; | 290 | }; |
| 290 | 291 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 1126f7ab4606..f51b79a67e1b 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -90,7 +90,8 @@ struct smb_vol { | |||
| 90 | bool nocase:1; /* request case insensitive filenames */ | 90 | bool nocase:1; /* request case insensitive filenames */ |
| 91 | bool nobrl:1; /* disable sending byte range locks to srv */ | 91 | bool nobrl:1; /* disable sending byte range locks to srv */ |
| 92 | bool seal:1; /* request transport encryption on share */ | 92 | bool seal:1; /* request transport encryption on share */ |
| 93 | bool nodfs:1; | 93 | bool nodfs:1; /* Do not request DFS, even if available */ |
| 94 | bool local_lease:1; /* check leases only on local system, not remote */ | ||
| 94 | unsigned int rsize; | 95 | unsigned int rsize; |
| 95 | unsigned int wsize; | 96 | unsigned int wsize; |
| 96 | unsigned int sockopt; | 97 | unsigned int sockopt; |
| @@ -1264,6 +1265,10 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1264 | vol->no_psx_acl = 0; | 1265 | vol->no_psx_acl = 0; |
| 1265 | } else if (strnicmp(data, "noacl", 5) == 0) { | 1266 | } else if (strnicmp(data, "noacl", 5) == 0) { |
| 1266 | vol->no_psx_acl = 1; | 1267 | vol->no_psx_acl = 1; |
| 1268 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 1269 | } else if (strnicmp(data, "locallease", 6) == 0) { | ||
| 1270 | vol->local_lease = 1; | ||
| 1271 | #endif | ||
| 1267 | } else if (strnicmp(data, "sign", 4) == 0) { | 1272 | } else if (strnicmp(data, "sign", 4) == 0) { |
| 1268 | vol->secFlg |= CIFSSEC_MUST_SIGN; | 1273 | vol->secFlg |= CIFSSEC_MUST_SIGN; |
| 1269 | } else if (strnicmp(data, "seal", 4) == 0) { | 1274 | } else if (strnicmp(data, "seal", 4) == 0) { |
| @@ -2162,6 +2167,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2162 | for the retry flag is used */ | 2167 | for the retry flag is used */ |
| 2163 | tcon->retry = volume_info.retry; | 2168 | tcon->retry = volume_info.retry; |
| 2164 | tcon->nocase = volume_info.nocase; | 2169 | tcon->nocase = volume_info.nocase; |
| 2170 | tcon->local_lease = volume_info.local_lease; | ||
| 2165 | if (tcon->seal != volume_info.seal) | 2171 | if (tcon->seal != volume_info.seal) |
| 2166 | cERROR(1, ("transport encryption setting " | 2172 | cERROR(1, ("transport encryption setting " |
| 2167 | "conflicts with existing tid")); | 2173 | "conflicts with existing tid")); |
