ksmbd: retry iterate_dir in smb2_query_dir
[ Upstream commit 2b904d61a9 ]
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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
f53b37313a
commit
2f75da8294
+11
-1
@@ -4225,6 +4225,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))
|
||||
@@ -4385,8 +4386,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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user