smb3: Add posix create context for smb3.11 posix mounts
Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
Родитель
28d59363ae
Коммит
ce558b0e17
|
@ -1082,6 +1082,7 @@ struct cifs_open_parms {
|
||||||
int create_options;
|
int create_options;
|
||||||
const char *path;
|
const char *path;
|
||||||
struct cifs_fid *fid;
|
struct cifs_fid *fid;
|
||||||
|
umode_t mode;
|
||||||
bool reconnect:1;
|
bool reconnect:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3963,6 +3963,12 @@ try_mount_again:
|
||||||
goto remote_path_check;
|
goto remote_path_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_SMB311
|
||||||
|
/* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
|
||||||
|
if (tcon->posix_extensions)
|
||||||
|
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
|
||||||
|
#endif /* SMB3.11 */
|
||||||
|
|
||||||
/* tell server which Unix caps we support */
|
/* tell server which Unix caps we support */
|
||||||
if (cap_unix(tcon->ses)) {
|
if (cap_unix(tcon->ses)) {
|
||||||
/* reset of caps checks mount to see if unix extensions
|
/* reset of caps checks mount to see if unix extensions
|
||||||
|
@ -4424,6 +4430,11 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_SMB311
|
||||||
|
/* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
|
||||||
|
if (tcon->posix_extensions)
|
||||||
|
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
|
||||||
|
#endif /* SMB3.11 */
|
||||||
if (cap_unix(ses))
|
if (cap_unix(ses))
|
||||||
reset_cifs_unix_caps(0, tcon, NULL, vol_info);
|
reset_cifs_unix_caps(0, tcon, NULL, vol_info);
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
|
||||||
oparms.path = full_path;
|
oparms.path = full_path;
|
||||||
oparms.fid = fid;
|
oparms.fid = fid;
|
||||||
oparms.reconnect = false;
|
oparms.reconnect = false;
|
||||||
|
oparms.mode = mode;
|
||||||
rc = server->ops->open(xid, &oparms, oplock, buf);
|
rc = server->ops->open(xid, &oparms, oplock, buf);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
|
cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
|
||||||
|
|
|
@ -455,8 +455,14 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
|
||||||
/* Windows doesn't allow paths beginning with \ */
|
/* Windows doesn't allow paths beginning with \ */
|
||||||
if (from[0] == '\\')
|
if (from[0] == '\\')
|
||||||
start_of_path = from + 1;
|
start_of_path = from + 1;
|
||||||
|
#ifdef CONFIG_CIFS_SMB311
|
||||||
|
/* SMB311 POSIX extensions paths do not include leading slash */
|
||||||
|
else if (cifs_sb_master_tcon(cifs_sb)->posix_extensions)
|
||||||
|
start_of_path = from + 1;
|
||||||
|
#endif /* 311 */
|
||||||
else
|
else
|
||||||
start_of_path = from;
|
start_of_path = from;
|
||||||
|
|
||||||
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
|
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
|
||||||
cifs_sb->local_nls, map_type);
|
cifs_sb->local_nls, map_type);
|
||||||
return to;
|
return to;
|
||||||
|
|
|
@ -519,6 +519,64 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct create_posix *
|
||||||
|
create_posix_buf(umode_t mode)
|
||||||
|
{
|
||||||
|
struct create_posix *buf;
|
||||||
|
|
||||||
|
buf = kzalloc(sizeof(struct create_posix),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buf->ccontext.DataOffset =
|
||||||
|
cpu_to_le16(offsetof(struct create_posix, Mode));
|
||||||
|
buf->ccontext.DataLength = cpu_to_le32(4);
|
||||||
|
buf->ccontext.NameOffset =
|
||||||
|
cpu_to_le16(offsetof(struct create_posix, Name));
|
||||||
|
buf->ccontext.NameLength = cpu_to_le16(16);
|
||||||
|
|
||||||
|
/* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
|
||||||
|
buf->Name[0] = 0x93;
|
||||||
|
buf->Name[1] = 0xAD;
|
||||||
|
buf->Name[2] = 0x25;
|
||||||
|
buf->Name[3] = 0x50;
|
||||||
|
buf->Name[4] = 0x9C;
|
||||||
|
buf->Name[5] = 0xB4;
|
||||||
|
buf->Name[6] = 0x11;
|
||||||
|
buf->Name[7] = 0xE7;
|
||||||
|
buf->Name[8] = 0xB4;
|
||||||
|
buf->Name[9] = 0x23;
|
||||||
|
buf->Name[10] = 0x83;
|
||||||
|
buf->Name[11] = 0xDE;
|
||||||
|
buf->Name[12] = 0x96;
|
||||||
|
buf->Name[13] = 0x8B;
|
||||||
|
buf->Name[14] = 0xCD;
|
||||||
|
buf->Name[15] = 0x7C;
|
||||||
|
buf->Mode = cpu_to_le32(mode);
|
||||||
|
cifs_dbg(FYI, "mode on posix create 0%o", mode);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
|
||||||
|
{
|
||||||
|
struct smb2_create_req *req = iov[0].iov_base;
|
||||||
|
unsigned int num = *num_iovec;
|
||||||
|
|
||||||
|
iov[num].iov_base = create_posix_buf(mode);
|
||||||
|
if (iov[num].iov_base == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
iov[num].iov_len = sizeof(struct create_posix);
|
||||||
|
if (!req->CreateContextsOffset)
|
||||||
|
req->CreateContextsOffset = cpu_to_le32(
|
||||||
|
sizeof(struct smb2_create_req) +
|
||||||
|
iov[num - 1].iov_len);
|
||||||
|
le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_posix));
|
||||||
|
*num_iovec = num + 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static void assemble_neg_contexts(struct smb2_negotiate_req *req,
|
static void assemble_neg_contexts(struct smb2_negotiate_req *req,
|
||||||
unsigned int *total_len)
|
unsigned int *total_len)
|
||||||
|
@ -1837,7 +1895,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||||
struct TCP_Server_Info *server;
|
struct TCP_Server_Info *server;
|
||||||
struct cifs_tcon *tcon = oparms->tcon;
|
struct cifs_tcon *tcon = oparms->tcon;
|
||||||
struct cifs_ses *ses = tcon->ses;
|
struct cifs_ses *ses = tcon->ses;
|
||||||
struct kvec iov[4];
|
struct kvec iov[5]; /* make sure at least one for each open context */
|
||||||
struct kvec rsp_iov = {NULL, 0};
|
struct kvec rsp_iov = {NULL, 0};
|
||||||
int resp_buftype;
|
int resp_buftype;
|
||||||
int uni_path_len;
|
int uni_path_len;
|
||||||
|
@ -1846,7 +1904,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int n_iov = 2;
|
unsigned int n_iov = 2;
|
||||||
__u32 file_attributes = 0;
|
__u32 file_attributes = 0;
|
||||||
char *dhc_buf = NULL, *lc_buf = NULL;
|
char *dhc_buf = NULL, *lc_buf = NULL, *pc_buf = NULL;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
unsigned int total_len;
|
unsigned int total_len;
|
||||||
|
|
||||||
|
@ -1963,6 +2021,27 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||||
dhc_buf = iov[n_iov-1].iov_base;
|
dhc_buf = iov[n_iov-1].iov_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_SMB311
|
||||||
|
if (tcon->posix_extensions) {
|
||||||
|
if (n_iov > 2) {
|
||||||
|
struct create_context *ccontext =
|
||||||
|
(struct create_context *)iov[n_iov-1].iov_base;
|
||||||
|
ccontext->Next =
|
||||||
|
cpu_to_le32(iov[n_iov-1].iov_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = add_posix_context(iov, &n_iov, oparms->mode);
|
||||||
|
if (rc) {
|
||||||
|
cifs_small_buf_release(req);
|
||||||
|
kfree(copy_path);
|
||||||
|
kfree(lc_buf);
|
||||||
|
kfree(dhc_buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
pc_buf = iov[n_iov-1].iov_base;
|
||||||
|
}
|
||||||
|
#endif /* SMB311 */
|
||||||
|
|
||||||
rc = smb2_send_recv(xid, ses, iov, n_iov, &resp_buftype, flags,
|
rc = smb2_send_recv(xid, ses, iov, n_iov, &resp_buftype, flags,
|
||||||
&rsp_iov);
|
&rsp_iov);
|
||||||
cifs_small_buf_release(req);
|
cifs_small_buf_release(req);
|
||||||
|
@ -2004,6 +2083,7 @@ creat_exit:
|
||||||
kfree(copy_path);
|
kfree(copy_path);
|
||||||
kfree(lc_buf);
|
kfree(lc_buf);
|
||||||
kfree(dhc_buf);
|
kfree(dhc_buf);
|
||||||
|
kfree(pc_buf);
|
||||||
free_rsp_buf(resp_buftype, rsp);
|
free_rsp_buf(resp_buftype, rsp);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче