cifs: Do not access tcon->cfids->cfid directly from is_path_accessible
authorRonnie Sahlberg <lsahlber@redhat.com>
Fri, 12 Aug 2022 00:51:18 +0000 (19:51 -0500)
committerSteve French <stfrench@microsoft.com>
Fri, 12 Aug 2022 22:40:15 +0000 (17:40 -0500)
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>
fs/cifs/cached_dir.c
fs/cifs/cached_dir.h
fs/cifs/readdir.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c

index 78e8deb82a0a11f3b48ae57ee2411699af352881..b401339f6e738a390891ec99ace9047400bce649 100644 (file)
@@ -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;
 
index 89c0343d7e266762f150bae4d7fcea8bf0ea7640..bd262dc8b179a42ca575b80434cd40863e8b3f5e 100644 (file)
@@ -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);
index a06072ae6c7e229b5f2b877c0a06e6a7f58b6580..2eece8a07c1124ea298964559824e0228d508211 100644 (file)
@@ -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;
index 9696184a09e39f66b4e5baca0ad776d28375a92f..b83f59051b26f984f742338d6746f97865e4b9f7 100644 (file)
@@ -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) {
index 6507761a8040ca25b70fb74e5c452a6218933300..f406af59688775904d4135803f291b8701a30a8b 100644 (file)
@@ -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;