]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
ksmbd: retry iterate_dir in smb2_query_dir
authorHobin Woo <hobin.woo@samsung.com>
Thu, 5 Dec 2024 02:31:19 +0000 (11:31 +0900)
committerSteve French <stfrench@microsoft.com>
Tue, 10 Dec 2024 23:48:06 +0000 (17:48 -0600)
Some file systems do not ensure that the single call of iterate_dir
reaches the end of the directory. For example, FUSE fetches entries from
a daemon using 4KB buffer and stops fetching if entries exceed the
buffer. And then an actor of caller, KSMBD, is used to fill the entries
from the buffer.
Thus, pattern searching on FUSE, files located after the 4KB could not
be found and STATUS_NO_SUCH_FILE was returned.

Signed-off-by: Hobin Woo <hobin.woo@samsung.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Tested-by: Yoonho Shin <yoonho.shin@samsung.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/smb2pdu.c
fs/smb/server/vfs.h

index 4f539eeadbb0debb5db463b3b0b10579b57cfbdf..558ebb2ba0fd2bc0b8f93b065ae568a2972c1e37 100644 (file)
@@ -4228,6 +4228,7 @@ static bool __query_dir(struct dir_context *ctx, const char *name, int namlen,
        /* dot and dotdot entries are already reserved */
        if (!strcmp(".", name) || !strcmp("..", name))
                return true;
+       d_info->num_scan++;
        if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
                return true;
        if (!match_pattern(name, namlen, priv->search_pattern))
@@ -4390,8 +4391,17 @@ int smb2_query_dir(struct ksmbd_work *work)
        query_dir_private.info_level            = req->FileInformationClass;
        dir_fp->readdir_data.private            = &query_dir_private;
        set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
-
+again:
+       d_info.num_scan = 0;
        rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
+       /*
+        * num_entry can be 0 if the directory iteration stops before reaching
+        * the end of the directory and no file is matched with the search
+        * pattern.
+        */
+       if (rc >= 0 && !d_info.num_entry && d_info.num_scan &&
+           d_info.out_buf_len > 0)
+               goto again;
        /*
         * req->OutputBufferLength is too small to contain even one entry.
         * In this case, it immediately returns OutputBufferLength 0 to client.
index cb76f4b5bafe8c15e6c0fd621b209ed4c63402a4..06903024a2d88b367982f08b0eaf1609f73b6f5a 100644 (file)
@@ -43,6 +43,7 @@ struct ksmbd_dir_info {
        char            *rptr;
        int             name_len;
        int             out_buf_len;
+       int             num_scan;
        int             num_entry;
        int             data_count;
        int             last_entry_offset;