diff options
author | Jeff Layton <jlayton@poochiereds.net> | 2014-04-30 09:31:47 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2014-05-21 10:18:05 -0700 |
commit | 4f73c7d342d57d065bdbc0995cb56d8d1701b0c0 (patch) | |
tree | 6933002e316475c879d702ffbb733a24ba4f0561 /fs/cifs/cifsfs.h | |
parent | e284e53fdea1dfd66e73c239fa190685985ae465 (diff) | |
download | linux-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/cifsfs.h')
-rw-r--r-- | fs/cifs/cifsfs.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 63d51274dfbf..1bbe97c2a632 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -76,6 +76,7 @@ extern int cifs_revalidate_file(struct file *filp); extern int cifs_revalidate_dentry(struct dentry *); extern int cifs_invalidate_mapping(struct inode *inode); extern int cifs_revalidate_mapping(struct inode *inode); +extern int cifs_zap_mapping(struct inode *inode); extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int cifs_setattr(struct dentry *, struct iattr *); |