Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+88 -76
+5 -2
fs/nfs/callback_xdr.c
··· 78 78 79 79 p = xdr_inline_decode(xdr, nbytes); 80 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 83 return p; 83 84 } 84 85 ··· 890 889 struct cb_compound_hdr_arg hdr_arg = { 0 }; 891 890 struct cb_compound_hdr_res hdr_res = { NULL }; 892 891 struct xdr_stream xdr_in, xdr_out; 892 + struct xdr_buf *rq_arg = &rqstp->rq_arg; 893 893 __be32 *p, status; 894 894 struct cb_process_state cps = { 895 895 .drc_status = 0, ··· 902 900 903 901 dprintk("%s: start\n", __func__); 904 902 905 - xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base); 903 + rq_arg->len = rq_arg->head[0].iov_len + rq_arg->page_len; 904 + xdr_init_decode(&xdr_in, rq_arg, rq_arg->head[0].iov_base); 906 905 907 906 p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len); 908 907 xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
+9 -2
fs/nfs/inode.c
··· 618 618 nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); 619 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 625 spin_unlock(&inode->i_lock); 623 626 } 624 627 EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); ··· 1827 1824 if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0) 1828 1825 nfsi->attr_gencount = fattr->gencount; 1829 1826 } 1830 - invalid &= ~NFS_INO_INVALID_ATTR; 1827 + 1828 + /* Don't declare attrcache up to date if there were no attrs! */ 1829 + if (fattr->valid != 0) 1830 + invalid &= ~NFS_INO_INVALID_ATTR; 1831 + 1831 1832 /* Don't invalidate the data if we were to blame */ 1832 1833 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) 1833 1834 || S_ISLNK(inode->i_mode)))
+2 -1
fs/nfs/nfs42proc.c
··· 14 14 #include "pnfs.h" 15 15 #include "internal.h" 16 16 17 - #define NFSDBG_FACILITY NFSDBG_PNFS 17 + #define NFSDBG_FACILITY NFSDBG_PROC 18 18 19 19 static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file, 20 20 fmode_t fmode) ··· 284 284 .dst_fh = NFS_FH(dst_inode), 285 285 .src_offset = src_offset, 286 286 .dst_offset = dst_offset, 287 + .count = count, 287 288 .dst_bitmask = server->cache_consistency_bitmask, 288 289 }; 289 290 struct nfs42_clone_res res = {
+1 -1
fs/nfs/nfs4client.c
··· 33 33 return ret; 34 34 idr_preload(GFP_KERNEL); 35 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 37 if (ret >= 0) 38 38 clp->cl_cb_ident = ret; 39 39 spin_unlock(&nn->nfs_client_lock);
+27 -32
fs/nfs/nfs4file.c
··· 7 7 #include <linux/file.h> 8 8 #include <linux/falloc.h> 9 9 #include <linux/nfs_fs.h> 10 + #include <uapi/linux/btrfs.h> /* BTRFS_IOC_CLONE/BTRFS_IOC_CLONE_RANGE */ 10 11 #include "delegation.h" 11 12 #include "internal.h" 12 13 #include "iostat.h" ··· 204 203 struct fd src_file; 205 204 struct inode *src_inode; 206 205 unsigned int bs = server->clone_blksize; 206 + bool same_inode = false; 207 207 int ret; 208 208 209 209 /* dst file must be opened for writing */ ··· 223 221 224 222 src_inode = file_inode(src_file.file); 225 223 226 - /* src and dst must be different files */ 227 - ret = -EINVAL; 228 224 if (src_inode == dst_inode) 229 - goto out_fput; 225 + same_inode = true; 230 226 231 227 /* src file must be opened for reading */ 232 228 if (!(src_file.file->f_mode & FMODE_READ)) ··· 249 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 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 262 mutex_lock_nested(&dst_inode->i_mutex, I_MUTEX_PARENT); 255 263 mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_CHILD); 256 264 } else { ··· 283 275 truncate_inode_pages_range(&dst_inode->i_data, dst_off, dst_off + count - 1); 284 276 285 277 out_unlock: 286 - if (dst_inode < src_inode) { 278 + if (same_inode) { 279 + mutex_unlock(&src_inode->i_mutex); 280 + } else if (dst_inode < src_inode) { 287 281 mutex_unlock(&src_inode->i_mutex); 288 282 mutex_unlock(&dst_inode->i_mutex); 289 283 } else { ··· 301 291 302 292 static long nfs42_ioctl_clone_range(struct file *dst_file, void __user *argp) 303 293 { 304 - struct nfs_ioctl_clone_range_args args; 294 + struct btrfs_ioctl_clone_range_args args; 305 295 306 296 if (copy_from_user(&args, argp, sizeof(args))) 307 297 return -EFAULT; 308 298 309 - return nfs42_ioctl_clone(dst_file, args.src_fd, args.src_off, args.dst_off, args.count); 299 + return nfs42_ioctl_clone(dst_file, args.src_fd, args.src_offset, 300 + args.dest_offset, args.src_length); 310 301 } 311 - #else 312 - static long nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd, 313 - u64 src_off, u64 dst_off, u64 count) 314 - { 315 - return -ENOTTY; 316 - } 317 - 318 - static long nfs42_ioctl_clone_range(struct file *dst_file, void __user *argp) 319 - { 320 - return -ENOTTY; 321 - } 322 - #endif /* CONFIG_NFS_V4_2 */ 323 302 324 303 long nfs4_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 325 304 { 326 305 void __user *argp = (void __user *)arg; 327 306 328 307 switch (cmd) { 329 - case NFS_IOC_CLONE: 308 + case BTRFS_IOC_CLONE: 330 309 return nfs42_ioctl_clone(file, arg, 0, 0, 0); 331 - case NFS_IOC_CLONE_RANGE: 310 + case BTRFS_IOC_CLONE_RANGE: 332 311 return nfs42_ioctl_clone_range(file, argp); 333 312 } 334 313 335 314 return -ENOTTY; 336 315 } 316 + #endif /* CONFIG_NFS_V4_2 */ 337 317 338 318 const struct file_operations nfs4_file_operations = { 339 - #ifdef CONFIG_NFS_V4_2 340 - .llseek = nfs4_file_llseek, 341 - #else 342 - .llseek = nfs_file_llseek, 343 - #endif 344 319 .read_iter = nfs_file_read, 345 320 .write_iter = nfs_file_write, 346 321 .mmap = nfs_file_mmap, ··· 337 342 .flock = nfs_flock, 338 343 .splice_read = nfs_file_splice_read, 339 344 .splice_write = iter_file_splice_write, 340 - #ifdef CONFIG_NFS_V4_2 341 - .fallocate = nfs42_fallocate, 342 - #endif /* CONFIG_NFS_V4_2 */ 343 345 .check_flags = nfs_check_flags, 344 346 .setlease = simple_nosetlease, 345 - #ifdef CONFIG_COMPAT 347 + #ifdef CONFIG_NFS_V4_2 348 + .llseek = nfs4_file_llseek, 349 + .fallocate = nfs42_fallocate, 346 350 .unlocked_ioctl = nfs4_ioctl, 347 - #else 348 351 .compat_ioctl = nfs4_ioctl, 349 - #endif /* CONFIG_COMPAT */ 352 + #else 353 + .llseek = nfs_file_llseek, 354 + #endif 350 355 };
+1 -1
fs/nfs/nfs4proc.c
··· 7866 7866 spin_unlock(&inode->i_lock); 7867 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 7870 goto out_restart; 7871 7871 out: 7872 7872 dprintk("<-- %s\n", __func__);
+1
fs/nfs/nfs4xdr.c
··· 3615 3615 status = 0; 3616 3616 if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) 3617 3617 goto out; 3618 + bitmap[0] &= ~FATTR4_WORD0_FS_LOCATIONS; 3618 3619 status = -EIO; 3619 3620 /* Ignore borken servers that return unrequested attrs */ 3620 3621 if (unlikely(res == NULL))
+32 -26
fs/nfs/pnfs.c
··· 872 872 873 873 dprintk("--> %s\n", __func__); 874 874 875 - lgp = kzalloc(sizeof(*lgp), gfp_flags); 876 - if (lgp == NULL) 877 - return NULL; 878 - 879 - i_size = i_size_read(ino); 880 - 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. 875 + /* 876 + * Synchronously retrieve layout information from server and 877 + * store in lseg. If we race with a concurrent seqid morphing 878 + * op, then re-send the LAYOUTGET. 900 879 */ 901 - lseg = nfs4_proc_layoutget(lgp, gfp_flags); 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; 903 + 904 + lseg = nfs4_proc_layoutget(lgp, gfp_flags); 905 + } while (lseg == ERR_PTR(-EAGAIN)); 906 + 902 907 if (IS_ERR(lseg)) { 903 908 switch (PTR_ERR(lseg)) { 904 909 case -ENOMEM: ··· 1692 1687 /* existing state ID, make sure the sequence number matches. */ 1693 1688 if (pnfs_layout_stateid_blocked(lo, &res->stateid)) { 1694 1689 dprintk("%s forget reply due to sequence\n", __func__); 1690 + status = -EAGAIN; 1695 1691 goto out_forget_reply; 1696 1692 } 1697 1693 pnfs_set_layout_stateid(lo, &res->stateid, false);
+1
include/linux/nfs_xdr.h
··· 251 251 struct nfs4_layoutget_res res; 252 252 struct rpc_cred *cred; 253 253 gfp_t gfp_flags; 254 + long timeout; 254 255 }; 255 256 256 257 struct nfs4_getdeviceinfo_args {
-11
include/uapi/linux/nfs.h
··· 33 33 34 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 37 * NFS stats. The good thing with these values is that NFSv3 errors are 49 38 * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which
+8
net/sunrpc/backchannel_rqst.c
··· 353 353 { 354 354 struct rpc_xprt *xprt = req->rq_xprt; 355 355 struct svc_serv *bc_serv = xprt->bc_serv; 356 + struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf; 356 357 357 358 spin_lock(&xprt->bc_pa_lock); 358 359 list_del(&req->rq_bc_pa_list); 359 360 xprt_dec_alloc_count(xprt, 1); 360 361 spin_unlock(&xprt->bc_pa_lock); 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 + } 361 369 362 370 req->rq_private_buf.len = copied; 363 371 set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
+1
net/sunrpc/svc.c
··· 1363 1363 memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); 1364 1364 memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); 1365 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 1368 /* reset result send buffer "put" position */ 1368 1369 resv->iov_len = 0;