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

Merge tag 'nfs-for-4.11-3' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client fixes from Anna Schumaker:
"Here are a few more bugfixes that came in over the last couple of
weeks. Most of these fix various hangs and loops that people found,
but we also had a few error handling fixes.

Stable Bugfixes:
- fix infinite loop on BAD_STATEID error

Other Bugfixes:
- fix old dentry rehash after move
- fix pnfs GETDEVINFO hangs
- fix pnfs fallback to MDS on commit errors
- fix flexfiles kernel oops"

* tag 'nfs-for-4.11-3' of git://git.linux-nfs.org/projects/anna/linux-nfs:
nfs: flexfiles: fix kernel OOPS if MDS returns unsupported DS type
NFSv4.1 fix infinite loop on IO BAD_STATEID error
PNFS fix fallback to MDS if got error on commit to DS
NFS filelayout:call GETDEVICEINFO after pnfs_layout_process completes
NFS store nfs4_deviceid in struct nfs4_filelayout_segment
NFS cleanup struct nfs4_filelayout_segment
NFS: Fix old dentry rehash after move

+120 -82
+2 -7
fs/nfs/dir.c
··· 2055 2055 { 2056 2056 struct inode *old_inode = d_inode(old_dentry); 2057 2057 struct inode *new_inode = d_inode(new_dentry); 2058 - struct dentry *dentry = NULL, *rehash = NULL; 2058 + struct dentry *dentry = NULL; 2059 2059 struct rpc_task *task; 2060 2060 int error = -EBUSY; 2061 2061 ··· 2078 2078 * To prevent any new references to the target during the 2079 2079 * rename, we unhash the dentry in advance. 2080 2080 */ 2081 - if (!d_unhashed(new_dentry)) { 2081 + if (!d_unhashed(new_dentry)) 2082 2082 d_drop(new_dentry); 2083 - rehash = new_dentry; 2084 - } 2085 2083 2086 2084 if (d_count(new_dentry) > 2) { 2087 2085 int err; ··· 2096 2098 goto out; 2097 2099 2098 2100 new_dentry = dentry; 2099 - rehash = NULL; 2100 2101 new_inode = NULL; 2101 2102 } 2102 2103 } ··· 2116 2119 error = task->tk_status; 2117 2120 rpc_put_task(task); 2118 2121 out: 2119 - if (rehash) 2120 - d_rehash(rehash); 2121 2122 trace_nfs_rename_exit(old_dir, old_dentry, 2122 2123 new_dir, new_dentry, error); 2123 2124 /* new dentry created? */
+101 -60
fs/nfs/filelayout/filelayout.c
··· 202 202 task->tk_status); 203 203 nfs4_mark_deviceid_unavailable(devid); 204 204 pnfs_error_mark_layout_for_return(inode, lseg); 205 - pnfs_set_lo_fail(lseg); 206 205 rpc_wake_up(&tbl->slot_tbl_waitq); 207 206 /* fall through */ 208 207 default: 208 + pnfs_set_lo_fail(lseg); 209 209 reset: 210 210 dprintk("%s Retry through MDS. Error %d\n", __func__, 211 211 task->tk_status); ··· 560 560 return PNFS_ATTEMPTED; 561 561 } 562 562 563 - /* 564 - * filelayout_check_layout() 565 - * 566 - * Make sure layout segment parameters are sane WRT the device. 567 - * At this point no generic layer initialization of the lseg has occurred, 568 - * and nothing has been added to the layout_hdr cache. 569 - * 570 - */ 571 563 static int 572 - filelayout_check_layout(struct pnfs_layout_hdr *lo, 573 - struct nfs4_filelayout_segment *fl, 574 - struct nfs4_layoutget_res *lgr, 575 - struct nfs4_deviceid *id, 576 - gfp_t gfp_flags) 564 + filelayout_check_deviceid(struct pnfs_layout_hdr *lo, 565 + struct nfs4_filelayout_segment *fl, 566 + gfp_t gfp_flags) 577 567 { 578 568 struct nfs4_deviceid_node *d; 579 569 struct nfs4_file_layout_dsaddr *dsaddr; 580 570 int status = -EINVAL; 581 571 582 - dprintk("--> %s\n", __func__); 583 - 584 - /* FIXME: remove this check when layout segment support is added */ 585 - if (lgr->range.offset != 0 || 586 - lgr->range.length != NFS4_MAX_UINT64) { 587 - dprintk("%s Only whole file layouts supported. Use MDS i/o\n", 588 - __func__); 589 - goto out; 590 - } 591 - 592 - if (fl->pattern_offset > lgr->range.offset) { 593 - dprintk("%s pattern_offset %lld too large\n", 594 - __func__, fl->pattern_offset); 595 - goto out; 596 - } 597 - 598 - if (!fl->stripe_unit) { 599 - dprintk("%s Invalid stripe unit (%u)\n", 600 - __func__, fl->stripe_unit); 601 - goto out; 602 - } 603 - 604 572 /* find and reference the deviceid */ 605 - d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), id, 573 + d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid, 606 574 lo->plh_lc_cred, gfp_flags); 607 575 if (d == NULL) 608 576 goto out; ··· 596 628 __func__, fl->num_fh); 597 629 goto out_put; 598 630 } 631 + status = 0; 632 + out: 633 + return status; 634 + out_put: 635 + nfs4_fl_put_deviceid(dsaddr); 636 + goto out; 637 + } 638 + 639 + /* 640 + * filelayout_check_layout() 641 + * 642 + * Make sure layout segment parameters are sane WRT the device. 643 + * At this point no generic layer initialization of the lseg has occurred, 644 + * and nothing has been added to the layout_hdr cache. 645 + * 646 + */ 647 + static int 648 + filelayout_check_layout(struct pnfs_layout_hdr *lo, 649 + struct nfs4_filelayout_segment *fl, 650 + struct nfs4_layoutget_res *lgr, 651 + gfp_t gfp_flags) 652 + { 653 + int status = -EINVAL; 654 + 655 + dprintk("--> %s\n", __func__); 656 + 657 + /* FIXME: remove this check when layout segment support is added */ 658 + if (lgr->range.offset != 0 || 659 + lgr->range.length != NFS4_MAX_UINT64) { 660 + dprintk("%s Only whole file layouts supported. Use MDS i/o\n", 661 + __func__); 662 + goto out; 663 + } 664 + 665 + if (fl->pattern_offset > lgr->range.offset) { 666 + dprintk("%s pattern_offset %lld too large\n", 667 + __func__, fl->pattern_offset); 668 + goto out; 669 + } 670 + 671 + if (!fl->stripe_unit) { 672 + dprintk("%s Invalid stripe unit (%u)\n", 673 + __func__, fl->stripe_unit); 674 + goto out; 675 + } 599 676 600 677 status = 0; 601 678 out: 602 679 dprintk("--> %s returns %d\n", __func__, status); 603 680 return status; 604 - out_put: 605 - nfs4_fl_put_deviceid(dsaddr); 606 - goto out; 607 681 } 608 682 609 683 static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl) ··· 667 657 filelayout_decode_layout(struct pnfs_layout_hdr *flo, 668 658 struct nfs4_filelayout_segment *fl, 669 659 struct nfs4_layoutget_res *lgr, 670 - struct nfs4_deviceid *id, 671 660 gfp_t gfp_flags) 672 661 { 673 662 struct xdr_stream stream; ··· 691 682 if (unlikely(!p)) 692 683 goto out_err; 693 684 694 - memcpy(id, p, sizeof(*id)); 685 + memcpy(&fl->deviceid, p, sizeof(fl->deviceid)); 695 686 p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); 696 - nfs4_print_deviceid(id); 687 + nfs4_print_deviceid(&fl->deviceid); 697 688 698 689 nfl_util = be32_to_cpup(p++); 699 690 if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS) ··· 840 831 { 841 832 struct nfs4_filelayout_segment *fl; 842 833 int rc; 843 - struct nfs4_deviceid id; 844 834 845 835 dprintk("--> %s\n", __func__); 846 836 fl = kzalloc(sizeof(*fl), gfp_flags); 847 837 if (!fl) 848 838 return NULL; 849 839 850 - rc = filelayout_decode_layout(layoutid, fl, lgr, &id, gfp_flags); 851 - if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id, gfp_flags)) { 840 + rc = filelayout_decode_layout(layoutid, fl, lgr, gfp_flags); 841 + if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, gfp_flags)) { 852 842 _filelayout_free_lseg(fl); 853 843 return NULL; 854 844 } ··· 896 888 return min(stripe_unit - (unsigned int)stripe_offset, size); 897 889 } 898 890 891 + static struct pnfs_layout_segment * 892 + fl_pnfs_update_layout(struct inode *ino, 893 + struct nfs_open_context *ctx, 894 + loff_t pos, 895 + u64 count, 896 + enum pnfs_iomode iomode, 897 + bool strict_iomode, 898 + gfp_t gfp_flags) 899 + { 900 + struct pnfs_layout_segment *lseg = NULL; 901 + struct pnfs_layout_hdr *lo; 902 + struct nfs4_filelayout_segment *fl; 903 + int status; 904 + 905 + lseg = pnfs_update_layout(ino, ctx, pos, count, iomode, strict_iomode, 906 + gfp_flags); 907 + if (!lseg) 908 + lseg = ERR_PTR(-ENOMEM); 909 + if (IS_ERR(lseg)) 910 + goto out; 911 + 912 + lo = NFS_I(ino)->layout; 913 + fl = FILELAYOUT_LSEG(lseg); 914 + 915 + status = filelayout_check_deviceid(lo, fl, gfp_flags); 916 + if (status) 917 + lseg = ERR_PTR(status); 918 + out: 919 + if (IS_ERR(lseg)) 920 + pnfs_put_lseg(lseg); 921 + return lseg; 922 + } 923 + 899 924 static void 900 925 filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, 901 926 struct nfs_page *req) 902 927 { 903 928 if (!pgio->pg_lseg) { 904 - pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, 905 - req->wb_context, 906 - 0, 907 - NFS4_MAX_UINT64, 908 - IOMODE_READ, 909 - false, 910 - GFP_KERNEL); 929 + pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, 930 + req->wb_context, 931 + 0, 932 + NFS4_MAX_UINT64, 933 + IOMODE_READ, 934 + false, 935 + GFP_KERNEL); 911 936 if (IS_ERR(pgio->pg_lseg)) { 912 937 pgio->pg_error = PTR_ERR(pgio->pg_lseg); 913 938 pgio->pg_lseg = NULL; ··· 960 919 int status; 961 920 962 921 if (!pgio->pg_lseg) { 963 - pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, 964 - req->wb_context, 965 - 0, 966 - NFS4_MAX_UINT64, 967 - IOMODE_RW, 968 - false, 969 - GFP_NOFS); 922 + pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, 923 + req->wb_context, 924 + 0, 925 + NFS4_MAX_UINT64, 926 + IOMODE_RW, 927 + false, 928 + GFP_NOFS); 970 929 if (IS_ERR(pgio->pg_lseg)) { 971 930 pgio->pg_error = PTR_ERR(pgio->pg_lseg); 972 931 pgio->pg_lseg = NULL;
+10 -9
fs/nfs/filelayout/filelayout.h
··· 55 55 }; 56 56 57 57 struct nfs4_filelayout_segment { 58 - struct pnfs_layout_segment generic_hdr; 59 - u32 stripe_type; 60 - u32 commit_through_mds; 61 - u32 stripe_unit; 62 - u32 first_stripe_index; 63 - u64 pattern_offset; 64 - struct nfs4_file_layout_dsaddr *dsaddr; /* Point to GETDEVINFO data */ 65 - unsigned int num_fh; 66 - struct nfs_fh **fh_array; 58 + struct pnfs_layout_segment generic_hdr; 59 + u32 stripe_type; 60 + u32 commit_through_mds; 61 + u32 stripe_unit; 62 + u32 first_stripe_index; 63 + u64 pattern_offset; 64 + struct nfs4_deviceid deviceid; 65 + struct nfs4_file_layout_dsaddr *dsaddr; /* Point to GETDEVINFO data */ 66 + unsigned int num_fh; 67 + struct nfs_fh **fh_array; 67 68 }; 68 69 69 70 struct nfs4_filelayout {
+4
fs/nfs/flexfilelayout/flexfilelayoutdev.c
··· 208 208 } else 209 209 goto outerr; 210 210 } 211 + 212 + if (IS_ERR(mirror->mirror_ds)) 213 + goto outerr; 214 + 211 215 if (mirror->mirror_ds->ds == NULL) { 212 216 struct nfs4_deviceid_node *devid; 213 217 devid = &mirror->mirror_ds->id_node;
+3 -6
fs/nfs/nfs4proc.c
··· 2442 2442 } 2443 2443 2444 2444 nfs4_stateid_copy(&stateid, &delegation->stateid); 2445 - if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) { 2445 + if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) || 2446 + !test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED, 2447 + &delegation->flags)) { 2446 2448 rcu_read_unlock(); 2447 2449 nfs_finish_clear_delegation_stateid(state, &stateid); 2448 - return; 2449 - } 2450 - 2451 - if (!test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags)) { 2452 - rcu_read_unlock(); 2453 2450 return; 2454 2451 } 2455 2452