summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRonnie Sahlberg <lsahlber@redhat.com>2022-08-11 19:51:18 -0500
committerSteve French <stfrench@microsoft.com>2022-08-12 17:40:15 -0500
commit7eb59a98701d3113671b513593bb489cc76f58d2 (patch)
tree307b4338c95b6a53760256c015d3ecdf4b898075
parenta63ec83c462b5b1439f71ace751e8985dfb3fcab (diff)
downloadlinux-7eb59a98701d3113671b513593bb489cc76f58d2.tar.bz2
cifs: Do not access tcon->cfids->cfid directly from is_path_accessible
cfids will soon keep a list of cached fids so we should not access this directly from outside of cached_dir.c Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/cifs/cached_dir.c10
-rw-r--r--fs/cifs/cached_dir.h2
-rw-r--r--fs/cifs/readdir.c4
-rw-r--r--fs/cifs/smb2inode.c2
-rw-r--r--fs/cifs/smb2ops.c19
5 files changed, 25 insertions, 12 deletions
diff --git a/fs/cifs/cached_dir.c b/fs/cifs/cached_dir.c
index 78e8deb82a0a..b401339f6e73 100644
--- a/fs/cifs/cached_dir.c
+++ b/fs/cifs/cached_dir.c
@@ -16,9 +16,9 @@
* If error then *cfid is not initialized.
*/
int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
- const char *path,
- struct cifs_sb_info *cifs_sb,
- struct cached_fid **ret_cfid)
+ const char *path,
+ struct cifs_sb_info *cifs_sb,
+ bool lookup_only, struct cached_fid **ret_cfid)
{
struct cifs_ses *ses;
struct TCP_Server_Info *server;
@@ -68,9 +68,11 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
* cifs_mark_open_files_invalid() which takes the lock again
* thus causing a deadlock
*/
-
mutex_unlock(&cfid->fid_mutex);
+ if (lookup_only)
+ return -ENOENT;
+
if (smb3_encryption_required(tcon))
flags |= CIFS_TRANSFORM_REQ;
diff --git a/fs/cifs/cached_dir.h b/fs/cifs/cached_dir.h
index 89c0343d7e26..bd262dc8b179 100644
--- a/fs/cifs/cached_dir.h
+++ b/fs/cifs/cached_dir.h
@@ -50,7 +50,7 @@ extern void free_cached_dir(struct cifs_tcon *tcon);
extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
const char *path,
struct cifs_sb_info *cifs_sb,
- struct cached_fid **cfid);
+ bool lookup_only, struct cached_fid **cfid);
extern int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
struct dentry *dentry,
struct cached_fid **cfid);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index a06072ae6c7e..2eece8a07c11 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -1072,7 +1072,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
tcon = tlink_tcon(cifsFile->tlink);
}
- rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid);
+ rc = open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid);
cifs_put_tlink(tlink);
if (rc)
goto cache_not_found;
@@ -1143,7 +1143,7 @@ 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);
+ open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid);
if (rc) {
cifs_dbg(FYI, "fce error %d\n", rc);
goto rddir2_exit;
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 9696184a09e3..b83f59051b26 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -516,7 +516,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
if (strcmp(full_path, ""))
rc = -ENOENT;
else
- rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid);
+ rc = open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid);
/* If it is a root and its handle is cached then use it */
if (!rc) {
if (cfid->file_all_info_is_valid) {
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 6507761a8040..f406af596887 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -720,7 +720,7 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = open_cached_dir(xid, tcon, "", cifs_sb, &cfid);
+ rc = open_cached_dir(xid, tcon, "", cifs_sb, false, &cfid);
if (rc == 0)
memcpy(&fid, &cfid->fid, sizeof(struct cifs_fid));
else
@@ -783,9 +783,16 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
struct cifs_open_parms oparms;
struct cifs_fid fid;
+ struct cached_fid *cfid;
- if ((*full_path == 0) && tcon->cfid->is_valid)
- return 0;
+ rc = open_cached_dir(xid, tcon, full_path, cifs_sb, true, &cfid);
+ if (!rc) {
+ if (cfid->is_valid) {
+ close_cached_dir(cfid);
+ return 0;
+ }
+ close_cached_dir(cfid);
+ }
utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
if (!utf16_path)
@@ -2430,8 +2437,12 @@ 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));
+ /*
+ * We can only call this for things we know are directories.
+ */
if (!strcmp(path, ""))
- open_cached_dir(xid, tcon, path, cifs_sb, &cfid); /* cfid null if open dir failed */
+ open_cached_dir(xid, tcon, path, cifs_sb, false,
+ &cfid); /* cfid null if open dir failed */
memset(&open_iov, 0, sizeof(open_iov));
rqst[0].rq_iov = open_iov;