mirror of https://gitee.com/openkylin/linux.git
one smb3 (ACL related) fix for stable, one SMB3 security enhancement (when mounting -t smb3 forbid less secure dialects), and some RDMA and compounding fixes
-----BEGIN PGP SIGNATURE----- iQHHBAABCgAxFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAlsdWXsTHHNtZnJlbmNo QGdtYWlsLmNvbQAKCRCKLL1wB3JPUXiyC/wJdnwM+R2JGtj1ygZqPfS6/xWbCI0F uXfn9a09nrMVbM2CQCDChiqoU2yvg9cKqc2d/UhssuwJYdfNNYSVe5MDkYYCADRn WSvCQ4+ZDQEl65pcjVKcOlhwl73cIVQmb6yaxMA/scZx+ikfe67EgJEEJZHJPhFO WJnMA5IUMAQFw5KxBdKtuVL0ixHBYvtrtQ9HAyPq0GTmCsTyb0GcbeMYaqRwpCMS R4NXyTr+s68UUi+iM9r+I6nYqml5L2EBFjrSwRbu7e6PIRF5fEMnKzj0WSmbgsSG KY2b/YWSskN5p5dkU+cLETXfjOjg8ugROJzz4LYkS/dUn+AJpg7IOwUNfr/a0yO5 dHMwpa9SltPOslcHZgnBUsfqLHZSP0y/QODVhhc80uapxmllA4CHOc+lgG5i0VlB mTS4SQNRPw2NINoGCr+C65ghcJJyf6ivP6J3PoCjobo76yte8TiyauxjuDIJgY8T h2Wc/fWgN9lc9IUcpvedUjxoacG+rMSopQc= =yibA -----END PGP SIGNATURE----- Merge tag '4.18-fixes-smb3' of git://git.samba.org/sfrench/cifs-2.6 Pull cifs fixes from Steve French: - one smb3 (ACL related) fix for stable - one SMB3 security enhancement (when mounting -t smb3 forbid less secure dialects) - some RDMA and compounding fixes * tag '4.18-fixes-smb3' of git://git.samba.org/sfrench/cifs-2.6: cifs: fix a buffer leak in smb2_query_symlink smb3: do not allow insecure cifs mounts when using smb3 CIFS: Fix NULL ptr deref CIFS: fix encryption in SMB3.1.1 CIFS: Pass page offset for encrypting CIFS: Pass page offset for calculating signature CIFS: SMBD: Support page offset in memory registration CIFS: SMBD: Support page offset in RDMA recv CIFS: SMBD: Support page offset in RDMA send CIFS: When sending data on socket, pass the correct page offset CIFS: Introduce helper function to get page offset and length in smb_rqst CIFS: Calculate the correct request length based on page offset and tail size cifs: For SMB2 security informaion query, check for minimum sized security descriptor instead of sizeof FileAllInformation class CIFS: Fix signing for SMB2/3
This commit is contained in:
commit
0c14e43a42
|
@ -98,4 +98,18 @@ struct cifs_ace {
|
|||
struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* Minimum security identifier can be one for system defined Users
|
||||
* and Groups such as NULL SID and World or Built-in accounts such
|
||||
* as Administrator and Guest and consists of
|
||||
* Revision + Num (Sub)Auths + Authority + Domain (one Subauthority)
|
||||
*/
|
||||
#define MIN_SID_LEN (1 + 1 + 6 + 4) /* in bytes */
|
||||
|
||||
/*
|
||||
* Minimum security descriptor can be one without any SACL and DACL and can
|
||||
* consist of revision, type, and two sids of minimum size for owner and group
|
||||
*/
|
||||
#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN))
|
||||
|
||||
#endif /* _CIFSACL_H */
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <crypto/aead.h>
|
||||
|
||||
int __cifs_calc_signature(struct smb_rqst *rqst,
|
||||
int start,
|
||||
struct TCP_Server_Info *server, char *signature,
|
||||
struct shash_desc *shash)
|
||||
{
|
||||
|
@ -45,10 +46,7 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
|
|||
struct kvec *iov = rqst->rq_iov;
|
||||
int n_vec = rqst->rq_nvec;
|
||||
|
||||
if (n_vec < 2 || iov[0].iov_len != 4)
|
||||
return -EIO;
|
||||
|
||||
for (i = 1; i < n_vec; i++) {
|
||||
for (i = start; i < n_vec; i++) {
|
||||
if (iov[i].iov_len == 0)
|
||||
continue;
|
||||
if (iov[i].iov_base == NULL) {
|
||||
|
@ -68,11 +66,12 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
|
|||
|
||||
/* now hash over the rq_pages array */
|
||||
for (i = 0; i < rqst->rq_npages; i++) {
|
||||
void *kaddr = kmap(rqst->rq_pages[i]);
|
||||
size_t len = rqst->rq_pagesz;
|
||||
void *kaddr;
|
||||
unsigned int len, offset;
|
||||
|
||||
if (i == rqst->rq_npages - 1)
|
||||
len = rqst->rq_tailsz;
|
||||
rqst_page_get_length(rqst, i, &len, &offset);
|
||||
|
||||
kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
|
||||
|
||||
crypto_shash_update(shash, kaddr, len);
|
||||
|
||||
|
@ -119,7 +118,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
|
|||
return rc;
|
||||
}
|
||||
|
||||
return __cifs_calc_signature(rqst, server, signature,
|
||||
return __cifs_calc_signature(rqst, 1, server, signature,
|
||||
&server->secmech.sdescmd5->shash);
|
||||
}
|
||||
|
||||
|
|
|
@ -698,8 +698,8 @@ static int cifs_set_super(struct super_block *sb, void *data)
|
|||
}
|
||||
|
||||
static struct dentry *
|
||||
cifs_do_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
cifs_smb3_do_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data, bool is_smb3)
|
||||
{
|
||||
int rc;
|
||||
struct super_block *sb;
|
||||
|
@ -710,7 +710,7 @@ cifs_do_mount(struct file_system_type *fs_type,
|
|||
|
||||
cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags);
|
||||
|
||||
volume_info = cifs_get_volume_info((char *)data, dev_name);
|
||||
volume_info = cifs_get_volume_info((char *)data, dev_name, is_smb3);
|
||||
if (IS_ERR(volume_info))
|
||||
return ERR_CAST(volume_info);
|
||||
|
||||
|
@ -790,6 +790,20 @@ cifs_do_mount(struct file_system_type *fs_type,
|
|||
goto out;
|
||||
}
|
||||
|
||||
static struct dentry *
|
||||
smb3_do_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
{
|
||||
return cifs_smb3_do_mount(fs_type, flags, dev_name, data, true);
|
||||
}
|
||||
|
||||
static struct dentry *
|
||||
cifs_do_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
{
|
||||
return cifs_smb3_do_mount(fs_type, flags, dev_name, data, false);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
|
||||
{
|
||||
|
@ -925,7 +939,7 @@ MODULE_ALIAS_FS("cifs");
|
|||
static struct file_system_type smb3_fs_type = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "smb3",
|
||||
.mount = cifs_do_mount,
|
||||
.mount = smb3_do_mount,
|
||||
.kill_sb = cifs_kill_sb,
|
||||
/* .fs_flags */
|
||||
};
|
||||
|
|
|
@ -1019,6 +1019,12 @@ tlink_tcon(struct tcon_link *tlink)
|
|||
return tlink->tl_tcon;
|
||||
}
|
||||
|
||||
static inline struct tcon_link *
|
||||
cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
return cifs_sb->master_tlink;
|
||||
}
|
||||
|
||||
extern void cifs_put_tlink(struct tcon_link *tlink);
|
||||
|
||||
static inline struct tcon_link *
|
||||
|
|
|
@ -211,7 +211,7 @@ extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
|
|||
extern int cifs_match_super(struct super_block *, void *);
|
||||
extern void cifs_cleanup_volume_info(struct smb_vol *pvolume_info);
|
||||
extern struct smb_vol *cifs_get_volume_info(char *mount_data,
|
||||
const char *devname);
|
||||
const char *devname, bool is_smb3);
|
||||
extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
|
||||
extern void cifs_umount(struct cifs_sb_info *);
|
||||
extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
|
||||
|
@ -544,7 +544,7 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
|||
struct cifs_sb_info *cifs_sb,
|
||||
const unsigned char *path, char *pbuf,
|
||||
unsigned int *pbytes_written);
|
||||
int __cifs_calc_signature(struct smb_rqst *rqst,
|
||||
int __cifs_calc_signature(struct smb_rqst *rqst, int start,
|
||||
struct TCP_Server_Info *server, char *signature,
|
||||
struct shash_desc *shash);
|
||||
enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
|
||||
|
@ -557,4 +557,7 @@ int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
|
|||
struct sdesc **sdesc);
|
||||
void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);
|
||||
|
||||
extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
|
||||
unsigned int *len, unsigned int *offset);
|
||||
|
||||
#endif /* _CIFSPROTO_H */
|
||||
|
|
|
@ -320,7 +320,7 @@ static int generic_ip_connect(struct TCP_Server_Info *server);
|
|||
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
|
||||
static void cifs_prune_tlinks(struct work_struct *work);
|
||||
static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
|
||||
const char *devname);
|
||||
const char *devname, bool is_smb3);
|
||||
|
||||
/*
|
||||
* cifs tcp session reconnection
|
||||
|
@ -1166,7 +1166,7 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
|
|||
}
|
||||
|
||||
static int
|
||||
cifs_parse_smb_version(char *value, struct smb_vol *vol)
|
||||
cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
|
||||
{
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
|
||||
|
@ -1176,6 +1176,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
|
|||
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
|
||||
return 1;
|
||||
}
|
||||
if (is_smb3) {
|
||||
cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
|
||||
return 1;
|
||||
}
|
||||
vol->ops = &smb1_operations;
|
||||
vol->vals = &smb1_values;
|
||||
break;
|
||||
|
@ -1184,6 +1188,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
|
|||
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
|
||||
return 1;
|
||||
}
|
||||
if (is_smb3) {
|
||||
cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
|
||||
return 1;
|
||||
}
|
||||
vol->ops = &smb20_operations;
|
||||
vol->vals = &smb20_values;
|
||||
break;
|
||||
|
@ -1272,7 +1280,7 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol)
|
|||
|
||||
static int
|
||||
cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||
struct smb_vol *vol)
|
||||
struct smb_vol *vol, bool is_smb3)
|
||||
{
|
||||
char *data, *end;
|
||||
char *mountdata_copy = NULL, *options;
|
||||
|
@ -1985,7 +1993,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
|||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
|
||||
if (cifs_parse_smb_version(string, vol) != 0)
|
||||
if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
|
||||
goto cifs_parse_mount_err;
|
||||
got_version = true;
|
||||
break;
|
||||
|
@ -3116,12 +3124,6 @@ cifs_put_tlink(struct tcon_link *tlink)
|
|||
return;
|
||||
}
|
||||
|
||||
static inline struct tcon_link *
|
||||
cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
return cifs_sb->master_tlink;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
|
||||
{
|
||||
|
@ -3803,7 +3805,7 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
|
|||
} else {
|
||||
cleanup_volume_info_contents(volume_info);
|
||||
rc = cifs_setup_volume_info(volume_info, mdata,
|
||||
fake_devname);
|
||||
fake_devname, false);
|
||||
}
|
||||
kfree(fake_devname);
|
||||
kfree(cifs_sb->mountdata);
|
||||
|
@ -3816,11 +3818,11 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
|
|||
|
||||
static int
|
||||
cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
|
||||
const char *devname)
|
||||
const char *devname, bool is_smb3)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (cifs_parse_mount_options(mount_data, devname, volume_info))
|
||||
if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
|
||||
return -EINVAL;
|
||||
|
||||
if (volume_info->nullauth) {
|
||||
|
@ -3854,7 +3856,7 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
|
|||
}
|
||||
|
||||
struct smb_vol *
|
||||
cifs_get_volume_info(char *mount_data, const char *devname)
|
||||
cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
|
||||
{
|
||||
int rc;
|
||||
struct smb_vol *volume_info;
|
||||
|
@ -3863,7 +3865,7 @@ cifs_get_volume_info(char *mount_data, const char *devname)
|
|||
if (!volume_info)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rc = cifs_setup_volume_info(volume_info, mount_data, devname);
|
||||
rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
|
||||
if (rc) {
|
||||
cifs_cleanup_volume_info(volume_info);
|
||||
volume_info = ERR_PTR(rc);
|
||||
|
|
|
@ -421,7 +421,8 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
|
||||
NULL);
|
||||
if (rc)
|
||||
goto qmf_out_open_fail;
|
||||
|
||||
|
@ -478,7 +479,8 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
|
||||
NULL);
|
||||
if (rc) {
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
|
|
|
@ -905,3 +905,20 @@ cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
|
|||
crypto_free_shash(*shash);
|
||||
*shash = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* rqst_page_get_length - obtain the length and offset for a page in smb_rqst
|
||||
* Input: rqst - a smb_rqst, page - a page index for rqst
|
||||
* Output: *len - the length for this page, *offset - the offset for this page
|
||||
*/
|
||||
void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
|
||||
unsigned int *len, unsigned int *offset)
|
||||
{
|
||||
*len = rqst->rq_pagesz;
|
||||
*offset = (page == 0) ? rqst->rq_offset : 0;
|
||||
|
||||
if (rqst->rq_npages == 1 || page == rqst->rq_npages-1)
|
||||
*len = rqst->rq_tailsz;
|
||||
else if (page == 0)
|
||||
*len = rqst->rq_pagesz - rqst->rq_offset;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,8 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
|
|||
if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
|
||||
memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
|
||||
|
||||
rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL);
|
||||
rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL,
|
||||
NULL);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
|
||||
NULL);
|
||||
if (rc) {
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
|
|
|
@ -453,8 +453,10 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
|
|||
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)
|
||||
else if (cifs_sb_master_tlink(cifs_sb) &&
|
||||
cifs_sb_master_tcon(cifs_sb)->posix_extensions) {
|
||||
start_of_path = from + 1;
|
||||
}
|
||||
#endif /* 311 */
|
||||
else
|
||||
start_of_path = from;
|
||||
|
|
|
@ -348,7 +348,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
|
|||
oparams.fid = pfid;
|
||||
oparams.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL, NULL);
|
||||
if (rc == 0) {
|
||||
memcpy(tcon->prfid, pfid, sizeof(struct cifs_fid));
|
||||
tcon->valid_root_fid = true;
|
||||
|
@ -375,7 +375,8 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
|
|||
oparms.reconnect = false;
|
||||
|
||||
if (no_cached_open)
|
||||
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
|
||||
NULL);
|
||||
else
|
||||
rc = open_shroot(xid, tcon, &fid);
|
||||
|
||||
|
@ -413,7 +414,7 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return;
|
||||
|
||||
|
@ -449,7 +450,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
|
||||
if (rc) {
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
|
@ -598,7 +599,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
|
||||
kfree(utf16_path);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "open failed rc=%d\n", rc);
|
||||
|
@ -677,7 +678,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
|
||||
kfree(utf16_path);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "open failed rc=%d\n", rc);
|
||||
|
@ -1261,7 +1262,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
oparms.fid = fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
|
||||
kfree(utf16_path);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "open dir failed rc=%d\n", rc);
|
||||
|
@ -1361,7 +1362,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
buf->f_type = SMB2_MAGIC_NUMBER;
|
||||
|
@ -1515,7 +1516,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
struct cifs_open_parms oparms;
|
||||
struct cifs_fid fid;
|
||||
struct kvec err_iov = {NULL, 0};
|
||||
struct smb2_err_rsp *err_buf;
|
||||
struct smb2_err_rsp *err_buf = NULL;
|
||||
int resp_buftype;
|
||||
struct smb2_symlink_err_rsp *symlink;
|
||||
unsigned int sub_len;
|
||||
unsigned int sub_offset;
|
||||
|
@ -1535,18 +1537,18 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov,
|
||||
&resp_buftype);
|
||||
if (!rc || !err_iov.iov_base) {
|
||||
kfree(utf16_path);
|
||||
return -ENOENT;
|
||||
rc = -ENOENT;
|
||||
goto querty_exit;
|
||||
}
|
||||
|
||||
err_buf = err_iov.iov_base;
|
||||
if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
|
||||
err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) {
|
||||
kfree(utf16_path);
|
||||
return -ENOENT;
|
||||
rc = -ENOENT;
|
||||
goto querty_exit;
|
||||
}
|
||||
|
||||
/* open must fail on symlink - reset rc */
|
||||
|
@ -1558,25 +1560,28 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
print_offset = le16_to_cpu(symlink->PrintNameOffset);
|
||||
|
||||
if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
|
||||
kfree(utf16_path);
|
||||
return -ENOENT;
|
||||
rc = -ENOENT;
|
||||
goto querty_exit;
|
||||
}
|
||||
|
||||
if (err_iov.iov_len <
|
||||
SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
|
||||
kfree(utf16_path);
|
||||
return -ENOENT;
|
||||
rc = -ENOENT;
|
||||
goto querty_exit;
|
||||
}
|
||||
|
||||
*target_path = cifs_strndup_from_utf16(
|
||||
(char *)symlink->PathBuffer + sub_offset,
|
||||
sub_len, true, cifs_sb->local_nls);
|
||||
if (!(*target_path)) {
|
||||
kfree(utf16_path);
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto querty_exit;
|
||||
}
|
||||
convert_delimiter(*target_path, '/');
|
||||
cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
|
||||
|
||||
querty_exit:
|
||||
free_rsp_buf(resp_buftype, err_buf);
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1649,7 +1654,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
|
||||
kfree(utf16_path);
|
||||
if (!rc) {
|
||||
rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
|
||||
|
@ -1712,7 +1717,7 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
|||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
|
||||
kfree(utf16_path);
|
||||
if (!rc) {
|
||||
rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
|
||||
|
@ -2189,9 +2194,10 @@ init_sg(struct smb_rqst *rqst, u8 *sign)
|
|||
smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,
|
||||
rqst->rq_iov[i+1].iov_len);
|
||||
for (j = 0; i < sg_len - 1; i++, j++) {
|
||||
unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
|
||||
: rqst->rq_tailsz;
|
||||
sg_set_page(&sg[i], rqst->rq_pages[j], len, 0);
|
||||
unsigned int len, offset;
|
||||
|
||||
rqst_page_get_length(rqst, j, &len, &offset);
|
||||
sg_set_page(&sg[i], rqst->rq_pages[j], len, offset);
|
||||
}
|
||||
smb2_sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);
|
||||
return sg;
|
||||
|
@ -2229,7 +2235,7 @@ static int
|
|||
crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
|
||||
{
|
||||
struct smb2_transform_hdr *tr_hdr =
|
||||
(struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base;
|
||||
(struct smb2_transform_hdr *)rqst->rq_iov[1].iov_base;
|
||||
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
|
||||
int rc = 0;
|
||||
struct scatterlist *sg;
|
||||
|
@ -2338,6 +2344,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
|
|||
return rc;
|
||||
|
||||
new_rq->rq_pages = pages;
|
||||
new_rq->rq_offset = old_rq->rq_offset;
|
||||
new_rq->rq_npages = old_rq->rq_npages;
|
||||
new_rq->rq_pagesz = old_rq->rq_pagesz;
|
||||
new_rq->rq_tailsz = old_rq->rq_tailsz;
|
||||
|
@ -2379,10 +2386,14 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
|
|||
|
||||
/* copy pages form the old */
|
||||
for (i = 0; i < npages; i++) {
|
||||
char *dst = kmap(new_rq->rq_pages[i]);
|
||||
char *src = kmap(old_rq->rq_pages[i]);
|
||||
unsigned int len = (i < npages - 1) ? new_rq->rq_pagesz :
|
||||
new_rq->rq_tailsz;
|
||||
char *dst, *src;
|
||||
unsigned int offset, len;
|
||||
|
||||
rqst_page_get_length(new_rq, i, &len, &offset);
|
||||
|
||||
dst = (char *) kmap(new_rq->rq_pages[i]) + offset;
|
||||
src = (char *) kmap(old_rq->rq_pages[i]) + offset;
|
||||
|
||||
memcpy(dst, src, len);
|
||||
kunmap(new_rq->rq_pages[i]);
|
||||
kunmap(old_rq->rq_pages[i]);
|
||||
|
|
|
@ -1889,7 +1889,7 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
|
|||
int
|
||||
SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||
__u8 *oplock, struct smb2_file_all_info *buf,
|
||||
struct kvec *err_iov)
|
||||
struct kvec *err_iov, int *buftype)
|
||||
{
|
||||
struct smb2_create_req *req;
|
||||
struct smb2_create_rsp *rsp;
|
||||
|
@ -2052,6 +2052,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
|||
cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
|
||||
if (err_iov && rsp) {
|
||||
*err_iov = rsp_iov;
|
||||
*buftype = resp_buftype;
|
||||
resp_buftype = CIFS_NO_BUFFER;
|
||||
rsp = NULL;
|
||||
}
|
||||
|
@ -2492,8 +2493,7 @@ SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
|
||||
return query_info(xid, tcon, persistent_fid, volatile_fid,
|
||||
0, SMB2_O_INFO_SECURITY, additional_info,
|
||||
SMB2_MAX_BUFFER_SIZE,
|
||||
sizeof(struct smb2_file_all_info), data, plen);
|
||||
SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -2721,8 +2721,8 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
|
|||
|
||||
rdata->mr = smbd_register_mr(
|
||||
server->smbd_conn, rdata->pages,
|
||||
rdata->nr_pages, rdata->tailsz,
|
||||
true, need_invalidate);
|
||||
rdata->nr_pages, rdata->page_offset,
|
||||
rdata->tailsz, true, need_invalidate);
|
||||
if (!rdata->mr)
|
||||
return -ENOBUFS;
|
||||
|
||||
|
@ -3108,16 +3108,22 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
|||
|
||||
wdata->mr = smbd_register_mr(
|
||||
server->smbd_conn, wdata->pages,
|
||||
wdata->nr_pages, wdata->tailsz,
|
||||
false, need_invalidate);
|
||||
wdata->nr_pages, wdata->page_offset,
|
||||
wdata->tailsz, false, need_invalidate);
|
||||
if (!wdata->mr) {
|
||||
rc = -ENOBUFS;
|
||||
goto async_writev_out;
|
||||
}
|
||||
req->Length = 0;
|
||||
req->DataOffset = 0;
|
||||
req->RemainingBytes =
|
||||
cpu_to_le32((wdata->nr_pages-1)*PAGE_SIZE + wdata->tailsz);
|
||||
if (wdata->nr_pages > 1)
|
||||
req->RemainingBytes =
|
||||
cpu_to_le32(
|
||||
(wdata->nr_pages - 1) * wdata->pagesz -
|
||||
wdata->page_offset + wdata->tailsz
|
||||
);
|
||||
else
|
||||
req->RemainingBytes = cpu_to_le32(wdata->tailsz);
|
||||
req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
|
||||
if (need_invalidate)
|
||||
req->Channel = SMB2_CHANNEL_RDMA_V1;
|
||||
|
|
|
@ -125,7 +125,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
|
|||
extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
|
||||
__le16 *path, __u8 *oplock,
|
||||
struct smb2_file_all_info *buf,
|
||||
struct kvec *err_iov);
|
||||
struct kvec *err_iov, int *resp_buftype);
|
||||
extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_fid, u64 volatile_fid, u32 opcode,
|
||||
bool is_fsctl, char *in_data, u32 indatalen,
|
||||
|
|
|
@ -171,7 +171,9 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
|||
unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
|
||||
unsigned char *sigptr = smb2_signature;
|
||||
struct kvec *iov = rqst->rq_iov;
|
||||
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
|
||||
int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
|
||||
struct smb2_sync_hdr *shdr =
|
||||
(struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
|
||||
struct cifs_ses *ses;
|
||||
|
||||
ses = smb2_find_smb_ses(server, shdr->SessionId);
|
||||
|
@ -202,7 +204,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = __cifs_calc_signature(rqst, server, sigptr,
|
||||
rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr,
|
||||
&server->secmech.sdeschmacsha256->shash);
|
||||
|
||||
if (!rc)
|
||||
|
@ -412,7 +414,9 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
|||
unsigned char smb3_signature[SMB2_CMACAES_SIZE];
|
||||
unsigned char *sigptr = smb3_signature;
|
||||
struct kvec *iov = rqst->rq_iov;
|
||||
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
|
||||
int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
|
||||
struct smb2_sync_hdr *shdr =
|
||||
(struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
|
||||
struct cifs_ses *ses;
|
||||
|
||||
ses = smb2_find_smb_ses(server, shdr->SessionId);
|
||||
|
@ -443,7 +447,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = __cifs_calc_signature(rqst, server, sigptr,
|
||||
rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr,
|
||||
&server->secmech.sdesccmacaes->shash);
|
||||
|
||||
if (!rc)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/highmem.h>
|
||||
#include "smbdirect.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifsproto.h"
|
||||
|
||||
static struct smbd_response *get_empty_queue_buffer(
|
||||
struct smbd_connection *info);
|
||||
|
@ -2003,10 +2004,12 @@ static int smbd_recv_buf(struct smbd_connection *info, char *buf,
|
|||
* return value: actual data read
|
||||
*/
|
||||
static int smbd_recv_page(struct smbd_connection *info,
|
||||
struct page *page, unsigned int to_read)
|
||||
struct page *page, unsigned int page_offset,
|
||||
unsigned int to_read)
|
||||
{
|
||||
int ret;
|
||||
char *to_address;
|
||||
void *page_address;
|
||||
|
||||
/* make sure we have the page ready for read */
|
||||
ret = wait_event_interruptible(
|
||||
|
@ -2014,16 +2017,17 @@ static int smbd_recv_page(struct smbd_connection *info,
|
|||
info->reassembly_data_length >= to_read ||
|
||||
info->transport_status != SMBD_CONNECTED);
|
||||
if (ret)
|
||||
return 0;
|
||||
return ret;
|
||||
|
||||
/* now we can read from reassembly queue and not sleep */
|
||||
to_address = kmap_atomic(page);
|
||||
page_address = kmap_atomic(page);
|
||||
to_address = (char *) page_address + page_offset;
|
||||
|
||||
log_read(INFO, "reading from page=%p address=%p to_read=%d\n",
|
||||
page, to_address, to_read);
|
||||
|
||||
ret = smbd_recv_buf(info, to_address, to_read);
|
||||
kunmap_atomic(to_address);
|
||||
kunmap_atomic(page_address);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2037,7 +2041,7 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
|
|||
{
|
||||
char *buf;
|
||||
struct page *page;
|
||||
unsigned int to_read;
|
||||
unsigned int to_read, page_offset;
|
||||
int rc;
|
||||
|
||||
info->smbd_recv_pending++;
|
||||
|
@ -2051,15 +2055,16 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
|
|||
|
||||
case READ | ITER_BVEC:
|
||||
page = msg->msg_iter.bvec->bv_page;
|
||||
page_offset = msg->msg_iter.bvec->bv_offset;
|
||||
to_read = msg->msg_iter.bvec->bv_len;
|
||||
rc = smbd_recv_page(info, page, to_read);
|
||||
rc = smbd_recv_page(info, page, page_offset, to_read);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* It's a bug in upper layer to get there */
|
||||
cifs_dbg(VFS, "CIFS: invalid msg type %d\n",
|
||||
msg->msg_iter.type);
|
||||
rc = -EIO;
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
info->smbd_recv_pending--;
|
||||
|
@ -2082,7 +2087,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
|
|||
struct kvec vec;
|
||||
int nvecs;
|
||||
int size;
|
||||
int buflen = 0, remaining_data_length;
|
||||
unsigned int buflen = 0, remaining_data_length;
|
||||
int start, i, j;
|
||||
int max_iov_size =
|
||||
info->max_send_size - sizeof(struct smbd_data_transfer);
|
||||
|
@ -2113,10 +2118,17 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
|
|||
buflen += iov[i].iov_len;
|
||||
}
|
||||
|
||||
/* add in the page array if there is one */
|
||||
/*
|
||||
* Add in the page array if there is one. The caller needs to set
|
||||
* rq_tailsz to PAGE_SIZE when the buffer has multiple pages and
|
||||
* ends at page boundary
|
||||
*/
|
||||
if (rqst->rq_npages) {
|
||||
buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
|
||||
buflen += rqst->rq_tailsz;
|
||||
if (rqst->rq_npages == 1)
|
||||
buflen += rqst->rq_tailsz;
|
||||
else
|
||||
buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
|
||||
rqst->rq_offset + rqst->rq_tailsz;
|
||||
}
|
||||
|
||||
if (buflen + sizeof(struct smbd_data_transfer) >
|
||||
|
@ -2213,8 +2225,9 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
|
|||
|
||||
/* now sending pages if there are any */
|
||||
for (i = 0; i < rqst->rq_npages; i++) {
|
||||
buflen = (i == rqst->rq_npages-1) ?
|
||||
rqst->rq_tailsz : rqst->rq_pagesz;
|
||||
unsigned int offset;
|
||||
|
||||
rqst_page_get_length(rqst, i, &buflen, &offset);
|
||||
nvecs = (buflen + max_iov_size - 1) / max_iov_size;
|
||||
log_write(INFO, "sending pages buflen=%d nvecs=%d\n",
|
||||
buflen, nvecs);
|
||||
|
@ -2225,9 +2238,11 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
|
|||
remaining_data_length -= size;
|
||||
log_write(INFO, "sending pages i=%d offset=%d size=%d"
|
||||
" remaining_data_length=%d\n",
|
||||
i, j*max_iov_size, size, remaining_data_length);
|
||||
i, j*max_iov_size+offset, size,
|
||||
remaining_data_length);
|
||||
rc = smbd_post_send_page(
|
||||
info, rqst->rq_pages[i], j*max_iov_size,
|
||||
info, rqst->rq_pages[i],
|
||||
j*max_iov_size + offset,
|
||||
size, remaining_data_length);
|
||||
if (rc)
|
||||
goto done;
|
||||
|
@ -2284,37 +2299,37 @@ static void smbd_mr_recovery_work(struct work_struct *work)
|
|||
if (smbdirect_mr->state == MR_INVALIDATED ||
|
||||
smbdirect_mr->state == MR_ERROR) {
|
||||
|
||||
if (smbdirect_mr->state == MR_INVALIDATED) {
|
||||
/* recover this MR entry */
|
||||
rc = ib_dereg_mr(smbdirect_mr->mr);
|
||||
if (rc) {
|
||||
log_rdma_mr(ERR,
|
||||
"ib_dereg_mr failed rc=%x\n",
|
||||
rc);
|
||||
smbd_disconnect_rdma_connection(info);
|
||||
continue;
|
||||
}
|
||||
|
||||
smbdirect_mr->mr = ib_alloc_mr(
|
||||
info->pd, info->mr_type,
|
||||
info->max_frmr_depth);
|
||||
if (IS_ERR(smbdirect_mr->mr)) {
|
||||
log_rdma_mr(ERR,
|
||||
"ib_alloc_mr failed mr_type=%x "
|
||||
"max_frmr_depth=%x\n",
|
||||
info->mr_type,
|
||||
info->max_frmr_depth);
|
||||
smbd_disconnect_rdma_connection(info);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (smbdirect_mr->state == MR_INVALIDATED)
|
||||
ib_dma_unmap_sg(
|
||||
info->id->device, smbdirect_mr->sgl,
|
||||
smbdirect_mr->sgl_count,
|
||||
smbdirect_mr->dir);
|
||||
smbdirect_mr->state = MR_READY;
|
||||
} else if (smbdirect_mr->state == MR_ERROR) {
|
||||
|
||||
/* recover this MR entry */
|
||||
rc = ib_dereg_mr(smbdirect_mr->mr);
|
||||
if (rc) {
|
||||
log_rdma_mr(ERR,
|
||||
"ib_dereg_mr failed rc=%x\n",
|
||||
rc);
|
||||
smbd_disconnect_rdma_connection(info);
|
||||
}
|
||||
smbdirect_mr->state = MR_READY;
|
||||
|
||||
smbdirect_mr->mr = ib_alloc_mr(
|
||||
info->pd, info->mr_type,
|
||||
info->max_frmr_depth);
|
||||
if (IS_ERR(smbdirect_mr->mr)) {
|
||||
log_rdma_mr(ERR,
|
||||
"ib_alloc_mr failed mr_type=%x "
|
||||
"max_frmr_depth=%x\n",
|
||||
info->mr_type,
|
||||
info->max_frmr_depth);
|
||||
smbd_disconnect_rdma_connection(info);
|
||||
}
|
||||
|
||||
smbdirect_mr->state = MR_READY;
|
||||
}
|
||||
/* smbdirect_mr->state is updated by this function
|
||||
* and is read and updated by I/O issuing CPUs trying
|
||||
* to get a MR, the call to atomic_inc_return
|
||||
|
@ -2460,7 +2475,7 @@ static struct smbd_mr *get_mr(struct smbd_connection *info)
|
|||
*/
|
||||
struct smbd_mr *smbd_register_mr(
|
||||
struct smbd_connection *info, struct page *pages[], int num_pages,
|
||||
int tailsz, bool writing, bool need_invalidate)
|
||||
int offset, int tailsz, bool writing, bool need_invalidate)
|
||||
{
|
||||
struct smbd_mr *smbdirect_mr;
|
||||
int rc, i;
|
||||
|
@ -2483,17 +2498,31 @@ struct smbd_mr *smbd_register_mr(
|
|||
smbdirect_mr->sgl_count = num_pages;
|
||||
sg_init_table(smbdirect_mr->sgl, num_pages);
|
||||
|
||||
for (i = 0; i < num_pages - 1; i++)
|
||||
sg_set_page(&smbdirect_mr->sgl[i], pages[i], PAGE_SIZE, 0);
|
||||
log_rdma_mr(INFO, "num_pages=0x%x offset=0x%x tailsz=0x%x\n",
|
||||
num_pages, offset, tailsz);
|
||||
|
||||
if (num_pages == 1) {
|
||||
sg_set_page(&smbdirect_mr->sgl[0], pages[0], tailsz, offset);
|
||||
goto skip_multiple_pages;
|
||||
}
|
||||
|
||||
/* We have at least two pages to register */
|
||||
sg_set_page(
|
||||
&smbdirect_mr->sgl[0], pages[0], PAGE_SIZE - offset, offset);
|
||||
i = 1;
|
||||
while (i < num_pages - 1) {
|
||||
sg_set_page(&smbdirect_mr->sgl[i], pages[i], PAGE_SIZE, 0);
|
||||
i++;
|
||||
}
|
||||
sg_set_page(&smbdirect_mr->sgl[i], pages[i],
|
||||
tailsz ? tailsz : PAGE_SIZE, 0);
|
||||
|
||||
skip_multiple_pages:
|
||||
dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
|
||||
smbdirect_mr->dir = dir;
|
||||
rc = ib_dma_map_sg(info->id->device, smbdirect_mr->sgl, num_pages, dir);
|
||||
if (!rc) {
|
||||
log_rdma_mr(INFO, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",
|
||||
log_rdma_mr(ERR, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",
|
||||
num_pages, dir, rc);
|
||||
goto dma_map_error;
|
||||
}
|
||||
|
@ -2501,8 +2530,8 @@ struct smbd_mr *smbd_register_mr(
|
|||
rc = ib_map_mr_sg(smbdirect_mr->mr, smbdirect_mr->sgl, num_pages,
|
||||
NULL, PAGE_SIZE);
|
||||
if (rc != num_pages) {
|
||||
log_rdma_mr(INFO,
|
||||
"ib_map_mr_sg failed rc = %x num_pages = %x\n",
|
||||
log_rdma_mr(ERR,
|
||||
"ib_map_mr_sg failed rc = %d num_pages = %x\n",
|
||||
rc, num_pages);
|
||||
goto map_mr_error;
|
||||
}
|
||||
|
|
|
@ -321,7 +321,7 @@ struct smbd_mr {
|
|||
/* Interfaces to register and deregister MR for RDMA read/write */
|
||||
struct smbd_mr *smbd_register_mr(
|
||||
struct smbd_connection *info, struct page *pages[], int num_pages,
|
||||
int tailsz, bool writing, bool need_invalidate);
|
||||
int offset, int tailsz, bool writing, bool need_invalidate);
|
||||
int smbd_deregister_mr(struct smbd_mr *mr);
|
||||
|
||||
#else
|
||||
|
|
|
@ -212,10 +212,24 @@ rqst_len(struct smb_rqst *rqst)
|
|||
for (i = 0; i < rqst->rq_nvec; i++)
|
||||
buflen += iov[i].iov_len;
|
||||
|
||||
/* add in the page array if there is one */
|
||||
/*
|
||||
* Add in the page array if there is one. The caller needs to make
|
||||
* sure rq_offset and rq_tailsz are set correctly. If a buffer of
|
||||
* multiple pages ends at page boundary, rq_tailsz needs to be set to
|
||||
* PAGE_SIZE.
|
||||
*/
|
||||
if (rqst->rq_npages) {
|
||||
buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
|
||||
buflen += rqst->rq_tailsz;
|
||||
if (rqst->rq_npages == 1)
|
||||
buflen += rqst->rq_tailsz;
|
||||
else {
|
||||
/*
|
||||
* If there is more than one page, calculate the
|
||||
* buffer length based on rq_offset and rq_tailsz
|
||||
*/
|
||||
buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
|
||||
rqst->rq_offset;
|
||||
buflen += rqst->rq_tailsz;
|
||||
}
|
||||
}
|
||||
|
||||
return buflen;
|
||||
|
@ -274,15 +288,13 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
|
|||
|
||||
/* now walk the page array and send each page in it */
|
||||
for (i = 0; i < rqst->rq_npages; i++) {
|
||||
size_t len = i == rqst->rq_npages - 1
|
||||
? rqst->rq_tailsz
|
||||
: rqst->rq_pagesz;
|
||||
struct bio_vec bvec = {
|
||||
.bv_page = rqst->rq_pages[i],
|
||||
.bv_len = len
|
||||
};
|
||||
struct bio_vec bvec;
|
||||
|
||||
bvec.bv_page = rqst->rq_pages[i];
|
||||
rqst_page_get_length(rqst, i, &bvec.bv_len, &bvec.bv_offset);
|
||||
|
||||
iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC,
|
||||
&bvec, 1, len);
|
||||
&bvec, 1, bvec.bv_len);
|
||||
rc = smb_send_kvec(server, &smb_msg, &sent);
|
||||
if (rc < 0)
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue