All of lore.kernel.org
 help / color / mirror / Atom feed
* Cifs: cache entries for the cached directory
@ 2022-05-09 23:42 Ronnie Sahlberg
  2022-05-09 23:42 ` [PATCH 1/4] cifs: move definition of cifs_fattr earlier in cifsglob.h Ronnie Sahlberg
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Ronnie Sahlberg @ 2022-05-09 23:42 UTC (permalink / raw)
  To: linux-cifs; +Cc: Steve French

Steve, List

Updated version of the patch to add caching of directory entries for the cached
dir.
I have updated with all the suggestions from Enzo and Paulo.
In this patch, once you have done the initial 'ls /mnt' and future 
listings of the root of the share will be served straight out of cache
until the lease is broken.
The first three patches are small and isolated for easy review
and the fourth patch is what actually adds the caching of entries.

These functions are now at a stage that we should be able to start looking at
replacing the "single cached direcotry" that is linked to the tcon
to be a list of <=n most recent directories we have accessed.
Thus expanding it to cache a lot more directories than just the root.
But that will come later once this is stabilized and road-tested.
At least I think with these all changes it should be fairly easy to expand
the use to more directories.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] cifs: move definition of cifs_fattr earlier in cifsglob.h
  2022-05-09 23:42 Cifs: cache entries for the cached directory Ronnie Sahlberg
@ 2022-05-09 23:42 ` Ronnie Sahlberg
  2022-05-09 23:42 ` [PATCH 2/4] cifs: check for smb1 in open_cached_dir() Ronnie Sahlberg
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Ronnie Sahlberg @ 2022-05-09 23:42 UTC (permalink / raw)
  To: linux-cifs; +Cc: Steve French

This only moves these definitions to come earlier in the file
but not change the definition itself.
This is done to reduce the amount of changes in future patches.

Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: Enzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/cifsglob.h | 62 +++++++++++++++++++++++-----------------------
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 8de977c359b1..f2eeabb189a2 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1009,6 +1009,37 @@ cap_unix(struct cifs_ses *ses)
 	return ses->server->vals->cap_unix & ses->capabilities;
 }
 
+/*
+ * common struct for holding inode info when searching for or updating an
+ * inode with new info
+ */
+
+#define CIFS_FATTR_DFS_REFERRAL		0x1
+#define CIFS_FATTR_DELETE_PENDING	0x2
+#define CIFS_FATTR_NEED_REVAL		0x4
+#define CIFS_FATTR_INO_COLLISION	0x8
+#define CIFS_FATTR_UNKNOWN_NLINK	0x10
+#define CIFS_FATTR_FAKE_ROOT_INO	0x20
+
+struct cifs_fattr {
+	u32		cf_flags;
+	u32		cf_cifsattrs;
+	u64		cf_uniqueid;
+	u64		cf_eof;
+	u64		cf_bytes;
+	u64		cf_createtime;
+	kuid_t		cf_uid;
+	kgid_t		cf_gid;
+	umode_t		cf_mode;
+	dev_t		cf_rdev;
+	unsigned int	cf_nlink;
+	unsigned int	cf_dtype;
+	struct timespec64 cf_atime;
+	struct timespec64 cf_mtime;
+	struct timespec64 cf_ctime;
+	u32             cf_cifstag;
+};
+
 struct cached_fid {
 	bool is_valid:1;	/* Do we have a useable root fid */
 	bool file_all_info_is_valid:1;
@@ -1641,37 +1672,6 @@ struct file_list {
 	struct cifsFileInfo *cfile;
 };
 
-/*
- * common struct for holding inode info when searching for or updating an
- * inode with new info
- */
-
-#define CIFS_FATTR_DFS_REFERRAL		0x1
-#define CIFS_FATTR_DELETE_PENDING	0x2
-#define CIFS_FATTR_NEED_REVAL		0x4
-#define CIFS_FATTR_INO_COLLISION	0x8
-#define CIFS_FATTR_UNKNOWN_NLINK	0x10
-#define CIFS_FATTR_FAKE_ROOT_INO	0x20
-
-struct cifs_fattr {
-	u32		cf_flags;
-	u32		cf_cifsattrs;
-	u64		cf_uniqueid;
-	u64		cf_eof;
-	u64		cf_bytes;
-	u64		cf_createtime;
-	kuid_t		cf_uid;
-	kgid_t		cf_gid;
-	umode_t		cf_mode;
-	dev_t		cf_rdev;
-	unsigned int	cf_nlink;
-	unsigned int	cf_dtype;
-	struct timespec64 cf_atime;
-	struct timespec64 cf_mtime;
-	struct timespec64 cf_ctime;
-	u32             cf_cifstag;
-};
-
 static inline void free_dfs_info_param(struct dfs_info3_param *param)
 {
 	if (param) {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] cifs: check for smb1 in open_cached_dir()
  2022-05-09 23:42 Cifs: cache entries for the cached directory Ronnie Sahlberg
  2022-05-09 23:42 ` [PATCH 1/4] cifs: move definition of cifs_fattr earlier in cifsglob.h Ronnie Sahlberg
@ 2022-05-09 23:42 ` Ronnie Sahlberg
  2022-05-09 23:42 ` [PATCH 3/4] cifs: set the CREATE_NOT_FILE when opening the directory in use_cached_dir() Ronnie Sahlberg
  2022-05-09 23:42 ` [PATCH 4/4] cifs: cache the dirents for entries in a cached directory Ronnie Sahlberg
  3 siblings, 0 replies; 9+ messages in thread
From: Ronnie Sahlberg @ 2022-05-09 23:42 UTC (permalink / raw)
  To: linux-cifs; +Cc: Steve French

Check protocol version in open_cached_dir() and return not supported
for SMB1.  This allows us to call open_cached_dir() from code that
is common to both smb1 and smb2/3 in future patches without having to
do this check in the call-site.
At the same time, add a check if tcon is valid or not for the same reason.

Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: Enzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/smb2ops.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index d6aaeff4a30a..2c93ee27d54d 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -776,7 +776,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 	struct cifs_fid *pfid;
 	struct dentry *dentry;
 
-	if (tcon->nohandlecache)
+	if (tcon == NULL || tcon->nohandlecache ||
+	    is_smb1_server(tcon->ses->server))
 		return -ENOTSUPP;
 
 	if (cifs_sb->root == NULL)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/4] cifs: set the CREATE_NOT_FILE when opening the directory in use_cached_dir()
  2022-05-09 23:42 Cifs: cache entries for the cached directory Ronnie Sahlberg
  2022-05-09 23:42 ` [PATCH 1/4] cifs: move definition of cifs_fattr earlier in cifsglob.h Ronnie Sahlberg
  2022-05-09 23:42 ` [PATCH 2/4] cifs: check for smb1 in open_cached_dir() Ronnie Sahlberg
@ 2022-05-09 23:42 ` Ronnie Sahlberg
  2022-05-21 17:26   ` Steve French
  2022-05-09 23:42 ` [PATCH 4/4] cifs: cache the dirents for entries in a cached directory Ronnie Sahlberg
  3 siblings, 1 reply; 9+ messages in thread
From: Ronnie Sahlberg @ 2022-05-09 23:42 UTC (permalink / raw)
  To: linux-cifs; +Cc: Steve French

This enforces that we can only do this for directories and not normal files
or else the server will return an error.
This means that we will have conditionally check IF the path refers
to a directory or not in all the call-sites where we are unsure.
Right now this check is for "" i.e. root.

Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: Enzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/smb2inode.c | 5 ++++-
 fs/cifs/smb2ops.c   | 5 +++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index fe5bfa245fa7..0c3e4d2c6207 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -514,8 +514,11 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
 	if (smb2_data == NULL)
 		return -ENOMEM;
 
+	if (strcmp(full_path, ""))
+		rc = -ENOENT;
+	else
+		rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid);
 	/* If it is a root and its handle is cached then use it */
-	rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid);
 	if (!rc) {
 		if (tcon->crfid.file_all_info_is_valid) {
 			move_smb2_info_to_cifs(data,
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 2c93ee27d54d..cbe56ed35694 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -825,7 +825,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 	rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
 
 	oparms.tcon = tcon;
-	oparms.create_options = cifs_create_options(cifs_sb, 0);
+	oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE);
 	oparms.desired_access = FILE_READ_ATTRIBUTES;
 	oparms.disposition = FILE_OPEN;
 	oparms.fid = pfid;
@@ -2696,7 +2696,8 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
 	resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
 	memset(rsp_iov, 0, sizeof(rsp_iov));
 
-	rc = open_cached_dir(xid, tcon, path, cifs_sb, &cfid);
+	if (!strcmp(path, ""))
+		rc = open_cached_dir(xid, tcon, path, cifs_sb, &cfid);
 
 	memset(&open_iov, 0, sizeof(open_iov));
 	rqst[0].rq_iov = open_iov;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/4] cifs: cache the dirents for entries in a cached directory
  2022-05-09 23:42 Cifs: cache entries for the cached directory Ronnie Sahlberg
                   ` (2 preceding siblings ...)
  2022-05-09 23:42 ` [PATCH 3/4] cifs: set the CREATE_NOT_FILE when opening the directory in use_cached_dir() Ronnie Sahlberg
@ 2022-05-09 23:42 ` Ronnie Sahlberg
  2022-05-10 22:57   ` Enzo Matsumiya
  3 siblings, 1 reply; 9+ messages in thread
From: Ronnie Sahlberg @ 2022-05-09 23:42 UTC (permalink / raw)
  To: linux-cifs; +Cc: Steve French

This adds caching of the directory entries for a cached directory while we keep
a lease on the directory.

Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: Enzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/cifsglob.h |  22 ++++++
 fs/cifs/misc.c     |   2 +
 fs/cifs/readdir.c  | 181 +++++++++++++++++++++++++++++++++++++++++++--
 fs/cifs/smb2ops.c  |  16 ++++
 4 files changed, 213 insertions(+), 8 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index f2eeabb189a2..4ec6a3df17fa 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1040,6 +1040,27 @@ struct cifs_fattr {
 	u32             cf_cifstag;
 };
 
+struct cached_dirent {
+	struct list_head entry;
+	char *name;
+	int namelen;
+	loff_t pos;
+
+	struct cifs_fattr fattr;
+};
+
+struct cached_dirents {
+	bool is_valid:1;
+	bool is_failed:1;
+	struct dir_context *ctx; /*
+				  * Only used to make sure we only take entries
+				  * from a single context. Never dereferenced.
+				  */
+	struct mutex de_mutex;
+	int pos;		 /* Expected ctx->pos */
+	struct list_head entries;
+};
+
 struct cached_fid {
 	bool is_valid:1;	/* Do we have a useable root fid */
 	bool file_all_info_is_valid:1;
@@ -1052,6 +1073,7 @@ struct cached_fid {
 	struct dentry *dentry;
 	struct work_struct lease_break;
 	struct smb2_file_all_info file_all_info;
+	struct cached_dirents dirents;
 };
 
 /*
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index afaf59c22193..7fef08add3bc 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -114,6 +114,8 @@ tconInfoAlloc(void)
 		kfree(ret_buf);
 		return NULL;
 	}
+	INIT_LIST_HEAD(&ret_buf->crfid.dirents.entries);
+	mutex_init(&ret_buf->crfid.dirents.de_mutex);
 
 	atomic_inc(&tconInfoAllocCount);
 	ret_buf->status = TID_NEW;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 1929e80c09ee..e71c7b3941b4 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -840,9 +840,109 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
 	return rc;
 }
 
+static bool emit_cached_dirents(struct cached_dirents *cde,
+				struct dir_context *ctx)
+{
+	struct cached_dirent *dirent;
+	int rc;
+
+	list_for_each_entry(dirent, &cde->entries, entry) {
+		if (ctx->pos >= dirent->pos)
+			continue;
+		ctx->pos = dirent->pos;
+		rc = dir_emit(ctx, dirent->name, dirent->namelen,
+			      dirent->fattr.cf_uniqueid,
+			      dirent->fattr.cf_dtype);
+		if (!rc)
+			return rc;
+	}
+	return true;
+}
+
+static void update_cached_dirents_count(struct cached_dirents *cde,
+					struct dir_context *ctx)
+{
+	if (cde->ctx != ctx)
+		return;
+	if (cde->is_valid || cde->is_failed)
+		return;
+
+	cde->pos++;
+}
+
+static void finished_cached_dirents_count(struct cached_dirents *cde,
+					struct dir_context *ctx)
+{
+	if (cde->ctx != ctx)
+		return;
+	if (cde->is_valid || cde->is_failed)
+		return;
+	if (ctx->pos != cde->pos)
+		return;
+
+	cde->is_valid = 1;
+}
+
+static void add_cached_dirent(struct cached_dirents *cde,
+			      struct dir_context *ctx,
+			      const char *name, int namelen,
+			      struct cifs_fattr *fattr)
+{
+	struct cached_dirent *de;
+
+	if (cde->ctx != ctx)
+		return;
+	if (cde->is_valid || cde->is_failed)
+		return;
+	if (ctx->pos != cde->pos) {
+		cde->is_failed = 1;
+		return;
+	}
+	de = kzalloc(sizeof(*de), GFP_ATOMIC);
+	if (de == NULL) {
+		cde->is_failed = 1;
+		return;
+	}
+	de->namelen = namelen;
+	de->name = kstrndup(name, namelen, GFP_ATOMIC);
+	if (de->name == NULL) {
+		kfree(de);
+		cde->is_failed = 1;
+		return;
+	}
+	de->pos = ctx->pos;
+
+	memcpy(&de->fattr, fattr, sizeof(struct cifs_fattr));
+
+	list_add_tail(&de->entry, &cde->entries);
+}
+
+static bool cifs_dir_emit(struct dir_context *ctx,
+			  const char *name, int namelen,
+			  struct cifs_fattr *fattr,
+			  struct cached_fid *cfid)
+{
+	bool rc;
+	ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
+
+	rc = dir_emit(ctx, name, namelen, ino, fattr->cf_dtype);
+	if (!rc)
+		return rc;
+
+	if (cfid) {
+		mutex_lock(&cfid->dirents.de_mutex);
+		add_cached_dirent(&cfid->dirents, ctx, name, namelen,
+				  fattr);
+		mutex_unlock(&cfid->dirents.de_mutex);
+	}
+
+	return rc;
+}
+
 static int cifs_filldir(char *find_entry, struct file *file,
-		struct dir_context *ctx,
-		char *scratch_buf, unsigned int max_len)
+			struct dir_context *ctx,
+			char *scratch_buf, unsigned int max_len,
+			struct cached_fid *cfid)
 {
 	struct cifsFileInfo *file_info = file->private_data;
 	struct super_block *sb = file_inode(file)->i_sb;
@@ -851,7 +951,6 @@ static int cifs_filldir(char *find_entry, struct file *file,
 	struct cifs_fattr fattr;
 	struct qstr name;
 	int rc = 0;
-	ino_t ino;
 
 	rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
 			      file_info->srch_inf.unicode);
@@ -931,8 +1030,8 @@ static int cifs_filldir(char *find_entry, struct file *file,
 
 	cifs_prime_dcache(file_dentry(file), &name, &fattr);
 
-	ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
-	return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
+	return !cifs_dir_emit(ctx, name.name, name.len,
+			      &fattr, cfid);
 }
 
 
@@ -941,8 +1040,9 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
 	int rc = 0;
 	unsigned int xid;
 	int i;
+	struct tcon_link *tlink = NULL;
 	struct cifs_tcon *tcon;
-	struct cifsFileInfo *cifsFile = NULL;
+	struct cifsFileInfo *cifsFile;
 	char *current_entry;
 	int num_to_fill = 0;
 	char *tmp_buf = NULL;
@@ -950,6 +1050,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
 	unsigned int max_len;
 	const char *full_path;
 	void *page = alloc_dentry_path();
+	struct cached_fid *cfid = NULL;
+	struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
 
 	xid = get_xid();
 
@@ -959,6 +1061,56 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
 		goto rddir2_exit;
 	}
 
+	if (file->private_data == NULL) {
+		tlink = cifs_sb_tlink(cifs_sb);
+		if (IS_ERR(tlink))
+			goto cache_not_found;
+		tcon = tlink_tcon(tlink);
+	} else {
+		cifsFile = file->private_data;
+		tcon = tlink_tcon(cifsFile->tlink);
+	}
+	
+	rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid);
+	cifs_put_tlink(tlink);
+	if (rc)
+		goto cache_not_found;
+
+	mutex_lock(&cfid->dirents.de_mutex);
+	/*
+	 * If this was reading from the start of the directory
+	 * we need to initialize scanning and storing the
+	 * directory content.
+	 */
+	if (ctx->pos == 0 && cfid->dirents.ctx == NULL) {
+		cfid->dirents.ctx = ctx;
+		cfid->dirents.pos = 2;
+	}
+	/*
+	 * If we already have the entire directory cached then
+	 * we can just serve the cache.
+	 */
+	if (cfid->dirents.is_valid) {
+		if (!dir_emit_dots(file, ctx)){
+			mutex_unlock(&cfid->dirents.de_mutex);
+			goto rddir2_exit;
+		}
+		emit_cached_dirents(&cfid->dirents, ctx);
+		mutex_unlock(&cfid->dirents.de_mutex);
+		goto rddir2_exit;
+	}
+	mutex_unlock(&cfid->dirents.de_mutex);
+
+	/* Drop the cache while calling initiate_cifs_search and
+	 * find_cifs_entry in case there will be reconnects during
+	 * query_directory.
+	 */
+	if (cfid) {
+		close_cached_dir(cfid);
+		cfid = NULL;
+	}
+
+ cache_not_found:	
 	/*
 	 * Ensure FindFirst doesn't fail before doing filldir() for '.' and
 	 * '..'. Otherwise we won't be able to notify VFS in case of failure.
@@ -977,7 +1129,6 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
 		is in current search buffer?
 		if it before then restart search
 		if after then keep searching till find it */
-
 	cifsFile = file->private_data;
 	if (cifsFile->srch_inf.endOfSearch) {
 		if (cifsFile->srch_inf.emptyDir) {
@@ -993,12 +1144,18 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
 	tcon = tlink_tcon(cifsFile->tlink);
 	rc = find_cifs_entry(xid, tcon, ctx->pos, file, full_path,
 			     &current_entry, &num_to_fill);
+	open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid);
 	if (rc) {
 		cifs_dbg(FYI, "fce error %d\n", rc);
 		goto rddir2_exit;
 	} else if (current_entry != NULL) {
 		cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
 	} else {
+		if (cfid) {
+			mutex_lock(&cfid->dirents.de_mutex);
+			finished_cached_dirents_count(&cfid->dirents, ctx);
+			mutex_unlock(&cfid->dirents.de_mutex);
+		}
 		cifs_dbg(FYI, "Could not find entry\n");
 		goto rddir2_exit;
 	}
@@ -1028,7 +1185,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
 		 */
 		*tmp_buf = 0;
 		rc = cifs_filldir(current_entry, file, ctx,
-				  tmp_buf, max_len);
+				  tmp_buf, max_len, cfid);
 		if (rc) {
 			if (rc > 0)
 				rc = 0;
@@ -1036,6 +1193,12 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
 		}
 
 		ctx->pos++;
+		if (cfid) {
+			mutex_lock(&cfid->dirents.de_mutex);
+			update_cached_dirents_count(&cfid->dirents, ctx);
+			mutex_unlock(&cfid->dirents.de_mutex);
+		}
+
 		if (ctx->pos ==
 			cifsFile->srch_inf.index_of_last_entry) {
 			cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
@@ -1050,6 +1213,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
 	kfree(tmp_buf);
 
 rddir2_exit:
+	if (cfid)
+		close_cached_dir(cfid);
 	free_dentry_path(page);
 	free_xid(xid);
 	return rc;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index cbe56ed35694..e59503733a27 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -699,6 +699,7 @@ smb2_close_cached_fid(struct kref *ref)
 {
 	struct cached_fid *cfid = container_of(ref, struct cached_fid,
 					       refcount);
+	struct cached_dirent *dirent, *q;
 
 	if (cfid->is_valid) {
 		cifs_dbg(FYI, "clear cached root file handle\n");
@@ -718,6 +719,21 @@ smb2_close_cached_fid(struct kref *ref)
 		dput(cfid->dentry);
 		cfid->dentry = NULL;
 	}
+	/*
+	 * Delete all cached dirent names
+	 */
+	mutex_lock(&cfid->dirents.de_mutex);
+	list_for_each_entry_safe(dirent, q, &cfid->dirents.entries, entry) {
+		list_del(&dirent->entry);
+		kfree(dirent->name);
+		kfree(dirent);
+	}
+	cfid->dirents.is_valid = 0;
+	cfid->dirents.is_failed = 0;
+	cfid->dirents.ctx = NULL;
+	cfid->dirents.pos = 0;
+	mutex_unlock(&cfid->dirents.de_mutex);
+	
 }
 
 void close_cached_dir(struct cached_fid *cfid)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] cifs: cache the dirents for entries in a cached directory
  2022-05-09 23:42 ` [PATCH 4/4] cifs: cache the dirents for entries in a cached directory Ronnie Sahlberg
@ 2022-05-10 22:57   ` Enzo Matsumiya
  2022-05-11  0:41     ` Leif Sahlberg
  0 siblings, 1 reply; 9+ messages in thread
From: Enzo Matsumiya @ 2022-05-10 22:57 UTC (permalink / raw)
  To: Ronnie Sahlberg; +Cc: linux-cifs, Steve French

Hi Ronnie,

On 05/10, Ronnie Sahlberg wrote:
>+struct cached_dirents {
>+	bool is_valid:1;
>+	bool is_failed:1;

Just as I commented in the other thread, having both fields above confuses me.
Shouldn't using is_valid/!is_valid be enough?


Cheers,

Enzo

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] cifs: cache the dirents for entries in a cached directory
  2022-05-10 22:57   ` Enzo Matsumiya
@ 2022-05-11  0:41     ` Leif Sahlberg
  2022-05-24 19:38       ` Steve French
  0 siblings, 1 reply; 9+ messages in thread
From: Leif Sahlberg @ 2022-05-11  0:41 UTC (permalink / raw)
  To: Enzo Matsumiya; +Cc: linux-cifs, Steve French

On Wed, May 11, 2022 at 8:57 AM Enzo Matsumiya <ematsumiya@suse.de> wrote:
>
> Hi Ronnie,
>
> On 05/10, Ronnie Sahlberg wrote:
> >+struct cached_dirents {
> >+      bool is_valid:1;
> >+      bool is_failed:1;
>
> Just as I commented in the other thread, having both fields above confuses me.
> Shouldn't using is_valid/!is_valid be enough?

We need two because semantically there are three states we need to describe:
1, we have successfully cached all entries and cache is valid
2, we are in the process of building the cache, and the cache might
eventually become complete and valid
3, we are in the process of building the cache, but there has been a
failure and the cache will never be complete or valid

>
>
> Cheers,
>
> Enzo
>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] cifs: set the CREATE_NOT_FILE when opening the directory in use_cached_dir()
  2022-05-09 23:42 ` [PATCH 3/4] cifs: set the CREATE_NOT_FILE when opening the directory in use_cached_dir() Ronnie Sahlberg
@ 2022-05-21 17:26   ` Steve French
  0 siblings, 0 replies; 9+ messages in thread
From: Steve French @ 2022-05-21 17:26 UTC (permalink / raw)
  To: Ronnie Sahlberg; +Cc: linux-cifs

tentatively merged the first 3 of the series (still looking at patch
4) pending testing

On Mon, May 9, 2022 at 6:42 PM Ronnie Sahlberg <lsahlber@redhat.com> wrote:
>
> This enforces that we can only do this for directories and not normal files
> or else the server will return an error.
> This means that we will have conditionally check IF the path refers
> to a directory or not in all the call-sites where we are unsure.
> Right now this check is for "" i.e. root.
>
> Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
> Reviewed-by: Enzo Matsumiya <ematsumiya@suse.de>
> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> ---
>  fs/cifs/smb2inode.c | 5 ++++-
>  fs/cifs/smb2ops.c   | 5 +++--
>  2 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
> index fe5bfa245fa7..0c3e4d2c6207 100644
> --- a/fs/cifs/smb2inode.c
> +++ b/fs/cifs/smb2inode.c
> @@ -514,8 +514,11 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
>         if (smb2_data == NULL)
>                 return -ENOMEM;
>
> +       if (strcmp(full_path, ""))
> +               rc = -ENOENT;
> +       else
> +               rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid);
>         /* If it is a root and its handle is cached then use it */
> -       rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid);
>         if (!rc) {
>                 if (tcon->crfid.file_all_info_is_valid) {
>                         move_smb2_info_to_cifs(data,
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 2c93ee27d54d..cbe56ed35694 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -825,7 +825,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
>         rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
>
>         oparms.tcon = tcon;
> -       oparms.create_options = cifs_create_options(cifs_sb, 0);
> +       oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE);
>         oparms.desired_access = FILE_READ_ATTRIBUTES;
>         oparms.disposition = FILE_OPEN;
>         oparms.fid = pfid;
> @@ -2696,7 +2696,8 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
>         resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
>         memset(rsp_iov, 0, sizeof(rsp_iov));
>
> -       rc = open_cached_dir(xid, tcon, path, cifs_sb, &cfid);
> +       if (!strcmp(path, ""))
> +               rc = open_cached_dir(xid, tcon, path, cifs_sb, &cfid);
>
>         memset(&open_iov, 0, sizeof(open_iov));
>         rqst[0].rq_iov = open_iov;
> --
> 2.30.2
>


-- 
Thanks,

Steve

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] cifs: cache the dirents for entries in a cached directory
  2022-05-11  0:41     ` Leif Sahlberg
@ 2022-05-24 19:38       ` Steve French
  0 siblings, 0 replies; 9+ messages in thread
From: Steve French @ 2022-05-24 19:38 UTC (permalink / raw)
  To: Leif Sahlberg; +Cc: Enzo Matsumiya, linux-cifs

tentatively merged this patch (and the 3 earlier ones are already in
for-next) into cifs-2.6.git for-next pending testing.

Did minor whitespace cleanup

On Tue, May 10, 2022 at 7:41 PM Leif Sahlberg <lsahlber@redhat.com> wrote:
>
> On Wed, May 11, 2022 at 8:57 AM Enzo Matsumiya <ematsumiya@suse.de> wrote:
> >
> > Hi Ronnie,
> >
> > On 05/10, Ronnie Sahlberg wrote:
> > >+struct cached_dirents {
> > >+      bool is_valid:1;
> > >+      bool is_failed:1;
> >
> > Just as I commented in the other thread, having both fields above confuses me.
> > Shouldn't using is_valid/!is_valid be enough?
>
> We need two because semantically there are three states we need to describe:
> 1, we have successfully cached all entries and cache is valid
> 2, we are in the process of building the cache, and the cache might
> eventually become complete and valid
> 3, we are in the process of building the cache, but there has been a
> failure and the cache will never be complete or valid
>
> >
> >
> > Cheers,
> >
> > Enzo
> >
>


-- 
Thanks,

Steve

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-05-24 19:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-09 23:42 Cifs: cache entries for the cached directory Ronnie Sahlberg
2022-05-09 23:42 ` [PATCH 1/4] cifs: move definition of cifs_fattr earlier in cifsglob.h Ronnie Sahlberg
2022-05-09 23:42 ` [PATCH 2/4] cifs: check for smb1 in open_cached_dir() Ronnie Sahlberg
2022-05-09 23:42 ` [PATCH 3/4] cifs: set the CREATE_NOT_FILE when opening the directory in use_cached_dir() Ronnie Sahlberg
2022-05-21 17:26   ` Steve French
2022-05-09 23:42 ` [PATCH 4/4] cifs: cache the dirents for entries in a cached directory Ronnie Sahlberg
2022-05-10 22:57   ` Enzo Matsumiya
2022-05-11  0:41     ` Leif Sahlberg
2022-05-24 19:38       ` Steve French

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.