Commit bc925c12 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French
Browse files

smb: client: improve compound padding in encryption



After commit f7f291e1 ("cifs: fix oops during encryption"), the
encryption layer can handle vmalloc'd buffers as well as kmalloc'd
buffers, so there is no need to inefficiently squash request iovs
into a single one to handle padding in compound requests.

Cc: David Howells <dhowells@redhat.com>
Signed-off-by: default avatarPaulo Alcantara (Red Hat) <pc@manguebit.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 9ed9d83a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -2230,7 +2230,7 @@ static inline int cifs_get_num_sgs(const struct smb_rqst *rqst,
			struct kvec *iov = &rqst[i].rq_iov[j];

			addr = (unsigned long)iov->iov_base + skip;
			if (unlikely(is_vmalloc_addr((void *)addr))) {
			if (is_vmalloc_or_module_addr((void *)addr)) {
				len = iov->iov_len - skip;
				nents += DIV_ROUND_UP(offset_in_page(addr) + len,
						      PAGE_SIZE);
@@ -2257,7 +2257,7 @@ static inline void cifs_sg_set_buf(struct sg_table *sgtable,
	unsigned int off = offset_in_page(addr);

	addr &= PAGE_MASK;
	if (unlikely(is_vmalloc_addr((void *)addr))) {
	if (is_vmalloc_or_module_addr((void *)addr)) {
		do {
			unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off);

+3 −34
Original line number Diff line number Diff line
@@ -2606,7 +2606,7 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
	struct cifs_ses *ses = tcon->ses;
	struct TCP_Server_Info *server = ses->server;
	unsigned long len = smb_rqst_len(server, rqst);
	int i, num_padding;
	int num_padding;

	shdr = (struct smb2_hdr *)(rqst->rq_iov[0].iov_base);
	if (shdr == NULL) {
@@ -2615,44 +2615,13 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
	}

	/* SMB headers in a compound are 8 byte aligned. */

	/* No padding needed */
	if (!(len & 7))
		goto finished;

	if (!IS_ALIGNED(len, 8)) {
		num_padding = 8 - (len & 7);
	if (!smb3_encryption_required(tcon)) {
		/*
		 * If we do not have encryption then we can just add an extra
		 * iov for the padding.
		 */
		rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding;
		rqst->rq_iov[rqst->rq_nvec].iov_len = num_padding;
		rqst->rq_nvec++;
		len += num_padding;
	} else {
		/*
		 * We can not add a small padding iov for the encryption case
		 * because the encryption framework can not handle the padding
		 * iovs.
		 * We have to flatten this into a single buffer and add
		 * the padding to it.
		 */
		for (i = 1; i < rqst->rq_nvec; i++) {
			memcpy(rqst->rq_iov[0].iov_base +
			       rqst->rq_iov[0].iov_len,
			       rqst->rq_iov[i].iov_base,
			       rqst->rq_iov[i].iov_len);
			rqst->rq_iov[0].iov_len += rqst->rq_iov[i].iov_len;
		}
		memset(rqst->rq_iov[0].iov_base + rqst->rq_iov[0].iov_len,
		       0, num_padding);
		rqst->rq_iov[0].iov_len += num_padding;
		len += num_padding;
		rqst->rq_nvec = 1;
	}

 finished:
	shdr->NextCommand = cpu_to_le32(len);
}

+13 −27
Original line number Diff line number Diff line
@@ -418,19 +418,16 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
	return rc;
}

struct send_req_vars {
	struct smb2_transform_hdr tr_hdr;
	struct smb_rqst rqst[MAX_COMPOUND];
	struct kvec iov;
};

static int
smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
	      struct smb_rqst *rqst, int flags)
{
	struct send_req_vars *vars;
	struct smb_rqst *cur_rqst;
	struct kvec *iov;
	struct smb2_transform_hdr tr_hdr;
	struct smb_rqst new_rqst[MAX_COMPOUND] = {};
	struct kvec iov = {
		.iov_base = &tr_hdr,
		.iov_len = sizeof(tr_hdr),
	};
	int rc;

	if (flags & CIFS_COMPRESS_REQ)
@@ -447,26 +444,15 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
		return -EIO;
	}

	vars = kzalloc(sizeof(*vars), GFP_NOFS);
	if (!vars)
		return -ENOMEM;
	cur_rqst = vars->rqst;
	iov = &vars->iov;

	iov->iov_base = &vars->tr_hdr;
	iov->iov_len = sizeof(vars->tr_hdr);
	cur_rqst[0].rq_iov = iov;
	cur_rqst[0].rq_nvec = 1;
	new_rqst[0].rq_iov = &iov;
	new_rqst[0].rq_nvec = 1;

	rc = server->ops->init_transform_rq(server, num_rqst + 1,
					    &cur_rqst[0], rqst);
	if (rc)
		goto out;

	rc = __smb_send_rqst(server, num_rqst + 1, &cur_rqst[0]);
	smb3_free_compound_rqst(num_rqst, &cur_rqst[1]);
out:
	kfree(vars);
					    new_rqst, rqst);
	if (!rc) {
		rc = __smb_send_rqst(server, num_rqst + 1, new_rqst);
		smb3_free_compound_rqst(num_rqst, &new_rqst[1]);
	}
	return rc;
}