aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsfs.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2008-10-23 00:42:37 -0400
committerSteve French <sfrench@us.ibm.com>2008-10-23 00:42:37 -0400
commit84210e9120a8c01a14379ba1f9a9b0f963641d94 (patch)
treeed20b210bb554f283d8458ee6d146a5c4439e37f /fs/cifs/cifsfs.c
parenta364bc0b37f14ffd66c1f982af42990a9d77fa43 (diff)
[CIFS] improve setlease handling
fcntl(F_SETLEASE) currently is not exported by cifs (nor by local file systems) so cifs grants leases based on how other local processes have opened the file not by whether the file is cacheable (oplocked). This adds the check to make sure that the file is cacheable on the client before checking whether we can grant the lease locally (generic_setlease). It also adds a mount option for cifs (locallease) if the user wants to override this and try to grant leases even if the server did not grant oplock. Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/cifsfs.c')
-rw-r--r--fs/cifs/cifsfs.c41
1 files changed, 41 insertions, 0 deletions
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
622static 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
621struct file_system_type cifs_fs_type = { 652struct 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};
721const struct file_operations cifs_file_nobrl_ops = { 754const 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(