Skip to content

Commit 7023866

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 1da4ebd commit 7023866

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