From: Greg Kroah-Hartman Date: Fri, 6 Apr 2012 01:01:35 +0000 (-0700) Subject: 3.3-stable patches X-Git-Tag: v3.3.2~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b84401431a239f53d22a7d888a492c67b4bca186;p=thirdparty%2Fkernel%2Fstable-queue.git 3.3-stable patches added patches: cifs-fix-vfs-lock-usage-for-oplocked-files.patch --- diff --git a/queue-3.3/cifs-fix-vfs-lock-usage-for-oplocked-files.patch b/queue-3.3/cifs-fix-vfs-lock-usage-for-oplocked-files.patch new file mode 100644 index 00000000000..80a0a9e0856 --- /dev/null +++ b/queue-3.3/cifs-fix-vfs-lock-usage-for-oplocked-files.patch @@ -0,0 +1,93 @@ +From 66189be74ff5f9f3fd6444315b85be210d07cef2 Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Wed, 28 Mar 2012 21:56:19 +0400 +Subject: CIFS: Fix VFS lock usage for oplocked files + +From: Pavel Shilovsky + +commit 66189be74ff5f9f3fd6444315b85be210d07cef2 upstream. + +We can deadlock if we have a write oplock and two processes +use the same file handle. In this case the first process can't +unlock its lock if the second process blocked on the lock in the +same time. + +Fix it by using posix_lock_file rather than posix_lock_file_wait +under cinode->lock_mutex. If we request a blocking lock and +posix_lock_file indicates that there is another lock that prevents +us, wait untill that lock is released and restart our call. + +Acked-by: Jeff Layton +Signed-off-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/file.c | 10 +++++++++- + fs/locks.c | 3 ++- + include/linux/fs.h | 5 +++++ + 3 files changed, 16 insertions(+), 2 deletions(-) + +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -835,13 +835,21 @@ cifs_posix_lock_set(struct file *file, s + if ((flock->fl_flags & FL_POSIX) == 0) + return rc; + ++try_again: + mutex_lock(&cinode->lock_mutex); + if (!cinode->can_cache_brlcks) { + mutex_unlock(&cinode->lock_mutex); + return rc; + } +- rc = posix_lock_file_wait(file, flock); ++ ++ rc = posix_lock_file(file, flock, NULL); + mutex_unlock(&cinode->lock_mutex); ++ if (rc == FILE_LOCK_DEFERRED) { ++ rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); ++ if (!rc) ++ goto try_again; ++ locks_delete_block(flock); ++ } + return rc; + } + +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -510,12 +510,13 @@ static void __locks_delete_block(struct + + /* + */ +-static void locks_delete_block(struct file_lock *waiter) ++void locks_delete_block(struct file_lock *waiter) + { + lock_flocks(); + __locks_delete_block(waiter); + unlock_flocks(); + } ++EXPORT_SYMBOL(locks_delete_block); + + /* Insert waiter into blocker's block list. + * We use a circular list so that processes can be easily woken up in +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1210,6 +1210,7 @@ extern int vfs_setlease(struct file *, l + extern int lease_modify(struct file_lock **, int); + extern int lock_may_read(struct inode *, loff_t start, unsigned long count); + extern int lock_may_write(struct inode *, loff_t start, unsigned long count); ++extern void locks_delete_block(struct file_lock *waiter); + extern void lock_flocks(void); + extern void unlock_flocks(void); + #else /* !CONFIG_FILE_LOCKING */ +@@ -1354,6 +1355,10 @@ static inline int lock_may_write(struct + return 1; + } + ++static inline void locks_delete_block(struct file_lock *waiter) ++{ ++} ++ + static inline void lock_flocks(void) + { + } diff --git a/queue-3.3/series b/queue-3.3/series index 8a61d0b7869..0028f27075c 100644 --- a/queue-3.3/series +++ b/queue-3.3/series @@ -48,3 +48,4 @@ kgdbts-fix-kernel-oops-with-config_debug_rodata.patch kgdbts-1-of-2-fix-single-step-awareness-to-work-correctly-with-smp.patch kgdbts-2-of-2-fix-single-step-awareness-to-work-correctly-with-smp.patch x86-kgdb-fix-debug_rodata-limitation-using-text_poke.patch +cifs-fix-vfs-lock-usage-for-oplocked-files.patch