Commit 2b904d61 authored by Hobin Woo's avatar Hobin Woo Committed by Steve French
Browse files

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: default avatarHobin Woo <hobin.woo@samsung.com>
Reviewed-by: default avatarSungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
Tested-by: default avatarYoonho Shin <yoonho.shin@samsung.com>
Acked-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent fac04efc
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -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.
+1 −0
Original line number Diff line number Diff line
@@ -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;