Commit 86987d84 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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()
parents 46d22bfd 416871f4
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -254,7 +254,6 @@ struct cifs_open_info_data {
struct smb_rqst {
	struct kvec	*rq_iov;	/* array of kvecs */
	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 xarray	rq_buffer;	/* Page buffer for encryption */
};
+0 −1
Original line number Diff line number Diff line
@@ -1713,7 +1713,6 @@ cifs_async_writev(struct cifs_io_subrequest *wdata)
	rqst.rq_iov = iov;
	rqst.rq_nvec = 2;
	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",
		 wdata->subreq.start, wdata->subreq.len);
+22 −2
Original line number Diff line number Diff line
@@ -3305,6 +3305,7 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
	struct inode *inode = file_inode(file);
	struct cifsFileInfo *cfile = file->private_data;
	struct file_zero_data_information fsctl_buf;
	unsigned long long end = offset + len, i_size, remote_i_size;
	long rc;
	unsigned int xid;
	__u8 set_sparse = 1;
@@ -3336,6 +3337,27 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
			(char *)&fsctl_buf,
			sizeof(struct file_zero_data_information),
			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);
out:
	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,
					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;
	if (iter) {
		rqst.rq_iter = *iter;
		rqst.rq_iter_size = iov_iter_count(iter);
		iter_size = iov_iter_count(iter);
	}

+21 −23
Original line number Diff line number Diff line
@@ -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
	 * 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;
		bool need_invalidate = server->dialect == SMB30_PROT_ID;

@@ -4523,7 +4523,6 @@ smb2_readv_callback(struct mid_q_entry *mid)

	if (rdata->got_bytes) {
		rqst.rq_iter	  = rdata->subreq.io_iter;
		rqst.rq_iter_size = iov_iter_count(&rdata->subreq.io_iter);
	}

	WARN_ONCE(rdata->server != mid->server,
@@ -4914,6 +4913,13 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
	if (rc)
		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))
		flags |= CIFS_TRANSFORM_REQ;

@@ -4925,6 +4931,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
	req->WriteChannelInfoOffset = 0;
	req->WriteChannelInfoLength = 0;
	req->Channel = SMB2_CHANNEL_NONE;
	req->Length = cpu_to_le32(io_parms->length);
	req->Offset = cpu_to_le64(io_parms->offset);
	req->DataOffset = cpu_to_le16(
				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)) {
		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;

		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;
			goto async_writev_out;
		}
		/* For RDMA read, I/O size is in RemainingBytes not in Length */
		req->RemainingBytes = req->Length;
		req->Length = 0;
		req->DataOffset = 0;
		req->RemainingBytes = cpu_to_le32(data_size);
		req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
		if (need_invalidate)
			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->token = cpu_to_le32(wdata->mr->mr->rkey);
		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
	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))
		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
	/* For RDMA read, I/O size is in RemainingBytes not in Length */
	if (!wdata->mr)
		req->Length = cpu_to_le32(io_parms->length);
#else
	req->Length = cpu_to_le32(io_parms->length);
#endif
	cifs_dbg(FYI, "async write at %llu %u bytes iter=%zx\n",
		 io_parms->offset, io_parms->length, iov_iter_count(&wdata->subreq.io_iter));

	if (wdata->credits.value > 0) {
		shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->subreq.len,