diff options
Diffstat (limited to 'fs/cifs')
-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")); |