Skip to content

Commit 2f75da8

Browse files
Hobin Woogregkh
authored andcommitted
ksmbd: retry iterate_dir in smb2_query_dir
[ Upstream commit 2b904d6 ] 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]> Signed-off-by: Sasha Levin <[email protected]>
1 parent f53b373 commit 2f75da8

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
@@ -4225,6 +4225,7 @@ static bool __query_dir(struct dir_context *ctx, const char *name, int namlen,
42254225
/* dot and dotdot entries are already reserved */
42264226
if (!strcmp(".", name) || !strcmp("..", name))
42274227
return true;
4228+
d_info->num_scan++;
42284229
if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
42294230
return true;
42304231
if (!match_pattern(name, namlen, priv->search_pattern))
@@ -4385,8 +4386,17 @@ int smb2_query_dir(struct ksmbd_work *work)
43854386
query_dir_private.info_level = req->FileInformationClass;
43864387
dir_fp->readdir_data.private = &query_dir_private;
43874388
set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
4388-
4389+
again:
4390+
d_info.num_scan = 0;
43894391
rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
4392+
/*
4393+
* num_entry can be 0 if the directory iteration stops before reaching
4394+
* the end of the directory and no file is matched with the search
4395+
* pattern.
4396+
*/
4397+
if (rc >= 0 && !d_info.num_entry && d_info.num_scan &&
4398+
d_info.out_buf_len > 0)
4399+
goto again;
43904400
/*
43914401
* req->OutputBufferLength is too small to contain even one entry.
43924402
* 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)