Skip to content

Commit

Permalink
NFS: invalidate file size when taking a lock.
Browse files Browse the repository at this point in the history
Prior to commit ca0daa2 ("NFS: Cache aggressively when file is open
for writing"), NFS would revalidate, or invalidate, the file size when
taking a lock.  Since that commit it only invalidates the file content.

If the file size is changed on the server while wait for the lock, the
client will have an incorrect understanding of the file size and could
corrupt data.  This particularly happens when writing beyond the
(supposed) end of file and can be easily be demonstrated with
posix_fallocate().

If an application opens an empty file, waits for a write lock, and then
calls posix_fallocate(), glibc will determine that the underlying
filesystem doesn't support fallocate (assuming version 4.1 or earlier)
and will write out a '0' byte at the end of each 4K page in the region
being fallocated that is after the end of the file.
NFS will (usually) detect that these writes are beyond EOF and will
expand them to cover the whole page, and then will merge the pages.
Consequently, NFS will write out large blocks of zeroes beyond where it
thought EOF was.  If EOF had moved, the pre-existing part of the file
will be over-written.  Locking should have protected against this,
but it doesn't.

This patch restores the use of nfs_zap_caches() which invalidated the
cached attributes.  When posix_fallocate() asks for the file size, the
request will go to the server and get a correct answer.

cc: [email protected] (v4.8+)
Fixes: ca0daa2 ("NFS: Cache aggressively when file is open for writing")
Signed-off-by: NeilBrown <[email protected]>
Signed-off-by: Anna Schumaker <[email protected]>
  • Loading branch information
NeilBrown authored and amschuma-ntap committed Jul 27, 2017
1 parent 1e6f209 commit 442ce04
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion fs/nfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
*/
nfs_sync_mapping(filp->f_mapping);
if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
nfs_zap_mapping(inode, filp->f_mapping);
nfs_zap_caches(inode);
out:
return status;
}
Expand Down

0 comments on commit 442ce04

Please sign in to comment.