Re: [PATCH v4 6/7] smb/client: emulate small mode 0 fallocate ranges at or past EOF

Steve French <[email protected]>
Newsgroups org.kernel.vger.linux-cifs
Message-ID <CAH2r5msQgF_ktpuAbebZzhd+=u7yu9GO1+9ePpRmwB4cLO6FTQ@mail.gmail.com>
Running to Samba I have always been getting a failure with generic/213
(with or without this patch). Any ideas?

generic/213        - output mismatch (see
/home/smfrench/xfstests-dev/results//sambamfs/generic/213.out.bad)
    --- tests/generic/213.out 2026-06-16 19:54:18.366737595 -0500
    +++ /home/smfrench/xfstests-dev/results//sambamfs/generic/213.out.bad
2026-06-27 12:37:15.973294906 -0500
    @@ -1,4 +1,3 @@
     QA output created by 213
     We should get: fallocate: No space left on device
     Strangely, xfs_io sometimes says "Success" when something went wrong, FYI
    -fallocate: No space left on device


On Fri, Jun 26, 2026 at 8:48 AM Huiwen He <[email protected]> wrote:
>
> From: Huiwen He <[email protected]>
>
> The xfstest generic/213 has a mode 0 fallocate case like:
>
>         falloc 0 1G
>         falloc 2G 1M
>         truncate 3G
>
> The expected layout is:
>
>         allocated [0, 1G)
>         hole      [1G, 2G)
>         allocated [2G, 2G + 1M)
>
> Current CIFS can pass this test while allocating the intervening hole.
> Before this change, the server-side layout was effectively:
>
>         allocated [0, 1G)
>         allocated [1G, 2G + 1M)
>
> so [1G, 2G) was allocated as part of the second extent.
>
> Emulate small mode 0 fallocate ranges that start at or past EOF by writing
> zeroes only to the requested range.  For off > old_eof, this preserves the
> hole between old_eof and off. Keep this emulation limited to 1 MiB so the
> client-side I/O cost remains bounded; larger unsupported ranges remain
> rejected.
>
> After this change, the same pattern gives the intended layout:
>
>         allocated [0, 1G)
>         hole      [1G, 2G)
>         allocated [2G, 2G + 1M)
>
> This changes generic/213 from a false pass into a range-correct pass.
>
> Signed-off-by: Huiwen He <[email protected]>
> Reviewed-by: ChenXiaoSong <[email protected]>
> ---
>  fs/smb/client/smb2ops.c | 50 ++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 47 insertions(+), 3 deletions(-)
>
> diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
> index 311709d73798..02ecba985daa 100644
> --- a/fs/smb/client/smb2ops.c
> +++ b/fs/smb/client/smb2ops.c
> @@ -3693,18 +3693,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);
> @@ -3714,11 +3718,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) {
>                         rc = smb2_set_sparse(xid, tcon, cfile, inode, false);
>                         if (rc)
> --
> 2.43.0
>


--
Thanks,

Steve
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.