* [PATCH v8 1/5] smb/client: refresh allocation size after duplicate extents
2026-07-03 5:32 [PATCH v8 0/5] smb: fix fallocate and allocation accounting Huiwen He
@ 2026-07-03 5:32 ` Huiwen He
2026-07-03 5:32 ` [PATCH v8 2/5] smb/client: handle overlapping allocated ranges in fallocate Huiwen He
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Huiwen He @ 2026-07-03 5:32 UTC (permalink / raw)
To: smfrench, linkinjeon, pc, ronniesahlberg, sprasad, tom, bharathsm,
senozhatsky, dhowells, metze, chenxiaosong
Cc: linux-cifs
From: Huiwen He <hehuiwen@kylinos.cn>
FSCTL_DUPLICATE_EXTENTS_TO_FILE changes the target file extents on the
server, but the client does not refresh the target AllocationSize/i_blocks.
Callers can observe or use the wrong st_blocks value immediately after the
clone, before a later attribute revalidation corrects it.
For example, create a reflinked file with a leading hole:
xfs_io -f -c "pwrite -S 0x61 0 64k" src
touch dst
chmod 600 dst
xfs_io -c "reflink src 0 1m 64k" dst
mkswap dst
swapon dst
The file still has a hole after mkswap:
/mnt/scratch/dst:
[0..7]: allocated
[8..2047]: hole
[2048..2175]: allocated
The server also reports only the allocated ranges:
server dst size=1114112 blocks=144
but the client reported EOF-derived blocks:
client dst size=1114112 blocks=2176
and swapon succeeded:
swapon_result=success
/mnt/scratch/dst 1.1M 0B -1
So EOF-derived i_blocks can let a sparse reflinked file pass the CIFS
swapfile hole check.
Fix this by querying FILE_ALL_INFORMATION on the target handle after a
successful duplicate extents request. Update i_blocks from AllocationSize
and keep the refreshed target inode attributes valid so a following stat
does not immediately revalidate again.
If the query fails, mark the cached inode attributes stale so a later
getattr can refresh them.
This also fixes the xfstests generic/370 regression introduced by the
i_blocks accounting change, as tested on a Samba "vfs objects = btrfs"
share.
Fixes: 99cd0a6eeb6c ("smb/client: do not account EOF extension as allocation")
Signed-off-by: Huiwen He <hehuiwen@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
fs/smb/client/cifsfs.c | 10 +++++++---
fs/smb/client/smb2ops.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index ea4fc0fa68ca..7fc2b0ad950d 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -1478,9 +1478,13 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
}
}
- /* force revalidate of size and timestamps of target file now
- that target is updated on the server */
- CIFS_I(target_inode)->time = 0;
+ /*
+ * On success, duplicate_extents already updated the target inode attrs
+ * or marked them stale if the refresh failed. On failure, mark attrs
+ * stale because EOF may have changed before the clone failed.
+ */
+ if (rc)
+ CIFS_I(target_inode)->time = 0;
unlock:
/* although unlocking in the reverse order from locking is not
strictly necessary here it is a little cleaner to be consistent */
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 06e9322a762a..26366098c4b7 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -2193,10 +2193,14 @@ smb2_duplicate_extents(const unsigned int xid,
u64 len, u64 dest_off)
{
int rc;
+ int qrc;
unsigned int ret_data_len;
struct inode *inode;
+ struct smb2_file_all_info file_inf;
struct duplicate_extents_to_file dup_ext_buf;
+ struct timespec64 ts;
struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
+ u64 asize;
/* server fileays advertise duplicate extent support with this flag */
if ((le32_to_cpu(tcon->fsAttrInfo.Attributes) &
@@ -2232,6 +2236,32 @@ smb2_duplicate_extents(const unsigned int xid,
if (ret_data_len > 0)
cifs_dbg(FYI, "Non-zero response length in duplicate extents\n");
+ if (rc == 0) {
+ qrc = SMB2_query_info(xid, tcon, trgtfile->fid.persistent_fid,
+ trgtfile->fid.volatile_fid, &file_inf);
+ spin_lock(&inode->i_lock);
+ if (qrc == 0) {
+ asize = le64_to_cpu(file_inf.AllocationSize);
+ CIFS_I(inode)->time = jiffies;
+ if (file_inf.LastWriteTime) {
+ ts = cifs_NTtimeToUnix(file_inf.LastWriteTime);
+ inode_set_mtime_to_ts(inode, ts);
+ }
+ if (file_inf.ChangeTime) {
+ ts = cifs_NTtimeToUnix(file_inf.ChangeTime);
+ inode_set_ctime_to_ts(inode, ts);
+ }
+ if (file_inf.LastAccessTime) {
+ ts = cifs_NTtimeToUnix(file_inf.LastAccessTime);
+ inode_set_atime_to_ts(inode, ts);
+ }
+ inode->i_blocks = CIFS_INO_BLOCKS(asize);
+ } else {
+ CIFS_I(inode)->time = 0; /* force reval */
+ }
+ spin_unlock(&inode->i_lock);
+ }
+
duplicate_extents_out:
if (rc)
trace_smb3_clone_err(xid, srcfile->fid.volatile_fid,
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v8 2/5] smb/client: handle overlapping allocated ranges in fallocate
2026-07-03 5:32 [PATCH v8 0/5] smb: fix fallocate and allocation accounting Huiwen He
2026-07-03 5:32 ` [PATCH v8 1/5] smb/client: refresh allocation size after duplicate extents Huiwen He
@ 2026-07-03 5:32 ` Huiwen He
2026-07-03 5:32 ` [PATCH v8 3/5] smb/client: reduce fallocate zero buffer allocation Huiwen He
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Huiwen He @ 2026-07-03 5:32 UTC (permalink / raw)
To: smfrench, linkinjeon, pc, ronniesahlberg, sprasad, tom, bharathsm,
senozhatsky, dhowells, metze, chenxiaosong
Cc: linux-cifs
From: Huiwen He <hehuiwen@kylinos.cn>
smb3_simple_fallocate_range() can skip holes when an allocated range
returned by the server starts before the current fallocate offset. The
skipped hole is not zero-filled, but fallocate still returns success. A
later write to that hole may therefore fail with ENOSPC.
The function queries allocated ranges so that it can preserve existing
contents and write zeroes only into holes. However, the server may return
a range that starts before the current fallocate offset.
For example, assume the fallocate request is [100, 400) and the only
allocated range returned by the server is [0, 200):
Request: [100, 400)
Server range: [ 0, 200) allocated
Correct:
[100, 200) allocated data, skip
[200, 400) hole, zero-fill
Current:
[100, 300) skipped
[300, 400) zero-filled afterwards
The current code adds the full server range length, 200, to the current
offset 100 and moves to 300. As a result, the hole in [200, 300) is
skipped without being zero-filled.
Fix this by advancing only over the part of the allocated range that
overlaps the current fallocate offset. Ignore ranges that end before the
current offset and reject ranges whose end offset overflows.
This also prevents a malformed range length from causing an out-of-bounds
zero-buffer read.
Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation")
Signed-off-by: Huiwen He <hehuiwen@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
fs/smb/client/smb2ops.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 26366098c4b7..380f4b4ddcd7 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -3611,6 +3611,7 @@ static int smb3_simple_fallocate_range(unsigned int xid,
struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data;
u32 out_data_len;
char *buf = NULL;
+ u64 range_start, range_len, range_end;
loff_t l;
int rc;
@@ -3647,13 +3648,21 @@ static int smb3_simple_fallocate_range(unsigned int xid,
goto out;
}
- if (off < le64_to_cpu(tmp_data->file_offset)) {
+ range_start = le64_to_cpu(tmp_data->file_offset);
+ range_len = le64_to_cpu(tmp_data->length);
+ if (check_add_overflow(range_start, range_len, &range_end) ||
+ range_end > S64_MAX) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (off < range_start) {
/*
* We are at a hole. Write until the end of the region
* or until the next allocated data,
* whichever comes next.
*/
- l = le64_to_cpu(tmp_data->file_offset) - off;
+ l = range_start - off;
if (len < l)
l = len;
rc = smb3_simple_fallocate_write_range(xid, tcon,
@@ -3670,11 +3679,13 @@ static int smb3_simple_fallocate_range(unsigned int xid,
* until the end of the data or the end of the region
* we are supposed to fallocate, whichever comes first.
*/
- l = le64_to_cpu(tmp_data->length);
- if (len < l)
- l = len;
- off += l;
- len -= l;
+ if (off < range_end) {
+ l = range_end - off;
+ if (len < l)
+ l = len;
+ off += l;
+ len -= l;
+ }
tmp_data = &tmp_data[1];
out_data_len -= sizeof(struct file_allocated_range_buffer);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v8 3/5] smb/client: reduce fallocate zero buffer allocation
2026-07-03 5:32 [PATCH v8 0/5] smb: fix fallocate and allocation accounting Huiwen He
2026-07-03 5:32 ` [PATCH v8 1/5] smb/client: refresh allocation size after duplicate extents Huiwen He
2026-07-03 5:32 ` [PATCH v8 2/5] smb/client: handle overlapping allocated ranges in fallocate Huiwen He
@ 2026-07-03 5:32 ` Huiwen He
2026-07-03 5:32 ` [PATCH v8 4/5] smb/client: emulate small EOF-extending mode 0 fallocate ranges Huiwen He
2026-07-03 5:32 ` [PATCH v8 5/5] smb/client: refresh allocation after EOF-extending fallocate Huiwen He
4 siblings, 0 replies; 6+ messages in thread
From: Huiwen He @ 2026-07-03 5:32 UTC (permalink / raw)
To: smfrench, linkinjeon, pc, ronniesahlberg, sprasad, tom, bharathsm,
senozhatsky, dhowells, metze, chenxiaosong
Cc: linux-cifs
From: Huiwen He <hehuiwen@kylinos.cn>
The fallocate emulation allocates a 1 MiB zero-filled buffer even
though each SMB2_write request is limited to SMB2_MAX_BUFFER_SIZE,
which is 64 KiB. A high-order 1 MiB allocation is more likely to
fail on a fragmented system.
Allocate only the smaller of the requested range and SMB2_MAX_BUFFER_SIZE,
and reuse that zero-filled buffer for every write request. Also reject
a successful write that makes no progress to avoid looping indefinitely.
This reduces the contiguous allocation required by fallocate emulation
without changing the written data or range semantics.
Signed-off-by: Huiwen He <hehuiwen@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
fs/smb/client/smb2ops.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 380f4b4ddcd7..41c928bc23c2 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -3573,7 +3573,7 @@ static int smb3_simple_fallocate_write_range(unsigned int xid,
char *buf)
{
struct cifs_io_parms io_parms = {0};
- int nbytes;
+ unsigned int nbytes;
int rc = 0;
struct kvec iov[2];
@@ -3594,9 +3594,10 @@ static int smb3_simple_fallocate_write_range(unsigned int xid,
rc = SMB2_write(xid, &io_parms, &nbytes, iov, 1);
if (rc)
break;
+ if (!nbytes)
+ return -EIO;
if (nbytes > len)
return -EINVAL;
- buf += nbytes;
off += nbytes;
len -= nbytes;
}
@@ -3626,7 +3627,7 @@ static int smb3_simple_fallocate_range(unsigned int xid,
if (rc)
goto out;
- buf = kzalloc(1024 * 1024, GFP_KERNEL);
+ buf = kzalloc(min_t(loff_t, len, SMB2_MAX_BUFFER_SIZE), GFP_KERNEL);
if (buf == NULL) {
rc = -ENOMEM;
goto out;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v8 4/5] smb/client: emulate small EOF-extending mode 0 fallocate ranges
2026-07-03 5:32 [PATCH v8 0/5] smb: fix fallocate and allocation accounting Huiwen He
` (2 preceding siblings ...)
2026-07-03 5:32 ` [PATCH v8 3/5] smb/client: reduce fallocate zero buffer allocation Huiwen He
@ 2026-07-03 5:32 ` Huiwen He
2026-07-03 5:32 ` [PATCH v8 5/5] smb/client: refresh allocation after EOF-extending fallocate Huiwen He
4 siblings, 0 replies; 6+ messages in thread
From: Huiwen He @ 2026-07-03 5:32 UTC (permalink / raw)
To: smfrench, linkinjeon, pc, ronniesahlberg, sprasad, tom, bharathsm,
senozhatsky, dhowells, metze, chenxiaosong
Cc: linux-cifs
From: Huiwen He <hehuiwen@kylinos.cn>
When a mode 0 fallocate extends EOF from 1G to 2G + 1M, the client
currently sends SetEOF for 2G + 1M. This can make fallocate return
success without allocating the requested range, or allocate extra
space before that range.
For example, on a fresh file:
xfs_io -f \
-c "falloc 0 1G" \
-c "falloc 2G 1M" \
-c "truncate 3G" test
The second fallocate should allocate [2G, 2G + 1M), leaving [1G, 2G)
as a hole.
Before this change, the result depended on the server allocation policy.
With Samba "strict allocate = no", SetEOF could return success without
allocating [2G, 2G + 1M). With "strict allocate = yes":
# filefrag -v test
[0, 1G) allocated
[1G, 2G) allocated unexpectedly
[2G, 2G + 1M) allocated
SMB cannot allocate that arbitrary range, so write zeroes to small
EOF-extending ranges instead. Limit this to 1 MiB to bound the
client-side I/O cost.
With "strict allocate = no", the requested range [2G, 2G + 1M) is
allocated by the writes. With "strict allocate = yes":
# filefrag -v test
[0, 1G) allocated
[1G, 2G) hole
[2G, 2G + 1M) allocated
This fixes the small EOF-extending range case exercised by generic/213.
Signed-off-by: Huiwen He <hehuiwen@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
fs/smb/client/smb2ops.c | 69 +++++++++++++++++++++++++++++++++++------
1 file changed, 60 insertions(+), 9 deletions(-)
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 41c928bc23c2..21628606a721 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -3610,12 +3610,25 @@ static int smb3_simple_fallocate_range(unsigned int xid,
loff_t off, loff_t len)
{
struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data;
+ struct inode *inode = d_inode(cfile->dentry);
u32 out_data_len;
char *buf = NULL;
u64 range_start, range_len, range_end;
loff_t l;
int rc;
+ buf = kzalloc(min_t(loff_t, len, SMB2_MAX_BUFFER_SIZE), GFP_KERNEL);
+ if (!buf) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ if (off >= i_size_read(inode)) {
+ rc = smb3_simple_fallocate_write_range(xid, tcon, cfile,
+ off, len, buf);
+ goto out;
+ }
+
in_data.file_offset = cpu_to_le64(off);
in_data.length = cpu_to_le64(len);
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
@@ -3627,12 +3640,6 @@ static int smb3_simple_fallocate_range(unsigned int xid,
if (rc)
goto out;
- buf = kzalloc(min_t(loff_t, len, SMB2_MAX_BUFFER_SIZE), GFP_KERNEL);
- if (buf == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
tmp_data = out_data;
while (len) {
/*
@@ -3707,18 +3714,22 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
struct cifsFileInfo *cfile = file->private_data;
long rc = -EOPNOTSUPP;
unsigned int xid;
- loff_t new_eof;
+ loff_t old_eof, new_eof;
+ struct smb2_file_all_info file_inf;
+ u64 asize;
+ int qrc;
xid = get_xid();
inode = d_inode(cfile->dentry);
cifsi = CIFS_I(inode);
+ old_eof = i_size_read(inode);
trace_smb3_falloc_enter(xid, cfile->fid.persistent_fid, tcon->tid,
tcon->ses->Suid, off, len);
/* if file not oplocked can't be sure whether asking to extend size */
if (!CIFS_CACHE_READ(cifsi))
- if (keep_size == false) {
+ if (!keep_size) {
trace_smb3_falloc_err(xid, cfile->fid.persistent_fid,
tcon->tid, tcon->ses->Suid, off, len, rc);
free_xid(xid);
@@ -3728,11 +3739,51 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
/*
* Extending the file
*/
- if ((keep_size == false) && i_size_read(inode) < off + len) {
+ if (!keep_size && old_eof < off + len) {
rc = inode_newsize_ok(inode, off + len);
if (rc)
goto out;
+ /*
+ * A small range at or beyond EOF can be allocated by writing
+ * zeroes. For off > old_eof, this preserves the intervening
+ * hole instead of allocating from offset 0.
+ */
+ if (off > old_eof ||
+ (off == old_eof && old_eof != 0 &&
+ (cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE))) {
+ if (len > 1024 * 1024) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
+ rc = smb3_simple_fallocate_range(xid, tcon, cfile,
+ off, len);
+ if (rc) {
+ spin_lock(&inode->i_lock);
+ cifsi->time = 0;
+ spin_unlock(&inode->i_lock);
+ goto out;
+ }
+
+ new_eof = off + len;
+ netfs_resize_file(&cifsi->netfs, new_eof, true);
+ cifs_setsize(inode, new_eof);
+
+ qrc = SMB2_query_info(xid, tcon,
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, &file_inf);
+ spin_lock(&inode->i_lock);
+ if (qrc == 0) {
+ asize = le64_to_cpu(file_inf.AllocationSize);
+ inode->i_blocks = CIFS_INO_BLOCKS(asize);
+ } else {
+ cifsi->time = 0;
+ }
+ spin_unlock(&inode->i_lock);
+ goto out;
+ }
+
if (cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)
smb2_set_sparse(xid, tcon, cfile, inode, false);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v8 5/5] smb/client: refresh allocation after EOF-extending fallocate
2026-07-03 5:32 [PATCH v8 0/5] smb: fix fallocate and allocation accounting Huiwen He
` (3 preceding siblings ...)
2026-07-03 5:32 ` [PATCH v8 4/5] smb/client: emulate small EOF-extending mode 0 fallocate ranges Huiwen He
@ 2026-07-03 5:32 ` Huiwen He
4 siblings, 0 replies; 6+ messages in thread
From: Huiwen He @ 2026-07-03 5:32 UTC (permalink / raw)
To: smfrench, linkinjeon, pc, ronniesahlberg, sprasad, tom, bharathsm,
senozhatsky, dhowells, metze, chenxiaosong
Cc: linux-cifs
From: Huiwen He <hehuiwen@kylinos.cn>
Before this change, xfstests generic/496 was not supported on ksmbd:
generic/496 ... [not run] fallocated swap not supported here
ksmbd handles SetEOF as truncate, so EOF extension alone does not
allocate backing blocks. A fallocated swapfile can therefore still
look sparse to swapon.
Request allocation for EOF-extending fallocate ranges that can be
represented by FILE_ALLOCATION_INFORMATION, and refresh the allocation
state afterwards.
With this change, xfstests generic/496 and generic/701 pass on ksmbd.
However, Samba "strict allocate = no" now exposes the real generic/701
failure: the old pass came from inflated local i_blocks, not from
server allocation. generic/213 also fails in that case because an
oversized allocation request may not return ENOSPC.
Signed-off-by: Huiwen He <hehuiwen@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
fs/smb/client/smb2ops.c | 43 ++++++++++++++++++++++++++++++++++++---
fs/smb/client/smb2pdu.c | 19 +++++++++++++++++
fs/smb/client/smb2proto.h | 3 +++
fs/smb/common/fscc.h | 5 +++++
fs/smb/server/smb2pdu.h | 4 ----
5 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 21628606a721..75eaf0105716 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -3788,12 +3788,49 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
smb2_set_sparse(xid, tcon, cfile, inode, false);
new_eof = off + len;
+
+ qrc = SMB2_query_info(xid, tcon,
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, &file_inf);
+ if (qrc == 0)
+ asize = le64_to_cpu(file_inf.AllocationSize);
+
+ /*
+ * FILE_ALLOCATION_INFORMATION can only describe allocation up to
+ * new_eof. Some servers may accept it without allocating blocks,
+ * so refresh AllocationSize before updating i_blocks.
+ */
+ if (off == 0 || off == old_eof) {
+ if (qrc || asize < new_eof) {
+ rc = SMB2_set_allocation(xid, tcon,
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ cfile->pid, new_eof);
+ if (rc)
+ goto out;
+ }
+ }
+
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, cfile->pid, new_eof);
- if (rc == 0) {
- netfs_resize_file(&cifsi->netfs, new_eof, true);
- cifs_setsize(inode, new_eof);
+ if (rc)
+ goto out;
+
+ netfs_resize_file(&cifsi->netfs, new_eof, true);
+ cifs_setsize(inode, new_eof);
+
+ qrc = SMB2_query_info(xid, tcon,
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, &file_inf);
+ spin_lock(&inode->i_lock);
+ if (qrc == 0) {
+ asize = le64_to_cpu(file_inf.AllocationSize);
+ if (asize >= new_eof)
+ inode->i_blocks = CIFS_INO_BLOCKS(asize);
+ } else {
+ cifsi->time = 0;
}
+ spin_unlock(&inode->i_lock);
goto out;
}
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index d058584b8f05..1374bbae627f 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -5947,6 +5947,25 @@ SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
0, 1, &data, &size);
}
+int
+SMB2_set_allocation(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, u32 pid,
+ loff_t allocation_size)
+{
+ struct smb2_file_alloc_info info;
+ void *data;
+ unsigned int size;
+
+ info.AllocationSize = cpu_to_le64(allocation_size);
+
+ data = &info;
+ size = sizeof(struct smb2_file_alloc_info);
+
+ return send_set_info(xid, tcon, persistent_fid, volatile_fid,
+ pid, FILE_ALLOCATION_INFORMATION, SMB2_O_INFO_FILE,
+ 0, 1, &data, &size);
+}
+
int
SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid,
diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
index 78a4e1c340f9..16a02c1eb0a1 100644
--- a/fs/smb/client/smb2proto.h
+++ b/fs/smb/client/smb2proto.h
@@ -204,6 +204,9 @@ void SMB2_query_directory_free(struct smb_rqst *rqst);
int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u32 pid,
loff_t new_eof);
+int SMB2_set_allocation(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, u32 pid,
+ loff_t allocation_size);
int SMB2_set_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
struct smb_rqst *rqst, u64 persistent_fid,
u64 volatile_fid, u32 pid, u8 info_class, u8 info_type,
diff --git a/fs/smb/common/fscc.h b/fs/smb/common/fscc.h
index 859849a42fec..941db5a95564 100644
--- a/fs/smb/common/fscc.h
+++ b/fs/smb/common/fscc.h
@@ -283,6 +283,11 @@ struct smb2_file_eof_info { /* encoding of request for level 10 */
__le64 EndOfFile; /* new end of file value */
} __packed; /* level 20 Set */
+/* See MS-FSCC 2.4.4 */
+struct smb2_file_alloc_info { /* encoding of request for level 19 */
+ __le64 AllocationSize;
+} __packed;
+
/* See MS-FSCC 2.4.15 */
typedef struct {
__le32 NextEntryOffset;
diff --git a/fs/smb/server/smb2pdu.h b/fs/smb/server/smb2pdu.h
index c2512dbcdec8..aa06c8c905f1 100644
--- a/fs/smb/server/smb2pdu.h
+++ b/fs/smb/server/smb2pdu.h
@@ -212,10 +212,6 @@ struct smb2_file_ea_info {
__le32 EASize;
} __packed;
-struct smb2_file_alloc_info {
- __le64 AllocationSize;
-} __packed;
-
struct smb2_file_disposition_info {
__u8 DeletePending;
} __packed;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread