diff options
author | Jan Kara <jack@suse.cz> | 2021-04-22 16:38:26 +0200 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2021-07-13 14:29:01 +0200 |
commit | 057ba5b24532aca202cb1ae8c246bde27de12763 (patch) | |
tree | 3abff803cddcd5ef21b135f6c31cb1d05f908e6a /fs/ceph/file.c | |
parent | 8bcbbe9c7c8e49281fc2e0a6c5455b87c85a9c2a (diff) | |
download | linux-stable-057ba5b24532aca202cb1ae8c246bde27de12763.tar.gz linux-stable-057ba5b24532aca202cb1ae8c246bde27de12763.tar.bz2 linux-stable-057ba5b24532aca202cb1ae8c246bde27de12763.zip |
ceph: Fix race between hole punch and page fault
Ceph has a following race between hole punching and page fault:
CPU1 CPU2
ceph_fallocate()
...
ceph_zero_pagecache_range()
ceph_filemap_fault()
faults in page in the range being
punched
ceph_zero_objects()
And now we have a page in punched range with invalid data. Fix the
problem by using mapping->invalidate_lock similarly to other
filesystems. Note that using invalidate_lock also fixes a similar race
wrt ->readpage().
CC: Jeff Layton <jlayton@kernel.org>
CC: ceph-devel@vger.kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ceph/file.c')
-rw-r--r-- | fs/ceph/file.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index d1755ac1d964..e1d605a02d4a 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -2088,6 +2088,7 @@ static long ceph_fallocate(struct file *file, int mode, if (ret < 0) goto unlock; + filemap_invalidate_lock(inode->i_mapping); ceph_zero_pagecache_range(inode, offset, length); ret = ceph_zero_objects(inode, offset, length); @@ -2100,6 +2101,7 @@ static long ceph_fallocate(struct file *file, int mode, if (dirty) __mark_inode_dirty(inode, dirty); } + filemap_invalidate_unlock(inode->i_mapping); ceph_put_cap_refs(ci, got); unlock: |