mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] ksmbd: truncate files before allocating space below EOF
@ 2026-10-11 11:52 DaeMyung Kang
  0 siblings, 0 replies; only message in thread
From: DaeMyung Kang @ 2026-10-11 11:52 UTC (permalink / raw)
  To: Namjae Jeon
  Cc: Sergey Senozhatsky, Tom Talpey, ChenXiaoSong, linux-cifs,
	linux-kernel, stable, DaeMyung Kang

set_file_allocation_info() compares the requested allocation with
stat.blocks to decide whether to fallocate or truncate. A file with
holes can have fewer allocated blocks than requested even when its EOF
is beyond the requested allocation size. In that case, ksmbd fallocates
with FALLOC_FL_KEEP_SIZE and returns success without shrinking the file.

For example, a file with one byte at offset 1 MiB has an EOF of
1 MiB + 1 but only one allocated page. Setting AllocationSize to 512 KiB
leaves the EOF and the byte unchanged, including after reopening the
file. [MS-FSA] section 2.1.5.15.1 requires EOF to be reduced when the
new allocation size is smaller than the file size.

Check EOF before comparing allocated blocks. Truncate first when the
requested allocation falls below EOF, and skip fallocate in that case.
This avoids allocating holes immediately before discarding them and
allows a shrink request to succeed when space is exhausted. Preserve
the existing behavior for allocation changes that do not shorten EOF.

Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Cc: stable@vger.kernel.org
Signed-off-by: DaeMyung Kang <charsyam@gmail.com>
---
 fs/smb/server/smb2pdu.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 12a43efdb53f..b155a27eaeac 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -8533,23 +8533,15 @@ static int set_file_allocation_info(struct ksmbd_work *work,
 	alloc_blks = (alloc_size + 511) >> 9;
 	inode = file_inode(fp->filp);
 
-	if (alloc_blks > stat.blocks) {
-		smb_break_all_levII_oplock(work, fp, 1);
-		rc = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
-				   alloc_blks * 512);
-		if (rc && rc != -EOPNOTSUPP) {
-			pr_err("vfs_fallocate is failed : %d\n", rc);
-			return rc;
-		}
-	} else if (alloc_blks < stat.blocks) {
+	if (alloc_blks * 512 < i_size_read(inode) ||
+	    alloc_blks < stat.blocks) {
 		loff_t size;
 
 		/*
-		 * Allocation size could be smaller than original one
-		 * which means allocated blocks in file should be
-		 * deallocated. use truncate to cut out it, but inode
-		 * size is also updated with truncate offset.
-		 * inode size is retained by backup inode size.
+		 * Truncate before considering allocation when the new size is below
+		 * EOF. This avoids allocating holes in a sparse file just before
+		 * shrinking it. Also release excess blocks if EOF is already
+		 * smaller than the requested allocation size.
 		 */
 		size = i_size_read(inode);
 		rc = ksmbd_vfs_truncate(work, fp, alloc_blks * 512);
@@ -8559,6 +8551,14 @@ static int set_file_allocation_info(struct ksmbd_work *work,
 		}
 		if (size < alloc_blks * 512)
 			i_size_write(inode, size);
+	} else if (alloc_blks > stat.blocks) {
+		smb_break_all_levII_oplock(work, fp, 1);
+		rc = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
+				   alloc_blks * 512);
+		if (rc && rc != -EOPNOTSUPP) {
+			pr_err("vfs_fallocate is failed : %d\n", rc);
+			return rc;
+		}
 	}
 
 	fp->allocation_size = le64_to_cpu(file_alloc_info->AllocationSize);
-- 
2.43.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-11 11:52 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-11 11:52 [PATCH] ksmbd: truncate files before allocating space below EOF DaeMyung Kang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®