mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	NFS client bugfixes for Linux 4.4
Highlights include:
 
 Stable patches:
 - Fix a NFSv4 callback identifier leak that was also causing client crashes
 - Fix NFSv4 callback decoding issues when incoming requests are truncated
 - Don't declare the attribute cache valid when we call nfs_update_inode with
   an empty attribute structure.
 - Resend LAYOUTGET when there is a race that changes the seqid
 
 Bugfixes:
 - Fix a number of issues with the NFSv4.2 CLONE ioctl()
 - Properly set NFS v4.2 NFSDBG_FACILITY
 - NFSv4 referrals are broken; Cleanup FATTR4_WORD0_FS_LOCATIONS after
   decoding success
 - Use sliding delay when LAYOUTGET gets NFS4ERR_DELAY
 - Ensure that attrcache is revalidated after a SETATTR
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJWWPeyAAoJEGcL54qWCgDy9/UQAKNTF09OeHxSqO7oXbM4x0hY
 8a8A4ostTshtu4g6OWxeqI4/89A5lOcdHAoM/KOr+2HzssKA6B9lU4+pzcKfFI+U
 d9WqKVEC3MZA1N4KR+fS5LhtQU62izGKH+CQ9+tHvvesZu+bIiQgQu/uMzKVh2Al
 cKdDu99UxrxNP3PFDCcBtxpBvy27akT+21P8RutG12tqGQkfa1715JIQl9bqgquY
 ZruukMsqamp+LbZlnowgvoaBLBVUo19v8zwI34uSfXwNbQS71xmAV52z7HVHaEFt
 A8HQzS/MaFtMKpq7HOZYEnHB6h8YaYTK4GmHcCCFXHtjXopvHo8LXA6vYLTNhJ8V
 SvLpUJzUWVcGDDQ75x6iX/APPMSq0gxJA4+AZryBer3k2EvKlUoRrP+hgxOIK7HT
 2joWoFFKVe8a5NBj4Pd5+x6dpDEnIvlqGdMQNuXFUiPvcA/l3Uc0gnWhauuqvrhy
 ePrLRcWoSikLlPWxq39DRzJjQUdyUhBWMcCRWkhNzsT6U6HDSip5j0BkUBXD7nlU
 FK9BM2zRHr7kQ5Aax497K9qJNZBWI94y/vFkR/hJg0Z/bVQBF45lGxGgNFbj8Kag
 gR/xcYC9plum1IFD7DcnVnJTxrDSftIsLS8bhjmknxC8Pcyur2jegZvoDXiFk1GF
 gXERq36Ej/4WyyGrNyWm
 =5aPD
 -----END PGP SIGNATURE-----
Merge tag 'nfs-for-4.4-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust:
 "Highlights include:
  Stable patches:
   - Fix a NFSv4 callback identifier leak that was also causing client
     crashes
   - Fix NFSv4 callback decoding issues when incoming requests are
     truncated
   - Don't declare the attribute cache valid when we call
     nfs_update_inode with an empty attribute structure.
   - Resend LAYOUTGET when there is a race that changes the seqid
  Bugfixes:
   - Fix a number of issues with the NFSv4.2 CLONE ioctl()
   - Properly set NFS v4.2 NFSDBG_FACILITY
   - NFSv4 referrals are broken; Cleanup FATTR4_WORD0_FS_LOCATIONS after
     decoding success
   - Use sliding delay when LAYOUTGET gets NFS4ERR_DELAY
   - Ensure that attrcache is revalidated after a SETATTR"
* tag 'nfs-for-4.4-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  nfs4: resend LAYOUTGET when there is a race that changes the seqid
  nfs: if we have no valid attrs, then don't declare the attribute cache valid
  nfs: ensure that attrcache is revalidated after a SETATTR
  nfs4: limit callback decoding to received bytes
  nfs4: start callback_ident at idr 1
  nfs: use sliding delay when LAYOUTGET gets NFS4ERR_DELAY
  NFS4: Cleanup FATTR4_WORD0_FS_LOCATIONS after decoding success
  NFS: Properly set NFS v4.2 NFSDBG_FACILITY
  nfs: reduce the amount of ifdefs for v4.2 in nfs4file.c
  nfs: use btrfs ioctl defintions for clone
  nfs: allow intra-file CLONE
  nfs: offer native ioctls even if CONFIG_COMPAT is set
  nfs: pass on count for CLONE operations
			
			
This commit is contained in:
		
						commit
						8003a57356
					
				
					 12 changed files with 88 additions and 76 deletions
				
			
		|  | @ -78,7 +78,8 @@ static __be32 *read_buf(struct xdr_stream *xdr, int nbytes) | |||
| 
 | ||||
| 	p = xdr_inline_decode(xdr, nbytes); | ||||
| 	if (unlikely(p == NULL)) | ||||
| 		printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed!\n"); | ||||
| 		printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed " | ||||
| 							"or truncated request.\n"); | ||||
| 	return p; | ||||
| } | ||||
| 
 | ||||
|  | @ -889,6 +890,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
| 	struct cb_compound_hdr_arg hdr_arg = { 0 }; | ||||
| 	struct cb_compound_hdr_res hdr_res = { NULL }; | ||||
| 	struct xdr_stream xdr_in, xdr_out; | ||||
| 	struct xdr_buf *rq_arg = &rqstp->rq_arg; | ||||
| 	__be32 *p, status; | ||||
| 	struct cb_process_state cps = { | ||||
| 		.drc_status = 0, | ||||
|  | @ -900,7 +902,8 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
| 
 | ||||
| 	dprintk("%s: start\n", __func__); | ||||
| 
 | ||||
| 	xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base); | ||||
| 	rq_arg->len = rq_arg->head[0].iov_len + rq_arg->page_len; | ||||
| 	xdr_init_decode(&xdr_in, rq_arg, rq_arg->head[0].iov_base); | ||||
| 
 | ||||
| 	p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); | ||||
| 	xdr_init_encode(&xdr_out, &rqstp->rq_res, p); | ||||
|  |  | |||
|  | @ -618,7 +618,10 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, | |||
| 		nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); | ||||
| 		nfs_vmtruncate(inode, attr->ia_size); | ||||
| 	} | ||||
| 	nfs_update_inode(inode, fattr); | ||||
| 	if (fattr->valid) | ||||
| 		nfs_update_inode(inode, fattr); | ||||
| 	else | ||||
| 		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; | ||||
| 	spin_unlock(&inode->i_lock); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); | ||||
|  | @ -1824,7 +1827,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 		if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0) | ||||
| 			nfsi->attr_gencount = fattr->gencount; | ||||
| 	} | ||||
| 	invalid &= ~NFS_INO_INVALID_ATTR; | ||||
| 
 | ||||
| 	/* Don't declare attrcache up to date if there were no attrs! */ | ||||
| 	if (fattr->valid != 0) | ||||
| 		invalid &= ~NFS_INO_INVALID_ATTR; | ||||
| 
 | ||||
| 	/* Don't invalidate the data if we were to blame */ | ||||
| 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | ||||
| 				|| S_ISLNK(inode->i_mode))) | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
| #include "pnfs.h" | ||||
| #include "internal.h" | ||||
| 
 | ||||
| #define NFSDBG_FACILITY NFSDBG_PNFS | ||||
| #define NFSDBG_FACILITY NFSDBG_PROC | ||||
| 
 | ||||
| static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file, | ||||
| 				fmode_t fmode) | ||||
|  | @ -284,6 +284,7 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f, | |||
| 		.dst_fh = NFS_FH(dst_inode), | ||||
| 		.src_offset = src_offset, | ||||
| 		.dst_offset = dst_offset, | ||||
| 		.count = count, | ||||
| 		.dst_bitmask = server->cache_consistency_bitmask, | ||||
| 	}; | ||||
| 	struct nfs42_clone_res res = { | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) | |||
| 		return ret; | ||||
| 	idr_preload(GFP_KERNEL); | ||||
| 	spin_lock(&nn->nfs_client_lock); | ||||
| 	ret = idr_alloc(&nn->cb_ident_idr, clp, 0, 0, GFP_NOWAIT); | ||||
| 	ret = idr_alloc(&nn->cb_ident_idr, clp, 1, 0, GFP_NOWAIT); | ||||
| 	if (ret >= 0) | ||||
| 		clp->cl_cb_ident = ret; | ||||
| 	spin_unlock(&nn->nfs_client_lock); | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include <linux/file.h> | ||||
| #include <linux/falloc.h> | ||||
| #include <linux/nfs_fs.h> | ||||
| #include <uapi/linux/btrfs.h>	/* BTRFS_IOC_CLONE/BTRFS_IOC_CLONE_RANGE */ | ||||
| #include "delegation.h" | ||||
| #include "internal.h" | ||||
| #include "iostat.h" | ||||
|  | @ -203,6 +204,7 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | |||
| 	struct fd src_file; | ||||
| 	struct inode *src_inode; | ||||
| 	unsigned int bs = server->clone_blksize; | ||||
| 	bool same_inode = false; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/* dst file must be opened for writing */ | ||||
|  | @ -221,10 +223,8 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | |||
| 
 | ||||
| 	src_inode = file_inode(src_file.file); | ||||
| 
 | ||||
| 	/* src and dst must be different files */ | ||||
| 	ret = -EINVAL; | ||||
| 	if (src_inode == dst_inode) | ||||
| 		goto out_fput; | ||||
| 		same_inode = true; | ||||
| 
 | ||||
| 	/* src file must be opened for reading */ | ||||
| 	if (!(src_file.file->f_mode & FMODE_READ)) | ||||
|  | @ -249,8 +249,16 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | |||
| 			goto out_fput; | ||||
| 	} | ||||
| 
 | ||||
| 	/* verify if ranges are overlapped within the same file */ | ||||
| 	if (same_inode) { | ||||
| 		if (dst_off + count > src_off && dst_off < src_off + count) | ||||
| 			goto out_fput; | ||||
| 	} | ||||
| 
 | ||||
| 	/* XXX: do we lock at all? what if server needs CB_RECALL_LAYOUT? */ | ||||
| 	if (dst_inode < src_inode) { | ||||
| 	if (same_inode) { | ||||
| 		mutex_lock(&src_inode->i_mutex); | ||||
| 	} else if (dst_inode < src_inode) { | ||||
| 		mutex_lock_nested(&dst_inode->i_mutex, I_MUTEX_PARENT); | ||||
| 		mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_CHILD); | ||||
| 	} else { | ||||
|  | @ -275,7 +283,9 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | |||
| 		truncate_inode_pages_range(&dst_inode->i_data, dst_off, dst_off + count - 1); | ||||
| 
 | ||||
| out_unlock: | ||||
| 	if (dst_inode < src_inode) { | ||||
| 	if (same_inode) { | ||||
| 		mutex_unlock(&src_inode->i_mutex); | ||||
| 	} else if (dst_inode < src_inode) { | ||||
| 		mutex_unlock(&src_inode->i_mutex); | ||||
| 		mutex_unlock(&dst_inode->i_mutex); | ||||
| 	} else { | ||||
|  | @ -291,46 +301,31 @@ out_drop_write: | |||
| 
 | ||||
| static long nfs42_ioctl_clone_range(struct file *dst_file, void __user *argp) | ||||
| { | ||||
| 	struct nfs_ioctl_clone_range_args args; | ||||
| 	struct btrfs_ioctl_clone_range_args args; | ||||
| 
 | ||||
| 	if (copy_from_user(&args, argp, sizeof(args))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return nfs42_ioctl_clone(dst_file, args.src_fd, args.src_off, args.dst_off, args.count); | ||||
| 	return nfs42_ioctl_clone(dst_file, args.src_fd, args.src_offset, | ||||
| 				 args.dest_offset, args.src_length); | ||||
| } | ||||
| #else | ||||
| static long nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | ||||
| 		u64 src_off, u64 dst_off, u64 count) | ||||
| { | ||||
| 	return -ENOTTY; | ||||
| } | ||||
| 
 | ||||
| static long nfs42_ioctl_clone_range(struct file *dst_file, void __user *argp) | ||||
| { | ||||
| 	return -ENOTTY; | ||||
| } | ||||
| #endif /* CONFIG_NFS_V4_2 */ | ||||
| 
 | ||||
| long nfs4_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||||
| { | ||||
| 	void __user *argp = (void __user *)arg; | ||||
| 
 | ||||
| 	switch (cmd) { | ||||
| 	case NFS_IOC_CLONE: | ||||
| 	case BTRFS_IOC_CLONE: | ||||
| 		return nfs42_ioctl_clone(file, arg, 0, 0, 0); | ||||
| 	case NFS_IOC_CLONE_RANGE: | ||||
| 	case BTRFS_IOC_CLONE_RANGE: | ||||
| 		return nfs42_ioctl_clone_range(file, argp); | ||||
| 	} | ||||
| 
 | ||||
| 	return -ENOTTY; | ||||
| } | ||||
| #endif /* CONFIG_NFS_V4_2 */ | ||||
| 
 | ||||
| const struct file_operations nfs4_file_operations = { | ||||
| #ifdef CONFIG_NFS_V4_2 | ||||
| 	.llseek		= nfs4_file_llseek, | ||||
| #else | ||||
| 	.llseek		= nfs_file_llseek, | ||||
| #endif | ||||
| 	.read_iter	= nfs_file_read, | ||||
| 	.write_iter	= nfs_file_write, | ||||
| 	.mmap		= nfs_file_mmap, | ||||
|  | @ -342,14 +337,14 @@ const struct file_operations nfs4_file_operations = { | |||
| 	.flock		= nfs_flock, | ||||
| 	.splice_read	= nfs_file_splice_read, | ||||
| 	.splice_write	= iter_file_splice_write, | ||||
| #ifdef CONFIG_NFS_V4_2 | ||||
| 	.fallocate	= nfs42_fallocate, | ||||
| #endif /* CONFIG_NFS_V4_2 */ | ||||
| 	.check_flags	= nfs_check_flags, | ||||
| 	.setlease	= simple_nosetlease, | ||||
| #ifdef CONFIG_COMPAT | ||||
| #ifdef CONFIG_NFS_V4_2 | ||||
| 	.llseek		= nfs4_file_llseek, | ||||
| 	.fallocate	= nfs42_fallocate, | ||||
| 	.unlocked_ioctl = nfs4_ioctl, | ||||
| #else | ||||
| 	.compat_ioctl	= nfs4_ioctl, | ||||
| #endif /* CONFIG_COMPAT */ | ||||
| #else | ||||
| 	.llseek		= nfs_file_llseek, | ||||
| #endif | ||||
| }; | ||||
|  |  | |||
|  | @ -7866,7 +7866,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
| 			spin_unlock(&inode->i_lock); | ||||
| 		goto out_restart; | ||||
| 	} | ||||
| 	if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) | ||||
| 	if (nfs4_async_handle_error(task, server, state, &lgp->timeout) == -EAGAIN) | ||||
| 		goto out_restart; | ||||
| out: | ||||
| 	dprintk("<-- %s\n", __func__); | ||||
|  |  | |||
|  | @ -3615,6 +3615,7 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
| 	status = 0; | ||||
| 	if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) | ||||
| 		goto out; | ||||
| 	bitmap[0] &= ~FATTR4_WORD0_FS_LOCATIONS; | ||||
| 	status = -EIO; | ||||
| 	/* Ignore borken servers that return unrequested attrs */ | ||||
| 	if (unlikely(res == NULL)) | ||||
|  |  | |||
|  | @ -872,33 +872,38 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
| 
 | ||||
| 	dprintk("--> %s\n", __func__); | ||||
| 
 | ||||
| 	lgp = kzalloc(sizeof(*lgp), gfp_flags); | ||||
| 	if (lgp == NULL) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	i_size = i_size_read(ino); | ||||
| 
 | ||||
| 	lgp->args.minlength = PAGE_CACHE_SIZE; | ||||
| 	if (lgp->args.minlength > range->length) | ||||
| 		lgp->args.minlength = range->length; | ||||
| 	if (range->iomode == IOMODE_READ) { | ||||
| 		if (range->offset >= i_size) | ||||
| 			lgp->args.minlength = 0; | ||||
| 		else if (i_size - range->offset < lgp->args.minlength) | ||||
| 			lgp->args.minlength = i_size - range->offset; | ||||
| 	} | ||||
| 	lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; | ||||
| 	lgp->args.range = *range; | ||||
| 	lgp->args.type = server->pnfs_curr_ld->id; | ||||
| 	lgp->args.inode = ino; | ||||
| 	lgp->args.ctx = get_nfs_open_context(ctx); | ||||
| 	lgp->gfp_flags = gfp_flags; | ||||
| 	lgp->cred = lo->plh_lc_cred; | ||||
| 
 | ||||
| 	/* Synchronously retrieve layout information from server and
 | ||||
| 	 * store in lseg. | ||||
| 	/*
 | ||||
| 	 * Synchronously retrieve layout information from server and | ||||
| 	 * store in lseg. If we race with a concurrent seqid morphing | ||||
| 	 * op, then re-send the LAYOUTGET. | ||||
| 	 */ | ||||
| 	lseg = nfs4_proc_layoutget(lgp, gfp_flags); | ||||
| 	do { | ||||
| 		lgp = kzalloc(sizeof(*lgp), gfp_flags); | ||||
| 		if (lgp == NULL) | ||||
| 			return NULL; | ||||
| 
 | ||||
| 		i_size = i_size_read(ino); | ||||
| 
 | ||||
| 		lgp->args.minlength = PAGE_CACHE_SIZE; | ||||
| 		if (lgp->args.minlength > range->length) | ||||
| 			lgp->args.minlength = range->length; | ||||
| 		if (range->iomode == IOMODE_READ) { | ||||
| 			if (range->offset >= i_size) | ||||
| 				lgp->args.minlength = 0; | ||||
| 			else if (i_size - range->offset < lgp->args.minlength) | ||||
| 				lgp->args.minlength = i_size - range->offset; | ||||
| 		} | ||||
| 		lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; | ||||
| 		lgp->args.range = *range; | ||||
| 		lgp->args.type = server->pnfs_curr_ld->id; | ||||
| 		lgp->args.inode = ino; | ||||
| 		lgp->args.ctx = get_nfs_open_context(ctx); | ||||
| 		lgp->gfp_flags = gfp_flags; | ||||
| 		lgp->cred = lo->plh_lc_cred; | ||||
| 
 | ||||
| 		lseg = nfs4_proc_layoutget(lgp, gfp_flags); | ||||
| 	} while (lseg == ERR_PTR(-EAGAIN)); | ||||
| 
 | ||||
| 	if (IS_ERR(lseg)) { | ||||
| 		switch (PTR_ERR(lseg)) { | ||||
| 		case -ENOMEM: | ||||
|  | @ -1687,6 +1692,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
| 		/* existing state ID, make sure the sequence number matches. */ | ||||
| 		if (pnfs_layout_stateid_blocked(lo, &res->stateid)) { | ||||
| 			dprintk("%s forget reply due to sequence\n", __func__); | ||||
| 			status = -EAGAIN; | ||||
| 			goto out_forget_reply; | ||||
| 		} | ||||
| 		pnfs_set_layout_stateid(lo, &res->stateid, false); | ||||
|  |  | |||
|  | @ -251,6 +251,7 @@ struct nfs4_layoutget { | |||
| 	struct nfs4_layoutget_res res; | ||||
| 	struct rpc_cred *cred; | ||||
| 	gfp_t gfp_flags; | ||||
| 	long timeout; | ||||
| }; | ||||
| 
 | ||||
| struct nfs4_getdeviceinfo_args { | ||||
|  |  | |||
|  | @ -33,17 +33,6 @@ | |||
| 
 | ||||
| #define NFS_PIPE_DIRNAME "nfs" | ||||
| 
 | ||||
| /* NFS ioctls */ | ||||
| /* Let's follow btrfs lead on CLONE to avoid messing userspace */ | ||||
| #define NFS_IOC_CLONE		_IOW(0x94, 9, int) | ||||
| #define NFS_IOC_CLONE_RANGE	_IOW(0x94, 13, int) | ||||
| 
 | ||||
| struct nfs_ioctl_clone_range_args { | ||||
| 	__s64 src_fd; | ||||
| 	__u64 src_off, count; | ||||
| 	__u64 dst_off; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * NFS stats. The good thing with these values is that NFSv3 errors are | ||||
|  * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which | ||||
|  |  | |||
|  | @ -353,12 +353,20 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) | |||
| { | ||||
| 	struct rpc_xprt *xprt = req->rq_xprt; | ||||
| 	struct svc_serv *bc_serv = xprt->bc_serv; | ||||
| 	struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf; | ||||
| 
 | ||||
| 	spin_lock(&xprt->bc_pa_lock); | ||||
| 	list_del(&req->rq_bc_pa_list); | ||||
| 	xprt_dec_alloc_count(xprt, 1); | ||||
| 	spin_unlock(&xprt->bc_pa_lock); | ||||
| 
 | ||||
| 	if (copied <= rq_rcv_buf->head[0].iov_len) { | ||||
| 		rq_rcv_buf->head[0].iov_len = copied; | ||||
| 		rq_rcv_buf->page_len = 0; | ||||
| 	} else { | ||||
| 		rq_rcv_buf->page_len = copied - rq_rcv_buf->head[0].iov_len; | ||||
| 	} | ||||
| 
 | ||||
| 	req->rq_private_buf.len = copied; | ||||
| 	set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1363,6 +1363,7 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, | |||
| 	memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); | ||||
| 	memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); | ||||
| 	memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); | ||||
| 	rqstp->rq_arg.len = req->rq_private_buf.len; | ||||
| 
 | ||||
| 	/* reset result send buffer "put" position */ | ||||
| 	resv->iov_len = 0; | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds