smb3: fix creating FIFOs when mounting with "sfu" mount option
authorSteve French <stfrench@microsoft.com>
Fri, 20 Oct 2023 04:01:49 +0000 (23:01 -0500)
committerSteve French <stfrench@microsoft.com>
Tue, 31 Oct 2023 17:23:11 +0000 (12:23 -0500)
Fixes some xfstests including generic/564 and generic/157

The "sfu" mount option can be useful for creating special files (character
and block devices in particular) but could not create FIFOs. It did
recognize existing empty files with the "system" attribute flag as FIFOs
but this is too general, so to support creating FIFOs more safely use a new
tag (but the same length as those for char and block devices ie "IntxLNK"
and "IntxBLK") "LnxFIFO" to indicate that the file should be treated as a
FIFO (when mounted with the "sfu").   For some additional context note that
"sfu" followed the way that "Services for Unix" on Windows handled these
special files (at least for character and block devices and symlinks),
which is different than newer Windows which can handle special files
as reparse points (which isn't an option to many servers).

Cc: stable@vger.kernel.org
Reviewed-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cifspdu.h
fs/smb/client/inode.c
fs/smb/client/smb2ops.c

index e17222fec9d290a643559603068a863b2a97b8ff..a75220db5c1e1893ea852c0ad761a63bd7adbfdf 100644 (file)
@@ -2570,7 +2570,7 @@ typedef struct {
 
 
 struct win_dev {
-       unsigned char type[8]; /* IntxCHR or IntxBLK */
+       unsigned char type[8]; /* IntxCHR or IntxBLK or LnxFIFO*/
        __le64 major;
        __le64 minor;
 } __attribute__((packed));
index d7c302442c1ec876cb977850c74a161331ff8577..c03a286ed418877f624e0e68148cf82fc817f05a 100644 (file)
@@ -592,6 +592,10 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
                        cifs_dbg(FYI, "Symlink\n");
                        fattr->cf_mode |= S_IFLNK;
                        fattr->cf_dtype = DT_LNK;
+               } else if (memcmp("LnxFIFO", pbuf, 8) == 0) {
+                       cifs_dbg(FYI, "FIFO\n");
+                       fattr->cf_mode |= S_IFIFO;
+                       fattr->cf_dtype = DT_FIFO;
                } else {
                        fattr->cf_mode |= S_IFREG; /* file? */
                        fattr->cf_dtype = DT_REG;
index 9aeecee6b91b356711d3f545119eba504e08c28e..4af0085239b74d79ac9add59a05b0510f1675a62 100644 (file)
@@ -5087,7 +5087,7 @@ smb2_make_node(unsigned int xid, struct inode *inode,
         * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
         */
 
-       if (!S_ISCHR(mode) && !S_ISBLK(mode))
+       if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
                return rc;
 
        cifs_dbg(FYI, "sfu compat create special file\n");
@@ -5135,6 +5135,12 @@ smb2_make_node(unsigned int xid, struct inode *inode,
                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);