Skip to content

Commit b0348e4

Browse files
Paulo AlcantaraSteve French
authored andcommitted
smb: client: introduce cifs_sfu_make_node()
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>
1 parent 45e7240 commit b0348e4

File tree

3 files changed

+52
-120
lines changed

3 files changed

+52
-120
lines changed

fs/smb/client/cifsproto.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,9 @@ char *extract_sharename(const char *unc);
668668
int parse_reparse_point(struct reparse_data_buffer *buf,
669669
u32 plen, struct cifs_sb_info *cifs_sb,
670670
bool unicode, struct cifs_open_info_data *data);
671+
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
672+
struct dentry *dentry, struct cifs_tcon *tcon,
673+
const char *full_path, umode_t mode, dev_t dev);
671674

672675
#ifdef CONFIG_CIFS_DFS_UPCALL
673676
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,

fs/smb/client/smb1ops.c

Lines changed: 8 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,15 +1041,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
10411041
{
10421042
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
10431043
struct inode *newinode = NULL;
1044-
int rc = -EPERM;
1045-
struct cifs_open_info_data buf = {};
1046-
struct cifs_io_parms io_parms;
1047-
__u32 oplock = 0;
1048-
struct cifs_fid fid;
1049-
struct cifs_open_parms oparms;
1050-
unsigned int bytes_written;
1051-
struct win_dev *pdev;
1052-
struct kvec iov[2];
1044+
int rc;
10531045

10541046
if (tcon->unix_ext) {
10551047
/*
@@ -1083,74 +1075,18 @@ cifs_make_node(unsigned int xid, struct inode *inode,
10831075
d_instantiate(dentry, newinode);
10841076
return rc;
10851077
}
1086-
10871078
/*
1088-
* SMB1 SFU emulation: should work with all servers, but only
1089-
* support block and char device (no socket & fifo)
1079+
* Check if mounted with mount parm 'sfu' mount parm.
1080+
* SFU emulation should work with all servers, but only
1081+
* supports block and char device (no socket & fifo),
1082+
* and was used by default in earlier versions of Windows
10901083
*/
10911084
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
1092-
return rc;
1093-
1094-
if (!S_ISCHR(mode) && !S_ISBLK(mode))
1095-
return rc;
1096-
1097-
cifs_dbg(FYI, "sfu compat create special file\n");
1098-
1099-
oparms = (struct cifs_open_parms) {
1100-
.tcon = tcon,
1101-
.cifs_sb = cifs_sb,
1102-
.desired_access = GENERIC_WRITE,
1103-
.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
1104-
CREATE_OPTION_SPECIAL),
1105-
.disposition = FILE_CREATE,
1106-
.path = full_path,
1107-
.fid = &fid,
1108-
};
1109-
1110-
if (tcon->ses->server->oplocks)
1111-
oplock = REQ_OPLOCK;
1112-
else
1113-
oplock = 0;
1114-
rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
1115-
if (rc)
1116-
return rc;
1117-
1118-
/*
1119-
* BB Do not bother to decode buf since no local inode yet to put
1120-
* timestamps in, but we can reuse it safely.
1121-
*/
1122-
1123-
pdev = (struct win_dev *)&buf.fi;
1124-
io_parms.pid = current->tgid;
1125-
io_parms.tcon = tcon;
1126-
io_parms.offset = 0;
1127-
io_parms.length = sizeof(struct win_dev);
1128-
iov[1].iov_base = &buf.fi;
1129-
iov[1].iov_len = sizeof(struct win_dev);
1130-
if (S_ISCHR(mode)) {
1131-
memcpy(pdev->type, "IntxCHR", 8);
1132-
pdev->major = cpu_to_le64(MAJOR(dev));
1133-
pdev->minor = cpu_to_le64(MINOR(dev));
1134-
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
1135-
&bytes_written, iov, 1);
1136-
} else if (S_ISBLK(mode)) {
1137-
memcpy(pdev->type, "IntxBLK", 8);
1138-
pdev->major = cpu_to_le64(MAJOR(dev));
1139-
pdev->minor = cpu_to_le64(MINOR(dev));
1140-
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
1141-
&bytes_written, iov, 1);
1142-
}
1143-
tcon->ses->server->ops->close(xid, tcon, &fid);
1144-
d_drop(dentry);
1145-
1146-
/* FIXME: add code here to set EAs */
1147-
1148-
cifs_free_open_info(&buf);
1149-
return rc;
1085+
return -EPERM;
1086+
return cifs_sfu_make_node(xid, inode, dentry, tcon,
1087+
full_path, mode, dev);
11501088
}
11511089

1152-
1153-
11541090
struct smb_version_operations smb1_operations = {
11551091
.send_cancel = send_nt_cancel,
11561092
.compare_fids = cifs_compare_fids,

fs/smb/client/smb2ops.c

Lines changed: 41 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5068,41 +5068,24 @@ smb2_next_header(char *buf)
50685068
return le32_to_cpu(hdr->NextCommand);
50695069
}
50705070

5071-
static int
5072-
smb2_make_node(unsigned int xid, struct inode *inode,
5073-
struct dentry *dentry, struct cifs_tcon *tcon,
5074-
const char *full_path, umode_t mode, dev_t dev)
5071+
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
5072+
struct dentry *dentry, struct cifs_tcon *tcon,
5073+
const char *full_path, umode_t mode, dev_t dev)
50755074
{
5076-
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
5077-
int rc = -EPERM;
50785075
struct cifs_open_info_data buf = {};
5079-
struct cifs_io_parms io_parms = {0};
5080-
__u32 oplock = 0;
5081-
struct cifs_fid fid;
5076+
struct TCP_Server_Info *server = tcon->ses->server;
50825077
struct cifs_open_parms oparms;
5078+
struct cifs_io_parms io_parms = {};
5079+
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
5080+
struct cifs_fid fid;
50835081
unsigned int bytes_written;
50845082
struct win_dev *pdev;
50855083
struct kvec iov[2];
5086-
5087-
/*
5088-
* Check if mounted with mount parm 'sfu' mount parm.
5089-
* SFU emulation should work with all servers, but only
5090-
* supports block and char device (no socket & fifo),
5091-
* and was used by default in earlier versions of Windows
5092-
*/
5093-
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
5094-
return rc;
5095-
5096-
/*
5097-
* TODO: Add ability to create instead via reparse point. Windows (e.g.
5098-
* their current NFS server) uses this approach to expose special files
5099-
* over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
5100-
*/
5084+
__u32 oplock = server->oplocks ? REQ_OPLOCK : 0;
5085+
int rc;
51015086

51025087
if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
5103-
return rc;
5104-
5105-
cifs_dbg(FYI, "sfu compat create special file\n");
5088+
return -EPERM;
51065089

51075090
oparms = (struct cifs_open_parms) {
51085091
.tcon = tcon,
@@ -5115,54 +5098,64 @@ smb2_make_node(unsigned int xid, struct inode *inode,
51155098
.fid = &fid,
51165099
};
51175100

5118-
if (tcon->ses->server->oplocks)
5119-
oplock = REQ_OPLOCK;
5120-
else
5121-
oplock = 0;
5122-
rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
5101+
rc = server->ops->open(xid, &oparms, &oplock, &buf);
51235102
if (rc)
51245103
return rc;
51255104

51265105
/*
51275106
* BB Do not bother to decode buf since no local inode yet to put
51285107
* timestamps in, but we can reuse it safely.
51295108
*/
5130-
51315109
pdev = (struct win_dev *)&buf.fi;
51325110
io_parms.pid = current->tgid;
51335111
io_parms.tcon = tcon;
5134-
io_parms.offset = 0;
5135-
io_parms.length = sizeof(struct win_dev);
5136-
iov[1].iov_base = &buf.fi;
5137-
iov[1].iov_len = sizeof(struct win_dev);
5112+
io_parms.length = sizeof(*pdev);
5113+
iov[1].iov_base = pdev;
5114+
iov[1].iov_len = sizeof(*pdev);
51385115
if (S_ISCHR(mode)) {
51395116
memcpy(pdev->type, "IntxCHR", 8);
51405117
pdev->major = cpu_to_le64(MAJOR(dev));
51415118
pdev->minor = cpu_to_le64(MINOR(dev));
5142-
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
5143-
&bytes_written, iov, 1);
51445119
} else if (S_ISBLK(mode)) {
51455120
memcpy(pdev->type, "IntxBLK", 8);
51465121
pdev->major = cpu_to_le64(MAJOR(dev));
51475122
pdev->minor = cpu_to_le64(MINOR(dev));
5148-
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
5149-
&bytes_written, iov, 1);
51505123
} else if (S_ISFIFO(mode)) {
51515124
memcpy(pdev->type, "LnxFIFO", 8);
5152-
pdev->major = 0;
5153-
pdev->minor = 0;
5154-
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
5155-
&bytes_written, iov, 1);
51565125
}
5157-
tcon->ses->server->ops->close(xid, tcon, &fid);
5158-
d_drop(dentry);
51595126

5127+
rc = server->ops->sync_write(xid, &fid, &io_parms,
5128+
&bytes_written, iov, 1);
5129+
server->ops->close(xid, tcon, &fid);
5130+
d_drop(dentry);
51605131
/* FIXME: add code here to set EAs */
5161-
51625132
cifs_free_open_info(&buf);
51635133
return rc;
51645134
}
51655135

5136+
static int smb2_make_node(unsigned int xid, struct inode *inode,
5137+
struct dentry *dentry, struct cifs_tcon *tcon,
5138+
const char *full_path, umode_t mode, dev_t dev)
5139+
{
5140+
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
5141+
5142+
/*
5143+
* Check if mounted with mount parm 'sfu' mount parm.
5144+
* SFU emulation should work with all servers, but only
5145+
* supports block and char device (no socket & fifo),
5146+
* and was used by default in earlier versions of Windows
5147+
*/
5148+
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
5149+
return -EPERM;
5150+
/*
5151+
* TODO: Add ability to create instead via reparse point. Windows (e.g.
5152+
* their current NFS server) uses this approach to expose special files
5153+
* over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
5154+
*/
5155+
return cifs_sfu_make_node(xid, inode, dentry, tcon,
5156+
full_path, mode, dev);
5157+
}
5158+
51665159
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
51675160
struct smb_version_operations smb20_operations = {
51685161
.compare_fids = smb2_compare_fids,

0 commit comments

Comments
 (0)