aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsfs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 13:43:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 13:43:36 -0400
commitdb563fc2e80534f98c7f9121a6f7dfe41f177a79 (patch)
treec97acbb983530b070e28c70825e0eedbbdb97ab2 /fs/cifs/cifsfs.c
parenteb81071584bed0b04adcaf57e525638d0f92e1e1 (diff)
parentb1c8d2b421376bc941823ee93e36cb491609b02c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: cifs: handle the TCP_Server_Info->tsk field more carefully cifs: fix unlinking of rename target when server doesn't support open file renames [CIFS] improve setlease handling [CIFS] fix saving of resume key before CIFSFindNext cifs: make cifs_rename handle -EACCES errors [CIFS] fix build error [CIFS] undo changes in cifs_rename_pending_delete if it errors out cifs: track DeletePending flag in cifsInodeInfo cifs: don't use CREATE_DELETE_ON_CLOSE in cifs_rename_pending_delete [CIFS] eliminate usage of kthread_stop for cifsd [CIFS] Add nodfs mount option
Diffstat (limited to 'fs/cifs/cifsfs.c')
-rw-r--r--fs/cifs/cifsfs.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 84cc011a16e4..ac5915d61dca 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -312,6 +312,7 @@ cifs_alloc_inode(struct super_block *sb)
312 file data or metadata */ 312 file data or metadata */
313 cifs_inode->clientCanCacheRead = false; 313 cifs_inode->clientCanCacheRead = false;
314 cifs_inode->clientCanCacheAll = false; 314 cifs_inode->clientCanCacheAll = false;
315 cifs_inode->delete_pending = false;
315 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 316 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
316 317
317 /* Can not set i_flags here - they get immediately overwritten 318 /* Can not set i_flags here - they get immediately overwritten
@@ -620,6 +621,37 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
620 return generic_file_llseek_unlocked(file, offset, origin); 621 return generic_file_llseek_unlocked(file, offset, origin);
621} 622}
622 623
624#ifdef CONFIG_CIFS_EXPERIMENTAL
625static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
626{
627 /* note that this is called by vfs setlease with the BKL held
628 although I doubt that BKL is needed here in cifs */
629 struct inode *inode = file->f_path.dentry->d_inode;
630
631 if (!(S_ISREG(inode->i_mode)))
632 return -EINVAL;
633
634 /* check if file is oplocked */
635 if (((arg == F_RDLCK) &&
636 (CIFS_I(inode)->clientCanCacheRead)) ||
637 ((arg == F_WRLCK) &&
638 (CIFS_I(inode)->clientCanCacheAll)))
639 return generic_setlease(file, arg, lease);
640 else if (CIFS_SB(inode->i_sb)->tcon->local_lease &&
641 !CIFS_I(inode)->clientCanCacheRead)
642 /* If the server claims to support oplock on this
643 file, then we still need to check oplock even
644 if the local_lease mount option is set, but there
645 are servers which do not support oplock for which
646 this mount option may be useful if the user
647 knows that the file won't be changed on the server
648 by anyone else */
649 return generic_setlease(file, arg, lease);
650 else
651 return -EAGAIN;
652}
653#endif
654
623struct file_system_type cifs_fs_type = { 655struct file_system_type cifs_fs_type = {
624 .owner = THIS_MODULE, 656 .owner = THIS_MODULE,
625 .name = "cifs", 657 .name = "cifs",
@@ -698,6 +730,7 @@ const struct file_operations cifs_file_ops = {
698 730
699#ifdef CONFIG_CIFS_EXPERIMENTAL 731#ifdef CONFIG_CIFS_EXPERIMENTAL
700 .dir_notify = cifs_dir_notify, 732 .dir_notify = cifs_dir_notify,
733 .setlease = cifs_setlease,
701#endif /* CONFIG_CIFS_EXPERIMENTAL */ 734#endif /* CONFIG_CIFS_EXPERIMENTAL */
702}; 735};
703 736
@@ -718,6 +751,7 @@ const struct file_operations cifs_file_direct_ops = {
718 .llseek = cifs_llseek, 751 .llseek = cifs_llseek,
719#ifdef CONFIG_CIFS_EXPERIMENTAL 752#ifdef CONFIG_CIFS_EXPERIMENTAL
720 .dir_notify = cifs_dir_notify, 753 .dir_notify = cifs_dir_notify,
754 .setlease = cifs_setlease,
721#endif /* CONFIG_CIFS_EXPERIMENTAL */ 755#endif /* CONFIG_CIFS_EXPERIMENTAL */
722}; 756};
723const struct file_operations cifs_file_nobrl_ops = { 757const struct file_operations cifs_file_nobrl_ops = {
@@ -738,6 +772,7 @@ const struct file_operations cifs_file_nobrl_ops = {
738 772
739#ifdef CONFIG_CIFS_EXPERIMENTAL 773#ifdef CONFIG_CIFS_EXPERIMENTAL
740 .dir_notify = cifs_dir_notify, 774 .dir_notify = cifs_dir_notify,
775 .setlease = cifs_setlease,
741#endif /* CONFIG_CIFS_EXPERIMENTAL */ 776#endif /* CONFIG_CIFS_EXPERIMENTAL */
742}; 777};
743 778
@@ -757,6 +792,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
757 .llseek = cifs_llseek, 792 .llseek = cifs_llseek,
758#ifdef CONFIG_CIFS_EXPERIMENTAL 793#ifdef CONFIG_CIFS_EXPERIMENTAL
759 .dir_notify = cifs_dir_notify, 794 .dir_notify = cifs_dir_notify,
795 .setlease = cifs_setlease,
760#endif /* CONFIG_CIFS_EXPERIMENTAL */ 796#endif /* CONFIG_CIFS_EXPERIMENTAL */
761}; 797};
762 798
@@ -949,6 +985,12 @@ static int cifs_oplock_thread(void *dummyarg)
949 the call */ 985 the call */
950 /* mutex_lock(&inode->i_mutex);*/ 986 /* mutex_lock(&inode->i_mutex);*/
951 if (S_ISREG(inode->i_mode)) { 987 if (S_ISREG(inode->i_mode)) {
988#ifdef CONFIG_CIFS_EXPERIMENTAL
989 if (CIFS_I(inode)->clientCanCacheAll == 0)
990 break_lease(inode, FMODE_READ);
991 else if (CIFS_I(inode)->clientCanCacheRead == 0)
992 break_lease(inode, FMODE_WRITE);
993#endif
952 rc = filemap_fdatawrite(inode->i_mapping); 994 rc = filemap_fdatawrite(inode->i_mapping);
953 if (CIFS_I(inode)->clientCanCacheRead == 0) { 995 if (CIFS_I(inode)->clientCanCacheRead == 0) {
954 waitrc = filemap_fdatawait( 996 waitrc = filemap_fdatawait(