Merge tag '6.9-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 Mar 2024 02:14:28 +0000 (19:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 Mar 2024 02:14:28 +0000 (19:14 -0700)
Pull smb client fixes from Steve French:

 - Various get_inode_info_fixes

 - Fix for querying xattrs of cached dirs

 - Four minor cleanup fixes (including adding some header corrections
   and a missing flag)

 - Performance improvement for deferred close

 - Two query interface fixes

* tag '6.9-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
  smb311: additional compression flag defined in updated protocol spec
  smb311: correct incorrect offset field in compression header
  cifs: Move some extern decls from .c files to .h
  cifs: remove redundant variable assignment
  cifs: fixes for get_inode_info
  cifs: open_cached_dir(): add FILE_READ_EA to desired access
  cifs: reduce warning log level for server not advertising interfaces
  cifs: make sure server interfaces are requested only for SMB3+
  cifs: defer close file handles having RH lease

fs/smb/client/cached_dir.c
fs/smb/client/cifsfs.c
fs/smb/client/cifsglob.h
fs/smb/client/connect.c
fs/smb/client/file.c
fs/smb/client/inode.c
fs/smb/client/misc.c
fs/smb/client/sess.c
fs/smb/client/smb2ops.c
fs/smb/client/smb2pdu.c
fs/smb/common/smb2pdu.h

index 3de5047a7ff988c2049350e464771e912b12894e..a0017724d5239312c14644bd15d2867880337d91 100644 (file)
@@ -239,7 +239,8 @@ replay_again:
                .tcon = tcon,
                .path = path,
                .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE),
-               .desired_access =  FILE_READ_DATA | FILE_READ_ATTRIBUTES,
+               .desired_access =  FILE_READ_DATA | FILE_READ_ATTRIBUTES |
+                                  FILE_READ_EA,
                .disposition = FILE_OPEN,
                .fid = pfid,
                .replay = !!(retries),
index 81d9aafd2210afb64e7fbcb58a1da901048dc34d..aa6f1ecb7c0e8fc11f9b1fb830d8c0ca8071b631 100644 (file)
@@ -151,10 +151,6 @@ MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be "
                                  "vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker"
                                  " and less secure. Default: n/N/0");
 
-extern mempool_t *cifs_sm_req_poolp;
-extern mempool_t *cifs_req_poolp;
-extern mempool_t *cifs_mid_poolp;
-
 struct workqueue_struct        *cifsiod_wq;
 struct workqueue_struct        *decrypt_wq;
 struct workqueue_struct        *fileinfo_put_wq;
index 8be62ed053a25e4c56018641553d10314d0f1563..7ed9d05f6890b4d40cb11a7b8d7384c6e0111461 100644 (file)
@@ -355,6 +355,9 @@ struct smb_version_operations {
        /* informational QFS call */
        void (*qfs_tcon)(const unsigned int, struct cifs_tcon *,
                         struct cifs_sb_info *);
+       /* query for server interfaces */
+       int (*query_server_interfaces)(const unsigned int, struct cifs_tcon *,
+                                      bool);
        /* check if a path is accessible or not */
        int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
                                  struct cifs_sb_info *, const char *);
@@ -2104,6 +2107,8 @@ extern struct workqueue_struct *cifsoplockd_wq;
 extern struct workqueue_struct *deferredclose_wq;
 extern __u32 cifs_lock_secret;
 
+extern mempool_t *cifs_sm_req_poolp;
+extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
 
 /* Operations for different SMB versions */
index 86ae578904a269be0fd17c7d110dc1548ef2f203..9b85b5341822e73d9a4746a027f50121f01873c3 100644 (file)
@@ -52,9 +52,6 @@
 #include "fs_context.h"
 #include "cifs_swn.h"
 
-extern mempool_t *cifs_req_poolp;
-extern bool disable_legacy_dialects;
-
 /* FIXME: should these be tunable? */
 #define TLINK_ERROR_EXPIRE     (1 * HZ)
 #define TLINK_IDLE_EXPIRE      (600 * HZ)
@@ -123,12 +120,16 @@ static void smb2_query_server_interfaces(struct work_struct *work)
        struct cifs_tcon *tcon = container_of(work,
                                        struct cifs_tcon,
                                        query_interfaces.work);
+       struct TCP_Server_Info *server = tcon->ses->server;
 
        /*
         * query server network interfaces, in case they change
         */
+       if (!server->ops->query_server_interfaces)
+               return;
+
        xid = get_xid();
-       rc = SMB3_request_interfaces(xid, tcon, false);
+       rc = server->ops->query_server_interfaces(xid, tcon, false);
        free_xid(xid);
 
        if (rc) {
index ec25d3c3e1ee3985152bec6c8e66a801917d9c0e..16aadce492b2ec67b973c8726e7cefd4857197d5 100644 (file)
@@ -486,7 +486,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
        cfile->uid = current_fsuid();
        cfile->dentry = dget(dentry);
        cfile->f_flags = file->f_flags;
-       cfile->status_file_deleted = false;
        cfile->invalidHandle = false;
        cfile->deferred_close_scheduled = false;
        cfile->tlink = cifs_get_tlink(tlink);
@@ -1073,6 +1072,19 @@ void smb2_deferred_work_close(struct work_struct *work)
        _cifsFileInfo_put(cfile, true, false);
 }
 
+static bool
+smb2_can_defer_close(struct inode *inode, struct cifs_deferred_close *dclose)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct cifsInodeInfo *cinode = CIFS_I(inode);
+
+       return (cifs_sb->ctx->closetimeo && cinode->lease_granted && dclose &&
+                       (cinode->oplock == CIFS_CACHE_RHW_FLG ||
+                        cinode->oplock == CIFS_CACHE_RH_FLG) &&
+                       !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags));
+
+}
+
 int cifs_close(struct inode *inode, struct file *file)
 {
        struct cifsFileInfo *cfile;
@@ -1086,10 +1098,8 @@ int cifs_close(struct inode *inode, struct file *file)
                cfile = file->private_data;
                file->private_data = NULL;
                dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
-               if ((cifs_sb->ctx->closetimeo && cinode->oplock == CIFS_CACHE_RHW_FLG)
-                   && cinode->lease_granted &&
-                   !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) &&
-                   dclose && !(cfile->status_file_deleted)) {
+               if ((cfile->status_file_deleted == false) &&
+                   (smb2_can_defer_close(inode, dclose))) {
                        if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
                                inode_set_mtime_to_ts(inode,
                                                      inode_set_ctime_current(inode));
index 8177ec59afeef6bfbb9df666836bb9496de4b6c4..d28ab0af60493623f3d209c4f36b5ccea14973bb 100644 (file)
@@ -401,7 +401,6 @@ cifs_get_file_info_unix(struct file *filp)
                cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
        } else if (rc == -EREMOTE) {
                cifs_create_junction_fattr(&fattr, inode->i_sb);
-               rc = 0;
        } else
                goto cifs_gfiunix_out;
 
@@ -820,8 +819,10 @@ cifs_get_file_info(struct file *filp)
        void *page = alloc_dentry_path();
        const unsigned char *path;
 
-       if (!server->ops->query_file_info)
+       if (!server->ops->query_file_info) {
+               free_dentry_path(page);
                return -ENOSYS;
+       }
 
        xid = get_xid();
        rc = server->ops->query_file_info(xid, tcon, cfile, &data);
@@ -835,8 +836,8 @@ cifs_get_file_info(struct file *filp)
                }
                path = build_path_from_dentry(dentry, page);
                if (IS_ERR(path)) {
-                       free_dentry_path(page);
-                       return PTR_ERR(path);
+                       rc = PTR_ERR(path);
+                       goto cgfi_exit;
                }
                cifs_open_info_to_fattr(&fattr, &data, inode->i_sb);
                if (fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
@@ -844,7 +845,6 @@ cifs_get_file_info(struct file *filp)
                break;
        case -EREMOTE:
                cifs_create_junction_fattr(&fattr, inode->i_sb);
-               rc = 0;
                break;
        case -EOPNOTSUPP:
        case -EINVAL:
@@ -1009,7 +1009,6 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
        struct kvec rsp_iov, *iov = NULL;
        int rsp_buftype = CIFS_NO_BUFFER;
        u32 tag = data->reparse.tag;
-       struct inode *inode = NULL;
        int rc = 0;
 
        if (!tag && server->ops->query_reparse_point) {
@@ -1049,12 +1048,8 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
 
        if (tcon->posix_extensions)
                smb311_posix_info_to_fattr(fattr, data, sb);
-       else {
+       else
                cifs_open_info_to_fattr(fattr, data, sb);
-               inode = cifs_iget(sb, fattr);
-               if (inode && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
-                       cifs_mark_open_handles_for_deleted_file(inode, full_path);
-       }
 out:
        fattr->cf_cifstag = data->reparse.tag;
        free_rsp_buf(rsp_buftype, rsp_iov.iov_base);
@@ -1109,9 +1104,9 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
                                                   full_path, fattr);
                } else {
                        cifs_open_info_to_fattr(fattr, data, sb);
-                       if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
-                               cifs_mark_open_handles_for_deleted_file(*inode, full_path);
                }
+               if (!rc && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
+                       cifs_mark_open_handles_for_deleted_file(*inode, full_path);
                break;
        case -EREMOTE:
                /* DFS link, no metadata available on this server */
@@ -1340,6 +1335,8 @@ int smb311_posix_get_inode_info(struct inode **inode,
                goto out;
 
        rc = update_inode_info(sb, &fattr, inode);
+       if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
+               cifs_mark_open_handles_for_deleted_file(*inode, full_path);
 out:
        kfree(fattr.cf_symlink_target);
        return rc;
@@ -1501,6 +1498,9 @@ iget_root:
                goto out;
        }
 
+       if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
+               cifs_mark_open_handles_for_deleted_file(inode, path);
+
        if (rc && tcon->pipe) {
                cifs_dbg(FYI, "ipc connection - fake read inode\n");
                spin_lock(&inode->i_lock);
index 9428a0db77183ffc4ab7cc4164d19f7c5409449a..c3771fc81328ff12d7d075cadab77c97b16b7e05 100644 (file)
@@ -27,9 +27,6 @@
 #include "fs_context.h"
 #include "cached_dir.h"
 
-extern mempool_t *cifs_sm_req_poolp;
-extern mempool_t *cifs_req_poolp;
-
 /* The xid serves as a useful identifier for each incoming vfs request,
    in a similar way to the mid which is useful to track each sent smb,
    and CurrentXid can also provide a running counter (although it
index 8f37373fd33344bacbf4d492f6115d9396573379..3216f786908fbb2ac8345cf5929fadf8ec6920d4 100644 (file)
@@ -230,7 +230,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
                spin_lock(&ses->iface_lock);
                if (!ses->iface_count) {
                        spin_unlock(&ses->iface_lock);
-                       cifs_dbg(VFS, "server %s does not advertise interfaces\n",
+                       cifs_dbg(ONCE, "server %s does not advertise interfaces\n",
                                      ses->server->hostname);
                        break;
                }
@@ -396,7 +396,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
        spin_lock(&ses->iface_lock);
        if (!ses->iface_count) {
                spin_unlock(&ses->iface_lock);
-               cifs_dbg(VFS, "server %s does not advertise interfaces\n", ses->server->hostname);
+               cifs_dbg(ONCE, "server %s does not advertise interfaces\n", ses->server->hostname);
                return;
        }
 
index 6ee22d0dbc006112c23ce6fea483a4db9cd00cf5..2ed456948f34ca0cd88dbe626429694456a681e2 100644 (file)
@@ -5290,6 +5290,7 @@ struct smb_version_operations smb30_operations = {
        .tree_connect = SMB2_tcon,
        .tree_disconnect = SMB2_tdis,
        .qfs_tcon = smb3_qfs_tcon,
+       .query_server_interfaces = SMB3_request_interfaces,
        .is_path_accessible = smb2_is_path_accessible,
        .can_echo = smb2_can_echo,
        .echo = SMB2_echo,
@@ -5405,6 +5406,7 @@ struct smb_version_operations smb311_operations = {
        .tree_connect = SMB2_tcon,
        .tree_disconnect = SMB2_tdis,
        .qfs_tcon = smb3_qfs_tcon,
+       .query_server_interfaces = SMB3_request_interfaces,
        .is_path_accessible = smb2_is_path_accessible,
        .can_echo = smb2_can_echo,
        .echo = SMB2_echo,
index e5e6b14f8cae37bb6ac470c457e34fcf437458a1..3ea688558e6c9b96f454e29197023ec74f274e2a 100644 (file)
@@ -409,14 +409,15 @@ skip_sess_setup:
        spin_unlock(&ses->ses_lock);
 
        if (!rc &&
-           (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
+           (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) &&
+           server->ops->query_server_interfaces) {
                mutex_unlock(&ses->session_mutex);
 
                /*
                 * query server network interfaces, in case they change
                 */
                xid = get_xid();
-               rc = SMB3_request_interfaces(xid, tcon, false);
+               rc = server->ops->query_server_interfaces(xid, tcon, false);
                free_xid(xid);
 
                if (rc == -EOPNOTSUPP && ses->chan_count > 1) {
index 20784f76a60455504e6febd6bd3d22f9ce43bee2..1b594307c9d5a01e0b9d62b47b331dbd31c6dfaf 100644 (file)
@@ -227,7 +227,7 @@ struct smb2_compression_hdr {
        __le32 OriginalCompressedSegmentSize;
        __le16 CompressionAlgorithm;
        __le16 Flags;
-       __le16 Offset; /* this is the size of the uncompressed SMB2 header below */
+       __le32 Offset; /* this is the size of the uncompressed SMB2 header below */
        /* uncompressed SMB2 header (READ or WRITE) goes here */
        /* compressed data goes here */
 } __packed;
@@ -280,15 +280,16 @@ struct smb3_blob_data {
 #define SE_GROUP_RESOURCE              0x20000000
 #define SE_GROUP_LOGON_ID              0xC0000000
 
-/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */
-
 struct sid_array_data {
        __le16 SidAttrCount;
        /* SidAttrList - array of sid_attr_data structs */
 } __packed;
 
-struct luid_attr_data {
-
+/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */
+struct sid_attr_data {
+       __le16 BlobSize;
+       __u8 BlobData[];
+       /* __le32 Attr */
 } __packed;
 
 /*
@@ -502,6 +503,7 @@ struct smb2_encryption_neg_context {
 #define SMB3_COMPRESS_LZ77_HUFF        cpu_to_le16(0x0003)
 /* Pattern scanning algorithm See MS-SMB2 3.1.4.4.1 */
 #define SMB3_COMPRESS_PATTERN  cpu_to_le16(0x0004) /* Pattern_V1 */
+#define SMB3_COMPRESS_LZ4      cpu_to_le16(0x0005)
 
 /* Compression Flags */
 #define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE                cpu_to_le32(0x00000000)