diff options
Diffstat (limited to 'fs/cifs/cifsfs.c')
-rw-r--r-- | fs/cifs/cifsfs.c | 41 |
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 | ||
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( |