summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJeff Layton <jlayton@poochiereds.net>2014-06-10 18:24:40 +0200
committerJeff Layton <jlayton@poochiereds.net>2014-06-10 18:24:40 +0200
commit962bd40bc30e412828e091bfda041b7547e779c8 (patch)
treedc5afa02febd54262708784552b497f11bd0c080 /include
parentMerge tag 'for-f2fs-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/ja... (diff)
downloadlinux-962bd40bc30e412828e091bfda041b7547e779c8.tar.xz
linux-962bd40bc30e412828e091bfda041b7547e779c8.zip
locks: add missing memory barrier in break_deleg
break_deleg is subject to the same potential race as break_lease. Add a memory barrier to prevent it. Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Diffstat (limited to 'include')
-rw-r--r--include/linux/fs.h6
1 files changed, 6 insertions, 0 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c3f46e499dd0..22ae79650b82 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1914,6 +1914,12 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
static inline int break_deleg(struct inode *inode, unsigned int mode)
{
+ /*
+ * Since this check is lockless, we must ensure that any refcounts
+ * taken are done before checking inode->i_flock. Otherwise, we could
+ * end up racing with tasks trying to set a new lease on this file.
+ */
+ smp_mb();
if (inode->i_flock)
return __break_lease(inode, mode, FL_DELEG);
return 0;