diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-12 17:13:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-12 17:13:45 -0400 |
commit | 2c937eb4ddca946bb74936cf63aba0f94aa0efb3 (patch) | |
tree | f1038c15e15871e77365b96ea3e7497a352629f2 /fs | |
parent | da499f8f5385c181e29978fdaab15a58de185302 (diff) | |
parent | b519d408ea32040b1c7e10b155a3ee9a36660947 (diff) |
Merge tag 'nfs-for-4.8-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust:
"Highlights include:
Stable patches:
- We must serialise LAYOUTGET and LAYOUTRETURN to ensure correct
state accounting
- Fix the CREATE_SESSION slot number
Bugfixes:
- sunrpc: fix a UDP memory accounting regression
- NFS: Fix an error reporting regression in nfs_file_write()
- pNFS: Fix further layout stateid issues
- RPC/rdma: Revert 3d4cf35bd4fa ("xprtrdma: Reply buffer
exhaustion...")
- RPC/rdma: Fix receive buffer accounting"
* tag 'nfs-for-4.8-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
NFSv4.1: Fix the CREATE_SESSION slot number accounting
xprtrdma: Fix receive buffer accounting
xprtrdma: Revert 3d4cf35bd4fa ("xprtrdma: Reply buffer exhaustion...")
pNFS: Don't forget the layout stateid if there are outstanding LAYOUTGETs
pNFS: Clear out all layout segments if the server unsets lrp->res.lrs_present
pNFS: Fix pnfs_set_layout_stateid() to clear NFS_LAYOUT_INVALID_STID
pNFS: Ensure LAYOUTGET and LAYOUTRETURN are properly serialised
NFS: Fix error reporting in nfs_file_write()
sunrpc: fix UDP memory accounting
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/file.c | 5 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 21 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 42 |
3 files changed, 44 insertions, 24 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 7d620970f2e1..ca699ddc11c1 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -657,7 +657,10 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) | |||
657 | if (result <= 0) | 657 | if (result <= 0) |
658 | goto out; | 658 | goto out; |
659 | 659 | ||
660 | written = generic_write_sync(iocb, result); | 660 | result = generic_write_sync(iocb, result); |
661 | if (result < 0) | ||
662 | goto out; | ||
663 | written = result; | ||
661 | iocb->ki_pos += written; | 664 | iocb->ki_pos += written; |
662 | 665 | ||
663 | /* Return error values */ | 666 | /* Return error values */ |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f5aecaabcb7c..a9dec32ba9ba 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -7570,12 +7570,20 @@ static int _nfs4_proc_create_session(struct nfs_client *clp, | |||
7570 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 7570 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
7571 | trace_nfs4_create_session(clp, status); | 7571 | trace_nfs4_create_session(clp, status); |
7572 | 7572 | ||
7573 | switch (status) { | ||
7574 | case -NFS4ERR_STALE_CLIENTID: | ||
7575 | case -NFS4ERR_DELAY: | ||
7576 | case -ETIMEDOUT: | ||
7577 | case -EACCES: | ||
7578 | case -EAGAIN: | ||
7579 | goto out; | ||
7580 | }; | ||
7581 | |||
7582 | clp->cl_seqid++; | ||
7573 | if (!status) { | 7583 | if (!status) { |
7574 | /* Verify the session's negotiated channel_attrs values */ | 7584 | /* Verify the session's negotiated channel_attrs values */ |
7575 | status = nfs4_verify_channel_attrs(&args, &res); | 7585 | status = nfs4_verify_channel_attrs(&args, &res); |
7576 | /* Increment the clientid slot sequence id */ | 7586 | /* Increment the clientid slot sequence id */ |
7577 | if (clp->cl_seqid == res.seqid) | ||
7578 | clp->cl_seqid++; | ||
7579 | if (status) | 7587 | if (status) |
7580 | goto out; | 7588 | goto out; |
7581 | nfs4_update_session(session, &res); | 7589 | nfs4_update_session(session, &res); |
@@ -8190,10 +8198,13 @@ static void nfs4_layoutreturn_release(void *calldata) | |||
8190 | 8198 | ||
8191 | dprintk("--> %s\n", __func__); | 8199 | dprintk("--> %s\n", __func__); |
8192 | spin_lock(&lo->plh_inode->i_lock); | 8200 | spin_lock(&lo->plh_inode->i_lock); |
8193 | pnfs_mark_matching_lsegs_invalid(lo, &freeme, &lrp->args.range, | 8201 | if (lrp->res.lrs_present) { |
8194 | be32_to_cpu(lrp->args.stateid.seqid)); | 8202 | pnfs_mark_matching_lsegs_invalid(lo, &freeme, |
8195 | if (lrp->res.lrs_present && pnfs_layout_is_valid(lo)) | 8203 | &lrp->args.range, |
8204 | be32_to_cpu(lrp->args.stateid.seqid)); | ||
8196 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); | 8205 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); |
8206 | } else | ||
8207 | pnfs_mark_layout_stateid_invalid(lo, &freeme); | ||
8197 | pnfs_clear_layoutreturn_waitbit(lo); | 8208 | pnfs_clear_layoutreturn_waitbit(lo); |
8198 | spin_unlock(&lo->plh_inode->i_lock); | 8209 | spin_unlock(&lo->plh_inode->i_lock); |
8199 | nfs4_sequence_free_slot(&lrp->res.seq_res); | 8210 | nfs4_sequence_free_slot(&lrp->res.seq_res); |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 6daf034645c8..2c93a85eda51 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -365,7 +365,8 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo, | |||
365 | /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */ | 365 | /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */ |
366 | atomic_dec(&lo->plh_refcount); | 366 | atomic_dec(&lo->plh_refcount); |
367 | if (list_empty(&lo->plh_segs)) { | 367 | if (list_empty(&lo->plh_segs)) { |
368 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | 368 | if (atomic_read(&lo->plh_outstanding) == 0) |
369 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | ||
369 | clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); | 370 | clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); |
370 | } | 371 | } |
371 | rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); | 372 | rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); |
@@ -768,17 +769,32 @@ pnfs_destroy_all_layouts(struct nfs_client *clp) | |||
768 | pnfs_destroy_layouts_byclid(clp, false); | 769 | pnfs_destroy_layouts_byclid(clp, false); |
769 | } | 770 | } |
770 | 771 | ||
772 | static void | ||
773 | pnfs_clear_layoutreturn_info(struct pnfs_layout_hdr *lo) | ||
774 | { | ||
775 | lo->plh_return_iomode = 0; | ||
776 | lo->plh_return_seq = 0; | ||
777 | clear_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags); | ||
778 | } | ||
779 | |||
771 | /* update lo->plh_stateid with new if is more recent */ | 780 | /* update lo->plh_stateid with new if is more recent */ |
772 | void | 781 | void |
773 | pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, | 782 | pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, |
774 | bool update_barrier) | 783 | bool update_barrier) |
775 | { | 784 | { |
776 | u32 oldseq, newseq, new_barrier = 0; | 785 | u32 oldseq, newseq, new_barrier = 0; |
777 | bool invalid = !pnfs_layout_is_valid(lo); | ||
778 | 786 | ||
779 | oldseq = be32_to_cpu(lo->plh_stateid.seqid); | 787 | oldseq = be32_to_cpu(lo->plh_stateid.seqid); |
780 | newseq = be32_to_cpu(new->seqid); | 788 | newseq = be32_to_cpu(new->seqid); |
781 | if (invalid || pnfs_seqid_is_newer(newseq, oldseq)) { | 789 | |
790 | if (!pnfs_layout_is_valid(lo)) { | ||
791 | nfs4_stateid_copy(&lo->plh_stateid, new); | ||
792 | lo->plh_barrier = newseq; | ||
793 | pnfs_clear_layoutreturn_info(lo); | ||
794 | clear_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | ||
795 | return; | ||
796 | } | ||
797 | if (pnfs_seqid_is_newer(newseq, oldseq)) { | ||
782 | nfs4_stateid_copy(&lo->plh_stateid, new); | 798 | nfs4_stateid_copy(&lo->plh_stateid, new); |
783 | /* | 799 | /* |
784 | * Because of wraparound, we want to keep the barrier | 800 | * Because of wraparound, we want to keep the barrier |
@@ -790,7 +806,7 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, | |||
790 | new_barrier = be32_to_cpu(new->seqid); | 806 | new_barrier = be32_to_cpu(new->seqid); |
791 | else if (new_barrier == 0) | 807 | else if (new_barrier == 0) |
792 | return; | 808 | return; |
793 | if (invalid || pnfs_seqid_is_newer(new_barrier, lo->plh_barrier)) | 809 | if (pnfs_seqid_is_newer(new_barrier, lo->plh_barrier)) |
794 | lo->plh_barrier = new_barrier; | 810 | lo->plh_barrier = new_barrier; |
795 | } | 811 | } |
796 | 812 | ||
@@ -886,19 +902,14 @@ void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo) | |||
886 | rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq); | 902 | rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq); |
887 | } | 903 | } |
888 | 904 | ||
889 | static void | ||
890 | pnfs_clear_layoutreturn_info(struct pnfs_layout_hdr *lo) | ||
891 | { | ||
892 | lo->plh_return_iomode = 0; | ||
893 | lo->plh_return_seq = 0; | ||
894 | clear_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags); | ||
895 | } | ||
896 | |||
897 | static bool | 905 | static bool |
898 | pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo, | 906 | pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo, |
899 | nfs4_stateid *stateid, | 907 | nfs4_stateid *stateid, |
900 | enum pnfs_iomode *iomode) | 908 | enum pnfs_iomode *iomode) |
901 | { | 909 | { |
910 | /* Serialise LAYOUTGET/LAYOUTRETURN */ | ||
911 | if (atomic_read(&lo->plh_outstanding) != 0) | ||
912 | return false; | ||
902 | if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) | 913 | if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) |
903 | return false; | 914 | return false; |
904 | pnfs_get_layout_hdr(lo); | 915 | pnfs_get_layout_hdr(lo); |
@@ -1798,16 +1809,11 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
1798 | */ | 1809 | */ |
1799 | pnfs_mark_layout_stateid_invalid(lo, &free_me); | 1810 | pnfs_mark_layout_stateid_invalid(lo, &free_me); |
1800 | 1811 | ||
1801 | nfs4_stateid_copy(&lo->plh_stateid, &res->stateid); | 1812 | pnfs_set_layout_stateid(lo, &res->stateid, true); |
1802 | lo->plh_barrier = be32_to_cpu(res->stateid.seqid); | ||
1803 | } | 1813 | } |
1804 | 1814 | ||
1805 | pnfs_get_lseg(lseg); | 1815 | pnfs_get_lseg(lseg); |
1806 | pnfs_layout_insert_lseg(lo, lseg, &free_me); | 1816 | pnfs_layout_insert_lseg(lo, lseg, &free_me); |
1807 | if (!pnfs_layout_is_valid(lo)) { | ||
1808 | pnfs_clear_layoutreturn_info(lo); | ||
1809 | clear_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | ||
1810 | } | ||
1811 | 1817 | ||
1812 | 1818 | ||
1813 | if (res->return_on_close) | 1819 | if (res->return_on_close) |