summaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsglob.h
diff options
context:
space:
mode:
authorJeff Layton <jlayton@poochiereds.net>2014-04-30 09:31:47 -0400
committerSteve French <smfrench@gmail.com>2014-05-21 10:18:05 -0700
commit4f73c7d342d57d065bdbc0995cb56d8d1701b0c0 (patch)
tree6933002e316475c879d702ffbb733a24ba4f0561 /fs/cifs/cifsglob.h
parente284e53fdea1dfd66e73c239fa190685985ae465 (diff)
downloadlinux-4f73c7d342d57d065bdbc0995cb56d8d1701b0c0.tar.gz
linux-4f73c7d342d57d065bdbc0995cb56d8d1701b0c0.tar.bz2
linux-4f73c7d342d57d065bdbc0995cb56d8d1701b0c0.zip
cifs: fix potential races in cifs_revalidate_mapping
The handling of the CIFS_INO_INVALID_MAPPING flag is racy. It's possible for two tasks to attempt to revalidate the mapping at the same time. The first sees that CIFS_INO_INVALID_MAPPING is set. It clears the flag and then calls invalidate_inode_pages2 to start shooting down the pagecache. While that's going on, another task checks the flag and sees that it's clear. It then ends up trusting the pagecache to satisfy a read when it shouldn't. Fix this by adding a bitlock to ensure that the clearing of the flag is atomic with respect to the actual cache invalidation. Also, move the other existing users of cifs_invalidate_mapping to use a new cifs_zap_mapping() function that just sets the INVALID_MAPPING bit and then uses the standard codepath to handle the invalidation. Signed-off-by: Jeff Layton <jlayton@poochiereds.net> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/cifsglob.h')
-rw-r--r--fs/cifs/cifsglob.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 69da55b750e7..630e0f4b2c66 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1118,6 +1118,7 @@ struct cifsInodeInfo {
#define CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 (2) /* Downgrade oplock to L2 */
#define CIFS_INO_DELETE_PENDING (3) /* delete pending on server */
#define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */
+#define CIFS_INO_LOCK (5) /* lock bit for synchronization */
unsigned long flags;
spinlock_t writers_lock;
unsigned int writers; /* Number of writers on this inode */