smb3: update allocation size more accurately on write completion
authorSteve French <stfrench@microsoft.com>
Thu, 22 Feb 2024 06:26:52 +0000 (00:26 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 May 2024 14:22:46 +0000 (16:22 +0200)
[ Upstream commit dbfdff402d89854126658376cbcb08363194d3cd ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/smb/client/file.c

index 6d44991e1ccdcd002aff22b5fa9a12b10639e3d0..751ae89cefe367bc11a1ead40ebb5ba18694d546 100644 (file)
@@ -3204,8 +3204,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);
        }