1

four cifs.ko client fixes

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmbOBa8ACgkQiiy9cAdy
 T1GHBAwAmSK9FTCg4x5tTRBwiS9VSrC3KQ2TwLrkXjeWXhJycZjsDQHnbHG68Q+t
 Sbq711RClpdvwMWLUqiryjd+VVqPzG/9jZLOPeeW7SIljyksUzxaQXGbGcquz57N
 hnZjrjyyquU5NhtOALyVeO4lNYboYTH+fETsrMoJIGNoI0yBHZSM/eRQO1heLRBn
 629yKbqp0m/5/A/w3s1nKljO74sG//6LKDZld6es7tmxgku8TFNEqsI7SONw3pUg
 dYgM2kIPf4rwpqupfxSriylz0xlHIEmITn5wkvygS+TvcWXsG855TVLjtD1I6uX3
 JYOZ9gfqubGNXkT5SbbfsmAOma8PBm54oT0UWwJVUj/5Ed3D9EyBl2jlqjNLQjSU
 qJ0/ha+AyFCn2vviPA+vVnHd5I2Y82JlI4VrwrSyHG5E/6UMHNQ2Do8GbA/eRdcp
 HeqR57V4VNzNzVfKCp4XygwBuifbXdRX+yrUdBPDZm+CMLPD6wGZdUQu4FaESYv6
 i24UdVG9
 =BDrz
 -----END PGP SIGNATURE-----

Merge tag 'v6.11-rc5-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - two RDMA/smbdirect fixes and a minor cleanup

 - punch hole fix

* tag 'v6.11-rc5-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: Fix FALLOC_FL_PUNCH_HOLE support
  smb/client: fix rdma usage in smb2_async_writev()
  smb/client: remove unused rq_iter_size from struct smb_rqst
  smb/client: avoid dereferencing rdata=NULL in smb2_new_read_req()
This commit is contained in:
Linus Torvalds 2024-08-28 15:05:02 +12:00
commit 86987d84b9
4 changed files with 43 additions and 27 deletions

View File

@ -254,7 +254,6 @@ struct cifs_open_info_data {
struct smb_rqst { struct smb_rqst {
struct kvec *rq_iov; /* array of kvecs */ struct kvec *rq_iov; /* array of kvecs */
unsigned int rq_nvec; /* number of kvecs in array */ unsigned int rq_nvec; /* number of kvecs in array */
size_t rq_iter_size; /* Amount of data in ->rq_iter */
struct iov_iter rq_iter; /* Data iterator */ struct iov_iter rq_iter; /* Data iterator */
struct xarray rq_buffer; /* Page buffer for encryption */ struct xarray rq_buffer; /* Page buffer for encryption */
}; };

View File

@ -1713,7 +1713,6 @@ cifs_async_writev(struct cifs_io_subrequest *wdata)
rqst.rq_iov = iov; rqst.rq_iov = iov;
rqst.rq_nvec = 2; rqst.rq_nvec = 2;
rqst.rq_iter = wdata->subreq.io_iter; rqst.rq_iter = wdata->subreq.io_iter;
rqst.rq_iter_size = iov_iter_count(&wdata->subreq.io_iter);
cifs_dbg(FYI, "async write at %llu %zu bytes\n", cifs_dbg(FYI, "async write at %llu %zu bytes\n",
wdata->subreq.start, wdata->subreq.len); wdata->subreq.start, wdata->subreq.len);

View File

@ -3305,6 +3305,7 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct cifsFileInfo *cfile = file->private_data; struct cifsFileInfo *cfile = file->private_data;
struct file_zero_data_information fsctl_buf; struct file_zero_data_information fsctl_buf;
unsigned long long end = offset + len, i_size, remote_i_size;
long rc; long rc;
unsigned int xid; unsigned int xid;
__u8 set_sparse = 1; __u8 set_sparse = 1;
@ -3336,6 +3337,27 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
(char *)&fsctl_buf, (char *)&fsctl_buf,
sizeof(struct file_zero_data_information), sizeof(struct file_zero_data_information),
CIFSMaxBufSize, NULL, NULL); CIFSMaxBufSize, NULL, NULL);
if (rc)
goto unlock;
/* If there's dirty data in the buffer that would extend the EOF if it
* were written, then we need to move the EOF marker over to the lower
* of the high end of the hole and the proposed EOF. The problem is
* that we locally hole-punch the tail of the dirty data, the proposed
* EOF update will end up in the wrong place.
*/
i_size = i_size_read(inode);
remote_i_size = netfs_inode(inode)->remote_i_size;
if (end > remote_i_size && i_size > remote_i_size) {
unsigned long long extend_to = umin(end, i_size);
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, cfile->pid, extend_to);
if (rc >= 0)
netfs_inode(inode)->remote_i_size = extend_to;
}
unlock:
filemap_invalidate_unlock(inode->i_mapping); filemap_invalidate_unlock(inode->i_mapping);
out: out:
inode_unlock(inode); inode_unlock(inode);
@ -4446,7 +4468,6 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
} }
iov_iter_xarray(&new->rq_iter, ITER_SOURCE, iov_iter_xarray(&new->rq_iter, ITER_SOURCE,
buffer, 0, size); buffer, 0, size);
new->rq_iter_size = size;
} }
} }
@ -4492,7 +4513,6 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
rqst.rq_nvec = 2; rqst.rq_nvec = 2;
if (iter) { if (iter) {
rqst.rq_iter = *iter; rqst.rq_iter = *iter;
rqst.rq_iter_size = iov_iter_count(iter);
iter_size = iov_iter_count(iter); iter_size = iov_iter_count(iter);
} }

View File

@ -4441,7 +4441,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
* If we want to do a RDMA write, fill in and append * If we want to do a RDMA write, fill in and append
* smbd_buffer_descriptor_v1 to the end of read request * smbd_buffer_descriptor_v1 to the end of read request
*/ */
if (smb3_use_rdma_offload(io_parms)) { if (rdata && smb3_use_rdma_offload(io_parms)) {
struct smbd_buffer_descriptor_v1 *v1; struct smbd_buffer_descriptor_v1 *v1;
bool need_invalidate = server->dialect == SMB30_PROT_ID; bool need_invalidate = server->dialect == SMB30_PROT_ID;
@ -4523,7 +4523,6 @@ smb2_readv_callback(struct mid_q_entry *mid)
if (rdata->got_bytes) { if (rdata->got_bytes) {
rqst.rq_iter = rdata->subreq.io_iter; rqst.rq_iter = rdata->subreq.io_iter;
rqst.rq_iter_size = iov_iter_count(&rdata->subreq.io_iter);
} }
WARN_ONCE(rdata->server != mid->server, WARN_ONCE(rdata->server != mid->server,
@ -4914,6 +4913,13 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
if (rc) if (rc)
goto out; goto out;
rqst.rq_iov = iov;
rqst.rq_iter = wdata->subreq.io_iter;
rqst.rq_iov[0].iov_len = total_len - 1;
rqst.rq_iov[0].iov_base = (char *)req;
rqst.rq_nvec += 1;
if (smb3_encryption_required(tcon)) if (smb3_encryption_required(tcon))
flags |= CIFS_TRANSFORM_REQ; flags |= CIFS_TRANSFORM_REQ;
@ -4925,6 +4931,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
req->WriteChannelInfoOffset = 0; req->WriteChannelInfoOffset = 0;
req->WriteChannelInfoLength = 0; req->WriteChannelInfoLength = 0;
req->Channel = SMB2_CHANNEL_NONE; req->Channel = SMB2_CHANNEL_NONE;
req->Length = cpu_to_le32(io_parms->length);
req->Offset = cpu_to_le64(io_parms->offset); req->Offset = cpu_to_le64(io_parms->offset);
req->DataOffset = cpu_to_le16( req->DataOffset = cpu_to_le16(
offsetof(struct smb2_write_req, Buffer)); offsetof(struct smb2_write_req, Buffer));
@ -4944,7 +4951,6 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
*/ */
if (smb3_use_rdma_offload(io_parms)) { if (smb3_use_rdma_offload(io_parms)) {
struct smbd_buffer_descriptor_v1 *v1; struct smbd_buffer_descriptor_v1 *v1;
size_t data_size = iov_iter_count(&wdata->subreq.io_iter);
bool need_invalidate = server->dialect == SMB30_PROT_ID; bool need_invalidate = server->dialect == SMB30_PROT_ID;
wdata->mr = smbd_register_mr(server->smbd_conn, &wdata->subreq.io_iter, wdata->mr = smbd_register_mr(server->smbd_conn, &wdata->subreq.io_iter,
@ -4953,9 +4959,10 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
rc = -EAGAIN; rc = -EAGAIN;
goto async_writev_out; goto async_writev_out;
} }
/* For RDMA read, I/O size is in RemainingBytes not in Length */
req->RemainingBytes = req->Length;
req->Length = 0; req->Length = 0;
req->DataOffset = 0; req->DataOffset = 0;
req->RemainingBytes = cpu_to_le32(data_size);
req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE; req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
if (need_invalidate) if (need_invalidate)
req->Channel = SMB2_CHANNEL_RDMA_V1; req->Channel = SMB2_CHANNEL_RDMA_V1;
@ -4967,31 +4974,22 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
v1->offset = cpu_to_le64(wdata->mr->mr->iova); v1->offset = cpu_to_le64(wdata->mr->mr->iova);
v1->token = cpu_to_le32(wdata->mr->mr->rkey); v1->token = cpu_to_le32(wdata->mr->mr->rkey);
v1->length = cpu_to_le32(wdata->mr->mr->length); v1->length = cpu_to_le32(wdata->mr->mr->length);
rqst.rq_iov[0].iov_len += sizeof(*v1);
/*
* We keep wdata->subreq.io_iter,
* but we have to truncate rqst.rq_iter
*/
iov_iter_truncate(&rqst.rq_iter, 0);
} }
#endif #endif
iov[0].iov_len = total_len - 1;
iov[0].iov_base = (char *)req;
rqst.rq_iov = iov;
rqst.rq_nvec = 1;
rqst.rq_iter = wdata->subreq.io_iter;
rqst.rq_iter_size = iov_iter_count(&rqst.rq_iter);
if (test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags)) if (test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags))
smb2_set_replay(server, &rqst); smb2_set_replay(server, &rqst);
#ifdef CONFIG_CIFS_SMB_DIRECT
if (wdata->mr)
iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1);
#endif
cifs_dbg(FYI, "async write at %llu %u bytes iter=%zx\n",
io_parms->offset, io_parms->length, iov_iter_count(&rqst.rq_iter));
#ifdef CONFIG_CIFS_SMB_DIRECT cifs_dbg(FYI, "async write at %llu %u bytes iter=%zx\n",
/* For RDMA read, I/O size is in RemainingBytes not in Length */ io_parms->offset, io_parms->length, iov_iter_count(&wdata->subreq.io_iter));
if (!wdata->mr)
req->Length = cpu_to_le32(io_parms->length);
#else
req->Length = cpu_to_le32(io_parms->length);
#endif
if (wdata->credits.value > 0) { if (wdata->credits.value > 0) {
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->subreq.len, shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->subreq.len,