Message ID | 20241205023120.792280-1-hobin.woo@samsung.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | ksmbd: retry iterate_dir in smb2_query_dir | expand |
On Thu, Dec 5, 2024 at 11:31 AM Hobin Woo <hobin.woo@samsung.com> wrote: > > 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> Applied it to #ksmbd-for-next-next. Thanks for your patch!
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 4f539eeadbb0..1923f91d40b6 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -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. diff --git a/fs/smb/server/vfs.h b/fs/smb/server/vfs.h index cb76f4b5bafe..06903024a2d8 100644 --- a/fs/smb/server/vfs.h +++ b/fs/smb/server/vfs.h @@ -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;