diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-27 20:22:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-27 20:22:47 -0500 |
commit | 8003a573560ae96540bce2a698347c6d502e2997 (patch) | |
tree | dd75a298d9659359a3dfc1b453881ac0312e93b7 | |
parent | d0bc387dbe7f93b5608e1d305a18f50060de69cb (diff) | |
parent | 4f2e9dce0c6348a95eaa56ade9bab18572221088 (diff) |
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
-rw-r--r-- | fs/nfs/callback_xdr.c | 7 | ||||
-rw-r--r-- | fs/nfs/inode.c | 11 | ||||
-rw-r--r-- | fs/nfs/nfs42proc.c | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4file.c | 59 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 1 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 56 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/nfs.h | 11 | ||||
-rw-r--r-- | net/sunrpc/backchannel_rqst.c | 8 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 1 |
12 files changed, 87 insertions, 75 deletions
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 646cdac73488..beac58b0e09c 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -78,7 +78,8 @@ static __be32 *read_buf(struct xdr_stream *xdr, int nbytes) | |||
78 | 78 | ||
79 | p = xdr_inline_decode(xdr, nbytes); | 79 | p = xdr_inline_decode(xdr, nbytes); |
80 | if (unlikely(p == NULL)) | 80 | if (unlikely(p == NULL)) |
81 | printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed!\n"); | 81 | printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed " |
82 | "or truncated request.\n"); | ||
82 | return p; | 83 | return p; |
83 | } | 84 | } |
84 | 85 | ||
@@ -889,6 +890,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
889 | struct cb_compound_hdr_arg hdr_arg = { 0 }; | 890 | struct cb_compound_hdr_arg hdr_arg = { 0 }; |
890 | struct cb_compound_hdr_res hdr_res = { NULL }; | 891 | struct cb_compound_hdr_res hdr_res = { NULL }; |
891 | struct xdr_stream xdr_in, xdr_out; | 892 | struct xdr_stream xdr_in, xdr_out; |
893 | struct xdr_buf *rq_arg = &rqstp->rq_arg; | ||
892 | __be32 *p, status; | 894 | __be32 *p, status; |
893 | struct cb_process_state cps = { | 895 | struct cb_process_state cps = { |
894 | .drc_status = 0, | 896 | .drc_status = 0, |
@@ -900,7 +902,8 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
900 | 902 | ||
901 | dprintk("%s: start\n", __func__); | 903 | dprintk("%s: start\n", __func__); |
902 | 904 | ||
903 | xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base); | 905 | rq_arg->len = rq_arg->head[0].iov_len + rq_arg->page_len; |
906 | xdr_init_decode(&xdr_in, rq_arg, rq_arg->head[0].iov_base); | ||
904 | 907 | ||
905 | p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); | 908 | p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); |
906 | xdr_init_encode(&xdr_out, &rqstp->rq_res, p); | 909 | xdr_init_encode(&xdr_out, &rqstp->rq_res, p); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 326d9e10d833..31b0a52223a7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -618,7 +618,10 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, | |||
618 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); | 618 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); |
619 | nfs_vmtruncate(inode, attr->ia_size); | 619 | nfs_vmtruncate(inode, attr->ia_size); |
620 | } | 620 | } |
621 | nfs_update_inode(inode, fattr); | 621 | if (fattr->valid) |
622 | nfs_update_inode(inode, fattr); | ||
623 | else | ||
624 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; | ||
622 | spin_unlock(&inode->i_lock); | 625 | spin_unlock(&inode->i_lock); |
623 | } | 626 | } |
624 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); | 627 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); |
@@ -1824,7 +1827,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1824 | if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0) | 1827 | if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0) |
1825 | nfsi->attr_gencount = fattr->gencount; | 1828 | nfsi->attr_gencount = fattr->gencount; |
1826 | } | 1829 | } |
1827 | invalid &= ~NFS_INO_INVALID_ATTR; | 1830 | |
1831 | /* Don't declare attrcache up to date if there were no attrs! */ | ||
1832 | if (fattr->valid != 0) | ||
1833 | invalid &= ~NFS_INO_INVALID_ATTR; | ||
1834 | |||
1828 | /* Don't invalidate the data if we were to blame */ | 1835 | /* Don't invalidate the data if we were to blame */ |
1829 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1836 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
1830 | || S_ISLNK(inode->i_mode))) | 1837 | || S_ISLNK(inode->i_mode))) |
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 3e92a3cde15d..6b1ce9825430 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include "pnfs.h" | 14 | #include "pnfs.h" |
15 | #include "internal.h" | 15 | #include "internal.h" |
16 | 16 | ||
17 | #define NFSDBG_FACILITY NFSDBG_PNFS | 17 | #define NFSDBG_FACILITY NFSDBG_PROC |
18 | 18 | ||
19 | static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file, | 19 | static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file, |
20 | fmode_t fmode) | 20 | fmode_t fmode) |
@@ -284,6 +284,7 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f, | |||
284 | .dst_fh = NFS_FH(dst_inode), | 284 | .dst_fh = NFS_FH(dst_inode), |
285 | .src_offset = src_offset, | 285 | .src_offset = src_offset, |
286 | .dst_offset = dst_offset, | 286 | .dst_offset = dst_offset, |
287 | .count = count, | ||
287 | .dst_bitmask = server->cache_consistency_bitmask, | 288 | .dst_bitmask = server->cache_consistency_bitmask, |
288 | }; | 289 | }; |
289 | struct nfs42_clone_res res = { | 290 | struct nfs42_clone_res res = { |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 223bedda64ae..10410e8b5853 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -33,7 +33,7 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) | |||
33 | return ret; | 33 | return ret; |
34 | idr_preload(GFP_KERNEL); | 34 | idr_preload(GFP_KERNEL); |
35 | spin_lock(&nn->nfs_client_lock); | 35 | spin_lock(&nn->nfs_client_lock); |
36 | ret = idr_alloc(&nn->cb_ident_idr, clp, 0, 0, GFP_NOWAIT); | 36 | ret = idr_alloc(&nn->cb_ident_idr, clp, 1, 0, GFP_NOWAIT); |
37 | if (ret >= 0) | 37 | if (ret >= 0) |
38 | clp->cl_cb_ident = ret; | 38 | clp->cl_cb_ident = ret; |
39 | spin_unlock(&nn->nfs_client_lock); | 39 | spin_unlock(&nn->nfs_client_lock); |
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 4aa571956cd6..db9b5fea5b3e 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/file.h> | 7 | #include <linux/file.h> |
8 | #include <linux/falloc.h> | 8 | #include <linux/falloc.h> |
9 | #include <linux/nfs_fs.h> | 9 | #include <linux/nfs_fs.h> |
10 | #include <uapi/linux/btrfs.h> /* BTRFS_IOC_CLONE/BTRFS_IOC_CLONE_RANGE */ | ||
10 | #include "delegation.h" | 11 | #include "delegation.h" |
11 | #include "internal.h" | 12 | #include "internal.h" |
12 | #include "iostat.h" | 13 | #include "iostat.h" |
@@ -203,6 +204,7 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | |||
203 | struct fd src_file; | 204 | struct fd src_file; |
204 | struct inode *src_inode; | 205 | struct inode *src_inode; |
205 | unsigned int bs = server->clone_blksize; | 206 | unsigned int bs = server->clone_blksize; |
207 | bool same_inode = false; | ||
206 | int ret; | 208 | int ret; |
207 | 209 | ||
208 | /* dst file must be opened for writing */ | 210 | /* dst file must be opened for writing */ |
@@ -221,10 +223,8 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | |||
221 | 223 | ||
222 | src_inode = file_inode(src_file.file); | 224 | src_inode = file_inode(src_file.file); |
223 | 225 | ||
224 | /* src and dst must be different files */ | ||
225 | ret = -EINVAL; | ||
226 | if (src_inode == dst_inode) | 226 | if (src_inode == dst_inode) |
227 | goto out_fput; | 227 | same_inode = true; |
228 | 228 | ||
229 | /* src file must be opened for reading */ | 229 | /* src file must be opened for reading */ |
230 | if (!(src_file.file->f_mode & FMODE_READ)) | 230 | if (!(src_file.file->f_mode & FMODE_READ)) |
@@ -249,8 +249,16 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | |||
249 | goto out_fput; | 249 | goto out_fput; |
250 | } | 250 | } |
251 | 251 | ||
252 | /* verify if ranges are overlapped within the same file */ | ||
253 | if (same_inode) { | ||
254 | if (dst_off + count > src_off && dst_off < src_off + count) | ||
255 | goto out_fput; | ||
256 | } | ||
257 | |||
252 | /* XXX: do we lock at all? what if server needs CB_RECALL_LAYOUT? */ | 258 | /* XXX: do we lock at all? what if server needs CB_RECALL_LAYOUT? */ |
253 | if (dst_inode < src_inode) { | 259 | if (same_inode) { |
260 | mutex_lock(&src_inode->i_mutex); | ||
261 | } else if (dst_inode < src_inode) { | ||
254 | mutex_lock_nested(&dst_inode->i_mutex, I_MUTEX_PARENT); | 262 | mutex_lock_nested(&dst_inode->i_mutex, I_MUTEX_PARENT); |
255 | mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_CHILD); | 263 | mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_CHILD); |
256 | } else { | 264 | } else { |
@@ -275,7 +283,9 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | |||
275 | truncate_inode_pages_range(&dst_inode->i_data, dst_off, dst_off + count - 1); | 283 | truncate_inode_pages_range(&dst_inode->i_data, dst_off, dst_off + count - 1); |
276 | 284 | ||
277 | out_unlock: | 285 | out_unlock: |
278 | if (dst_inode < src_inode) { | 286 | if (same_inode) { |
287 | mutex_unlock(&src_inode->i_mutex); | ||
288 | } else if (dst_inode < src_inode) { | ||
279 | mutex_unlock(&src_inode->i_mutex); | 289 | mutex_unlock(&src_inode->i_mutex); |
280 | mutex_unlock(&dst_inode->i_mutex); | 290 | mutex_unlock(&dst_inode->i_mutex); |
281 | } else { | 291 | } else { |
@@ -291,46 +301,31 @@ out_drop_write: | |||
291 | 301 | ||
292 | static long nfs42_ioctl_clone_range(struct file *dst_file, void __user *argp) | 302 | static long nfs42_ioctl_clone_range(struct file *dst_file, void __user *argp) |
293 | { | 303 | { |
294 | struct nfs_ioctl_clone_range_args args; | 304 | struct btrfs_ioctl_clone_range_args args; |
295 | 305 | ||
296 | if (copy_from_user(&args, argp, sizeof(args))) | 306 | if (copy_from_user(&args, argp, sizeof(args))) |
297 | return -EFAULT; | 307 | return -EFAULT; |
298 | 308 | ||
299 | return nfs42_ioctl_clone(dst_file, args.src_fd, args.src_off, args.dst_off, args.count); | 309 | return nfs42_ioctl_clone(dst_file, args.src_fd, args.src_offset, |
300 | } | 310 | args.dest_offset, args.src_length); |
301 | #else | ||
302 | static long nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, | ||
303 | u64 src_off, u64 dst_off, u64 count) | ||
304 | { | ||
305 | return -ENOTTY; | ||
306 | } | ||
307 | |||
308 | static long nfs42_ioctl_clone_range(struct file *dst_file, void __user *argp) | ||
309 | { | ||
310 | return -ENOTTY; | ||
311 | } | 311 | } |
312 | #endif /* CONFIG_NFS_V4_2 */ | ||
313 | 312 | ||
314 | long nfs4_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 313 | long nfs4_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
315 | { | 314 | { |
316 | void __user *argp = (void __user *)arg; | 315 | void __user *argp = (void __user *)arg; |
317 | 316 | ||
318 | switch (cmd) { | 317 | switch (cmd) { |
319 | case NFS_IOC_CLONE: | 318 | case BTRFS_IOC_CLONE: |
320 | return nfs42_ioctl_clone(file, arg, 0, 0, 0); | 319 | return nfs42_ioctl_clone(file, arg, 0, 0, 0); |
321 | case NFS_IOC_CLONE_RANGE: | 320 | case BTRFS_IOC_CLONE_RANGE: |
322 | return nfs42_ioctl_clone_range(file, argp); | 321 | return nfs42_ioctl_clone_range(file, argp); |
323 | } | 322 | } |
324 | 323 | ||
325 | return -ENOTTY; | 324 | return -ENOTTY; |
326 | } | 325 | } |
326 | #endif /* CONFIG_NFS_V4_2 */ | ||
327 | 327 | ||
328 | const struct file_operations nfs4_file_operations = { | 328 | const struct file_operations nfs4_file_operations = { |
329 | #ifdef CONFIG_NFS_V4_2 | ||
330 | .llseek = nfs4_file_llseek, | ||
331 | #else | ||
332 | .llseek = nfs_file_llseek, | ||
333 | #endif | ||
334 | .read_iter = nfs_file_read, | 329 | .read_iter = nfs_file_read, |
335 | .write_iter = nfs_file_write, | 330 | .write_iter = nfs_file_write, |
336 | .mmap = nfs_file_mmap, | 331 | .mmap = nfs_file_mmap, |
@@ -342,14 +337,14 @@ const struct file_operations nfs4_file_operations = { | |||
342 | .flock = nfs_flock, | 337 | .flock = nfs_flock, |
343 | .splice_read = nfs_file_splice_read, | 338 | .splice_read = nfs_file_splice_read, |
344 | .splice_write = iter_file_splice_write, | 339 | .splice_write = iter_file_splice_write, |
345 | #ifdef CONFIG_NFS_V4_2 | ||
346 | .fallocate = nfs42_fallocate, | ||
347 | #endif /* CONFIG_NFS_V4_2 */ | ||
348 | .check_flags = nfs_check_flags, | 340 | .check_flags = nfs_check_flags, |
349 | .setlease = simple_nosetlease, | 341 | .setlease = simple_nosetlease, |
350 | #ifdef CONFIG_COMPAT | 342 | #ifdef CONFIG_NFS_V4_2 |
343 | .llseek = nfs4_file_llseek, | ||
344 | .fallocate = nfs42_fallocate, | ||
351 | .unlocked_ioctl = nfs4_ioctl, | 345 | .unlocked_ioctl = nfs4_ioctl, |
352 | #else | ||
353 | .compat_ioctl = nfs4_ioctl, | 346 | .compat_ioctl = nfs4_ioctl, |
354 | #endif /* CONFIG_COMPAT */ | 347 | #else |
348 | .llseek = nfs_file_llseek, | ||
349 | #endif | ||
355 | }; | 350 | }; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 765a03559363..89818036f035 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -7866,7 +7866,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
7866 | spin_unlock(&inode->i_lock); | 7866 | spin_unlock(&inode->i_lock); |
7867 | goto out_restart; | 7867 | goto out_restart; |
7868 | } | 7868 | } |
7869 | if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) | 7869 | if (nfs4_async_handle_error(task, server, state, &lgp->timeout) == -EAGAIN) |
7870 | goto out_restart; | 7870 | goto out_restart; |
7871 | out: | 7871 | out: |
7872 | dprintk("<-- %s\n", __func__); | 7872 | dprintk("<-- %s\n", __func__); |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index dfed4f5c8fcc..4e4441216804 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -3615,6 +3615,7 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
3615 | status = 0; | 3615 | status = 0; |
3616 | if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) | 3616 | if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) |
3617 | goto out; | 3617 | goto out; |
3618 | bitmap[0] &= ~FATTR4_WORD0_FS_LOCATIONS; | ||
3618 | status = -EIO; | 3619 | status = -EIO; |
3619 | /* Ignore borken servers that return unrequested attrs */ | 3620 | /* Ignore borken servers that return unrequested attrs */ |
3620 | if (unlikely(res == NULL)) | 3621 | if (unlikely(res == NULL)) |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 93496c059837..5a8ae2125b50 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -872,33 +872,38 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
872 | 872 | ||
873 | dprintk("--> %s\n", __func__); | 873 | dprintk("--> %s\n", __func__); |
874 | 874 | ||
875 | lgp = kzalloc(sizeof(*lgp), gfp_flags); | 875 | /* |
876 | if (lgp == NULL) | 876 | * Synchronously retrieve layout information from server and |
877 | return NULL; | 877 | * store in lseg. If we race with a concurrent seqid morphing |
878 | * op, then re-send the LAYOUTGET. | ||
879 | */ | ||
880 | do { | ||
881 | lgp = kzalloc(sizeof(*lgp), gfp_flags); | ||
882 | if (lgp == NULL) | ||
883 | return NULL; | ||
884 | |||
885 | i_size = i_size_read(ino); | ||
886 | |||
887 | lgp->args.minlength = PAGE_CACHE_SIZE; | ||
888 | if (lgp->args.minlength > range->length) | ||
889 | lgp->args.minlength = range->length; | ||
890 | if (range->iomode == IOMODE_READ) { | ||
891 | if (range->offset >= i_size) | ||
892 | lgp->args.minlength = 0; | ||
893 | else if (i_size - range->offset < lgp->args.minlength) | ||
894 | lgp->args.minlength = i_size - range->offset; | ||
895 | } | ||
896 | lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; | ||
897 | lgp->args.range = *range; | ||
898 | lgp->args.type = server->pnfs_curr_ld->id; | ||
899 | lgp->args.inode = ino; | ||
900 | lgp->args.ctx = get_nfs_open_context(ctx); | ||
901 | lgp->gfp_flags = gfp_flags; | ||
902 | lgp->cred = lo->plh_lc_cred; | ||
878 | 903 | ||
879 | i_size = i_size_read(ino); | 904 | lseg = nfs4_proc_layoutget(lgp, gfp_flags); |
905 | } while (lseg == ERR_PTR(-EAGAIN)); | ||
880 | 906 | ||
881 | lgp->args.minlength = PAGE_CACHE_SIZE; | ||
882 | if (lgp->args.minlength > range->length) | ||
883 | lgp->args.minlength = range->length; | ||
884 | if (range->iomode == IOMODE_READ) { | ||
885 | if (range->offset >= i_size) | ||
886 | lgp->args.minlength = 0; | ||
887 | else if (i_size - range->offset < lgp->args.minlength) | ||
888 | lgp->args.minlength = i_size - range->offset; | ||
889 | } | ||
890 | lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; | ||
891 | lgp->args.range = *range; | ||
892 | lgp->args.type = server->pnfs_curr_ld->id; | ||
893 | lgp->args.inode = ino; | ||
894 | lgp->args.ctx = get_nfs_open_context(ctx); | ||
895 | lgp->gfp_flags = gfp_flags; | ||
896 | lgp->cred = lo->plh_lc_cred; | ||
897 | |||
898 | /* Synchronously retrieve layout information from server and | ||
899 | * store in lseg. | ||
900 | */ | ||
901 | lseg = nfs4_proc_layoutget(lgp, gfp_flags); | ||
902 | if (IS_ERR(lseg)) { | 907 | if (IS_ERR(lseg)) { |
903 | switch (PTR_ERR(lseg)) { | 908 | switch (PTR_ERR(lseg)) { |
904 | case -ENOMEM: | 909 | case -ENOMEM: |
@@ -1687,6 +1692,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
1687 | /* existing state ID, make sure the sequence number matches. */ | 1692 | /* existing state ID, make sure the sequence number matches. */ |
1688 | if (pnfs_layout_stateid_blocked(lo, &res->stateid)) { | 1693 | if (pnfs_layout_stateid_blocked(lo, &res->stateid)) { |
1689 | dprintk("%s forget reply due to sequence\n", __func__); | 1694 | dprintk("%s forget reply due to sequence\n", __func__); |
1695 | status = -EAGAIN; | ||
1690 | goto out_forget_reply; | 1696 | goto out_forget_reply; |
1691 | } | 1697 | } |
1692 | pnfs_set_layout_stateid(lo, &res->stateid, false); | 1698 | pnfs_set_layout_stateid(lo, &res->stateid, false); |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 570d630f98ae..11bbae44f4cb 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -251,6 +251,7 @@ struct nfs4_layoutget { | |||
251 | struct nfs4_layoutget_res res; | 251 | struct nfs4_layoutget_res res; |
252 | struct rpc_cred *cred; | 252 | struct rpc_cred *cred; |
253 | gfp_t gfp_flags; | 253 | gfp_t gfp_flags; |
254 | long timeout; | ||
254 | }; | 255 | }; |
255 | 256 | ||
256 | struct nfs4_getdeviceinfo_args { | 257 | struct nfs4_getdeviceinfo_args { |
diff --git a/include/uapi/linux/nfs.h b/include/uapi/linux/nfs.h index 654bae3f1a38..5e6296160361 100644 --- a/include/uapi/linux/nfs.h +++ b/include/uapi/linux/nfs.h | |||
@@ -33,17 +33,6 @@ | |||
33 | 33 | ||
34 | #define NFS_PIPE_DIRNAME "nfs" | 34 | #define NFS_PIPE_DIRNAME "nfs" |
35 | 35 | ||
36 | /* NFS ioctls */ | ||
37 | /* Let's follow btrfs lead on CLONE to avoid messing userspace */ | ||
38 | #define NFS_IOC_CLONE _IOW(0x94, 9, int) | ||
39 | #define NFS_IOC_CLONE_RANGE _IOW(0x94, 13, int) | ||
40 | |||
41 | struct nfs_ioctl_clone_range_args { | ||
42 | __s64 src_fd; | ||
43 | __u64 src_off, count; | ||
44 | __u64 dst_off; | ||
45 | }; | ||
46 | |||
47 | /* | 36 | /* |
48 | * NFS stats. The good thing with these values is that NFSv3 errors are | 37 | * NFS stats. The good thing with these values is that NFSv3 errors are |
49 | * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which | 38 | * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 229956bf8457..95f82d8d4888 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
@@ -353,12 +353,20 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) | |||
353 | { | 353 | { |
354 | struct rpc_xprt *xprt = req->rq_xprt; | 354 | struct rpc_xprt *xprt = req->rq_xprt; |
355 | struct svc_serv *bc_serv = xprt->bc_serv; | 355 | struct svc_serv *bc_serv = xprt->bc_serv; |
356 | struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf; | ||
356 | 357 | ||
357 | spin_lock(&xprt->bc_pa_lock); | 358 | spin_lock(&xprt->bc_pa_lock); |
358 | list_del(&req->rq_bc_pa_list); | 359 | list_del(&req->rq_bc_pa_list); |
359 | xprt_dec_alloc_count(xprt, 1); | 360 | xprt_dec_alloc_count(xprt, 1); |
360 | spin_unlock(&xprt->bc_pa_lock); | 361 | spin_unlock(&xprt->bc_pa_lock); |
361 | 362 | ||
363 | if (copied <= rq_rcv_buf->head[0].iov_len) { | ||
364 | rq_rcv_buf->head[0].iov_len = copied; | ||
365 | rq_rcv_buf->page_len = 0; | ||
366 | } else { | ||
367 | rq_rcv_buf->page_len = copied - rq_rcv_buf->head[0].iov_len; | ||
368 | } | ||
369 | |||
362 | req->rq_private_buf.len = copied; | 370 | req->rq_private_buf.len = copied; |
363 | set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | 371 | set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); |
364 | 372 | ||
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index bc5b7b5032ca..7fccf9675df8 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -1363,6 +1363,7 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, | |||
1363 | memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); | 1363 | memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); |
1364 | memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); | 1364 | memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); |
1365 | memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); | 1365 | memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); |
1366 | rqstp->rq_arg.len = req->rq_private_buf.len; | ||
1366 | 1367 | ||
1367 | /* reset result send buffer "put" position */ | 1368 | /* reset result send buffer "put" position */ |
1368 | resv->iov_len = 0; | 1369 | resv->iov_len = 0; |