]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
smb: client: introduce cifs_sfu_make_node()
authorPaulo Alcantara <pc@manguebit.com>
Tue, 21 Nov 2023 23:12:55 +0000 (20:12 -0300)
committerSteve French <stfrench@microsoft.com>
Thu, 23 Nov 2023 17:46:05 +0000 (11:46 -0600)
Remove duplicate code and add new helper for creating special files in
SFU (Services for UNIX) format that can be shared by SMB1+ code.

Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cifsproto.h
fs/smb/client/smb1ops.c
fs/smb/client/smb2ops.c

index c00f844205590f38e32e8cdd62ce729c9f3c5e6c..46feaa0880bdf18f54eff409694c7d06c501ebf4 100644 (file)
@@ -668,6 +668,9 @@ char *extract_sharename(const char *unc);
 int parse_reparse_point(struct reparse_data_buffer *buf,
                        u32 plen, struct cifs_sb_info *cifs_sb,
                        bool unicode, struct cifs_open_info_data *data);
+int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
+                      struct dentry *dentry, struct cifs_tcon *tcon,
+                      const char *full_path, umode_t mode, dev_t dev);
 
 #ifdef CONFIG_CIFS_DFS_UPCALL
 static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
index 64e25233e85deb2062571c28c89bda791fc2ec0b..a9eaba8083b0d6b2745ebedb1d3d4705c0f4809d 100644 (file)
@@ -1041,15 +1041,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct inode *newinode = NULL;
-       int rc = -EPERM;
-       struct cifs_open_info_data buf = {};
-       struct cifs_io_parms io_parms;
-       __u32 oplock = 0;
-       struct cifs_fid fid;
-       struct cifs_open_parms oparms;
-       unsigned int bytes_written;
-       struct win_dev *pdev;
-       struct kvec iov[2];
+       int rc;
 
        if (tcon->unix_ext) {
                /*
@@ -1083,74 +1075,18 @@ cifs_make_node(unsigned int xid, struct inode *inode,
                        d_instantiate(dentry, newinode);
                return rc;
        }
-
        /*
-        * SMB1 SFU emulation: should work with all servers, but only
-        * support block and char device (no socket & fifo)
+        * Check if mounted with mount parm 'sfu' mount parm.
+        * SFU emulation should work with all servers, but only
+        * supports block and char device (no socket & fifo),
+        * and was used by default in earlier versions of Windows
         */
        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
-               return rc;
-
-       if (!S_ISCHR(mode) && !S_ISBLK(mode))
-               return rc;
-
-       cifs_dbg(FYI, "sfu compat create special file\n");
-
-       oparms = (struct cifs_open_parms) {
-               .tcon = tcon,
-               .cifs_sb = cifs_sb,
-               .desired_access = GENERIC_WRITE,
-               .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
-                                                     CREATE_OPTION_SPECIAL),
-               .disposition = FILE_CREATE,
-               .path = full_path,
-               .fid = &fid,
-       };
-
-       if (tcon->ses->server->oplocks)
-               oplock = REQ_OPLOCK;
-       else
-               oplock = 0;
-       rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
-       if (rc)
-               return rc;
-
-       /*
-        * BB Do not bother to decode buf since no local inode yet to put
-        * timestamps in, but we can reuse it safely.
-        */
-
-       pdev = (struct win_dev *)&buf.fi;
-       io_parms.pid = current->tgid;
-       io_parms.tcon = tcon;
-       io_parms.offset = 0;
-       io_parms.length = sizeof(struct win_dev);
-       iov[1].iov_base = &buf.fi;
-       iov[1].iov_len = sizeof(struct win_dev);
-       if (S_ISCHR(mode)) {
-               memcpy(pdev->type, "IntxCHR", 8);
-               pdev->major = cpu_to_le64(MAJOR(dev));
-               pdev->minor = cpu_to_le64(MINOR(dev));
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
-       } else if (S_ISBLK(mode)) {
-               memcpy(pdev->type, "IntxBLK", 8);
-               pdev->major = cpu_to_le64(MAJOR(dev));
-               pdev->minor = cpu_to_le64(MINOR(dev));
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
-       }
-       tcon->ses->server->ops->close(xid, tcon, &fid);
-       d_drop(dentry);
-
-       /* FIXME: add code here to set EAs */
-
-       cifs_free_open_info(&buf);
-       return rc;
+               return -EPERM;
+       return cifs_sfu_make_node(xid, inode, dentry, tcon,
+                                 full_path, mode, dev);
 }
 
-
-
 struct smb_version_operations smb1_operations = {
        .send_cancel = send_nt_cancel,
        .compare_fids = cifs_compare_fids,
index f01a929a7a3a5967325c109d38c49b0c2b2ba9ed..82ab62fd00404d76d11e34632b47f8d6ac182992 100644 (file)
@@ -5068,41 +5068,24 @@ smb2_next_header(char *buf)
        return le32_to_cpu(hdr->NextCommand);
 }
 
-static int
-smb2_make_node(unsigned int xid, struct inode *inode,
-              struct dentry *dentry, struct cifs_tcon *tcon,
-              const char *full_path, umode_t mode, dev_t dev)
+int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
+                      struct dentry *dentry, struct cifs_tcon *tcon,
+                      const char *full_path, umode_t mode, dev_t dev)
 {
-       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-       int rc = -EPERM;
        struct cifs_open_info_data buf = {};
-       struct cifs_io_parms io_parms = {0};
-       __u32 oplock = 0;
-       struct cifs_fid fid;
+       struct TCP_Server_Info *server = tcon->ses->server;
        struct cifs_open_parms oparms;
+       struct cifs_io_parms io_parms = {};
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct cifs_fid fid;
        unsigned int bytes_written;
        struct win_dev *pdev;
        struct kvec iov[2];
-
-       /*
-        * Check if mounted with mount parm 'sfu' mount parm.
-        * SFU emulation should work with all servers, but only
-        * supports block and char device (no socket & fifo),
-        * and was used by default in earlier versions of Windows
-        */
-       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
-               return rc;
-
-       /*
-        * TODO: Add ability to create instead via reparse point. Windows (e.g.
-        * their current NFS server) uses this approach to expose special files
-        * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
-        */
+       __u32 oplock = server->oplocks ? REQ_OPLOCK : 0;
+       int rc;
 
        if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
-               return rc;
-
-       cifs_dbg(FYI, "sfu compat create special file\n");
+               return -EPERM;
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
@@ -5115,11 +5098,7 @@ smb2_make_node(unsigned int xid, struct inode *inode,
                .fid = &fid,
        };
 
-       if (tcon->ses->server->oplocks)
-               oplock = REQ_OPLOCK;
-       else
-               oplock = 0;
-       rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
+       rc = server->ops->open(xid, &oparms, &oplock, &buf);
        if (rc)
                return rc;
 
@@ -5127,42 +5106,56 @@ smb2_make_node(unsigned int xid, struct inode *inode,
         * BB Do not bother to decode buf since no local inode yet to put
         * timestamps in, but we can reuse it safely.
         */
-
        pdev = (struct win_dev *)&buf.fi;
        io_parms.pid = current->tgid;
        io_parms.tcon = tcon;
-       io_parms.offset = 0;
-       io_parms.length = sizeof(struct win_dev);
-       iov[1].iov_base = &buf.fi;
-       iov[1].iov_len = sizeof(struct win_dev);
+       io_parms.length = sizeof(*pdev);
+       iov[1].iov_base = pdev;
+       iov[1].iov_len = sizeof(*pdev);
        if (S_ISCHR(mode)) {
                memcpy(pdev->type, "IntxCHR", 8);
                pdev->major = cpu_to_le64(MAJOR(dev));
                pdev->minor = cpu_to_le64(MINOR(dev));
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
        } else if (S_ISBLK(mode)) {
                memcpy(pdev->type, "IntxBLK", 8);
                pdev->major = cpu_to_le64(MAJOR(dev));
                pdev->minor = cpu_to_le64(MINOR(dev));
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
        } else if (S_ISFIFO(mode)) {
                memcpy(pdev->type, "LnxFIFO", 8);
-               pdev->major = 0;
-               pdev->minor = 0;
-               rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
-                                                       &bytes_written, iov, 1);
        }
-       tcon->ses->server->ops->close(xid, tcon, &fid);
-       d_drop(dentry);
 
+       rc = server->ops->sync_write(xid, &fid, &io_parms,
+                                    &bytes_written, iov, 1);
+       server->ops->close(xid, tcon, &fid);
+       d_drop(dentry);
        /* FIXME: add code here to set EAs */
-
        cifs_free_open_info(&buf);
        return rc;
 }
 
+static int smb2_make_node(unsigned int xid, struct inode *inode,
+                         struct dentry *dentry, struct cifs_tcon *tcon,
+                         const char *full_path, umode_t mode, dev_t dev)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+       /*
+        * Check if mounted with mount parm 'sfu' mount parm.
+        * SFU emulation should work with all servers, but only
+        * supports block and char device (no socket & fifo),
+        * and was used by default in earlier versions of Windows
+        */
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
+               return -EPERM;
+       /*
+        * TODO: Add ability to create instead via reparse point. Windows (e.g.
+        * their current NFS server) uses this approach to expose special files
+        * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
+        */
+       return cifs_sfu_make_node(xid, inode, dentry, tcon,
+                                 full_path, mode, dev);
+}
+
 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
 struct smb_version_operations smb20_operations = {
        .compare_fids = smb2_compare_fids,