Skip to content

Commit 2b904d6

Browse files
Hobin WooSteve French
authored andcommitted
ksmbd: retry iterate_dir in smb2_query_dir
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 <[email protected]> Reviewed-by: Sungjong Seo <[email protected]> Reviewed-by: Namjae Jeon <[email protected]> Tested-by: Yoonho Shin <[email protected]> Acked-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent fac04ef commit 2b904d6

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

fs/smb/server/smb2pdu.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4228,6 +4228,7 @@ static bool __query_dir(struct dir_context *ctx, const char *name, int namlen,
42284228
/* dot and dotdot entries are already reserved */
42294229
if (!strcmp(".", name) || !strcmp("..", name))
42304230
return true;
4231+
d_info->num_scan++;
42314232
if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
42324233
return true;
42334234
if (!match_pattern(name, namlen, priv->search_pattern))
@@ -4390,8 +4391,17 @@ int smb2_query_dir(struct ksmbd_work *work)
43904391
query_dir_private.info_level = req->FileInformationClass;
43914392
dir_fp->readdir_data.private = &query_dir_private;
43924393
set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
4393-
4394+
again:
4395+
d_info.num_scan = 0;
43944396
rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
4397+
/*
4398+
* num_entry can be 0 if the directory iteration stops before reaching
4399+
* the end of the directory and no file is matched with the search
4400+
* pattern.
4401+
*/
4402+
if (rc >= 0 && !d_info.num_entry && d_info.num_scan &&
4403+
d_info.out_buf_len > 0)
4404+
goto again;
43954405
/*
43964406
* req->OutputBufferLength is too small to contain even one entry.
43974407
* In this case, it immediately returns OutputBufferLength 0 to client.

fs/smb/server/vfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct ksmbd_dir_info {
4343
char *rptr;
4444
int name_len;
4545
int out_buf_len;
46+
int num_scan;
4647
int num_entry;
4748
int data_count;
4849
int last_entry_offset;

0 commit comments

Comments
 (0)