summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorSteve French <stfrench@microsoft.com>2024-02-22 00:26:52 -0600
committerSteve French <stfrench@microsoft.com>2024-03-10 19:33:54 -0500
commitdbfdff402d89854126658376cbcb08363194d3cd (patch)
treeb58716dd7bdf6ae67d0395a36dbec0cb166bd877 /fs
parent13c2e30809c751a81d7eb01897825f7221c94e3c (diff)
smb3: update allocation size more accurately on write completion
Changes to allocation size are approximated for extending writes of cached files until the server returns the actual value (on SMB3 close or query info for example), but it was setting the estimated value for number of blocks to larger than the file size even if the file is likely sparse which breaks various xfstests (e.g. generic/129, 130, 221, 228). When i_size and i_blocks are updated in write completion do not increase allocation size more than what was written (rounded up to 512 bytes). Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/smb/client/file.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index 9cff5f7dc062..24534b7e3aca 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -3094,8 +3094,15 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
if (rc > 0) {
spin_lock(&inode->i_lock);
if (pos > inode->i_size) {
+ loff_t additional_blocks = (512 - 1 + copied) >> 9;
+
i_size_write(inode, pos);
- inode->i_blocks = (512 - 1 + pos) >> 9;
+ /*
+ * Estimate new allocation size based on the amount written.
+ * This will be updated from server on close (and on queryinfo)
+ */
+ inode->i_blocks = min_t(blkcnt_t, (512 - 1 + pos) >> 9,
+ inode->i_blocks + additional_blocks);
}
spin_unlock(&inode->i_lock);
}