aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-02-03 12:36:41 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-03 12:36:41 -0500
commit81b676bd87b3e098e06295a6dd523c02e7861e88 (patch)
tree406f06fbc8e542c8caed8d4cf52773ba0e40efef
parentef582d095db13504a54b9bc57c9489e551441c2a (diff)
parent2370abdab530718b61afc222c51901bdc2884ee2 (diff)
Merge tag 'nfs-for-4.5-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfix and cleanup from Trond Myklebust: "Bugfix: - pNFS: Fix for missing layoutreturn calls Cleanup: - pNFS: rename NFS_LAYOUT_RETURN_BEFORE_CLOSE for code clarity" * tag 'nfs-for-4.5-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFS: Cleanup - rename NFS_LAYOUT_RETURN_BEFORE_CLOSE pNFS: Fix missing layoutreturn calls
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c2
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayoutdev.c2
-rw-r--r--fs/nfs/pnfs.c122
-rw-r--r--fs/nfs/pnfs.h4
4 files changed, 62 insertions, 68 deletions
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 5bcd92d50e82..0cb1abd535e3 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -1215,7 +1215,7 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
1215 hdr->pgio_mirror_idx + 1, 1215 hdr->pgio_mirror_idx + 1,
1216 &hdr->pgio_mirror_idx)) 1216 &hdr->pgio_mirror_idx))
1217 goto out_eagain; 1217 goto out_eagain;
1218 set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, 1218 set_bit(NFS_LAYOUT_RETURN_REQUESTED,
1219 &hdr->lseg->pls_layout->plh_flags); 1219 &hdr->lseg->pls_layout->plh_flags);
1220 pnfs_read_resend_pnfs(hdr); 1220 pnfs_read_resend_pnfs(hdr);
1221 return task->tk_status; 1221 return task->tk_status;
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
index 29898a9550fa..eb370460ce20 100644
--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c
+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
@@ -412,7 +412,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
412 OP_ILLEGAL, GFP_NOIO); 412 OP_ILLEGAL, GFP_NOIO);
413 if (!fail_return) { 413 if (!fail_return) {
414 if (ff_layout_has_available_ds(lseg)) 414 if (ff_layout_has_available_ds(lseg))
415 set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, 415 set_bit(NFS_LAYOUT_RETURN_REQUESTED,
416 &lseg->pls_layout->plh_flags); 416 &lseg->pls_layout->plh_flags);
417 else 417 else
418 pnfs_error_mark_layout_for_return(ino, lseg); 418 pnfs_error_mark_layout_for_return(ino, lseg);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index a3592cc34a20..482b6e94bb37 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -52,9 +52,7 @@ static DEFINE_SPINLOCK(pnfs_spinlock);
52 */ 52 */
53static LIST_HEAD(pnfs_modules_tbl); 53static LIST_HEAD(pnfs_modules_tbl);
54 54
55static int 55static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo);
56pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid,
57 enum pnfs_iomode iomode, bool sync);
58 56
59/* Return the registered pnfs layout driver module matching given id */ 57/* Return the registered pnfs layout driver module matching given id */
60static struct pnfs_layoutdriver_type * 58static struct pnfs_layoutdriver_type *
@@ -243,6 +241,8 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
243{ 241{
244 struct inode *inode = lo->plh_inode; 242 struct inode *inode = lo->plh_inode;
245 243
244 pnfs_layoutreturn_before_put_layout_hdr(lo);
245
246 if (atomic_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) { 246 if (atomic_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
247 if (!list_empty(&lo->plh_segs)) 247 if (!list_empty(&lo->plh_segs))
248 WARN_ONCE(1, "NFS: BUG unfreed layout segments.\n"); 248 WARN_ONCE(1, "NFS: BUG unfreed layout segments.\n");
@@ -345,58 +345,6 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo,
345 rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); 345 rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq);
346} 346}
347 347
348/* Return true if layoutreturn is needed */
349static bool
350pnfs_layout_need_return(struct pnfs_layout_hdr *lo,
351 struct pnfs_layout_segment *lseg)
352{
353 struct pnfs_layout_segment *s;
354
355 if (!test_and_clear_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
356 return false;
357
358 list_for_each_entry(s, &lo->plh_segs, pls_list)
359 if (s != lseg && test_bit(NFS_LSEG_LAYOUTRETURN, &s->pls_flags))
360 return false;
361
362 return true;
363}
364
365static bool
366pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo)
367{
368 if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
369 return false;
370 lo->plh_return_iomode = 0;
371 pnfs_get_layout_hdr(lo);
372 clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags);
373 return true;
374}
375
376static void pnfs_layoutreturn_before_put_lseg(struct pnfs_layout_segment *lseg,
377 struct pnfs_layout_hdr *lo, struct inode *inode)
378{
379 lo = lseg->pls_layout;
380 inode = lo->plh_inode;
381
382 spin_lock(&inode->i_lock);
383 if (pnfs_layout_need_return(lo, lseg)) {
384 nfs4_stateid stateid;
385 enum pnfs_iomode iomode;
386 bool send;
387
388 nfs4_stateid_copy(&stateid, &lo->plh_stateid);
389 iomode = lo->plh_return_iomode;
390 send = pnfs_prepare_layoutreturn(lo);
391 spin_unlock(&inode->i_lock);
392 if (send) {
393 /* Send an async layoutreturn so we dont deadlock */
394 pnfs_send_layoutreturn(lo, &stateid, iomode, false);
395 }
396 } else
397 spin_unlock(&inode->i_lock);
398}
399
400void 348void
401pnfs_put_lseg(struct pnfs_layout_segment *lseg) 349pnfs_put_lseg(struct pnfs_layout_segment *lseg)
402{ 350{
@@ -410,15 +358,8 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)
410 atomic_read(&lseg->pls_refcount), 358 atomic_read(&lseg->pls_refcount),
411 test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); 359 test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
412 360
413 /* Handle the case where refcount != 1 */
414 if (atomic_add_unless(&lseg->pls_refcount, -1, 1))
415 return;
416
417 lo = lseg->pls_layout; 361 lo = lseg->pls_layout;
418 inode = lo->plh_inode; 362 inode = lo->plh_inode;
419 /* Do we need a layoutreturn? */
420 if (test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
421 pnfs_layoutreturn_before_put_lseg(lseg, lo, inode);
422 363
423 if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) { 364 if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
424 if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) { 365 if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) {
@@ -937,6 +878,17 @@ void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo)
937 rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq); 878 rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq);
938} 879}
939 880
881static bool
882pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo)
883{
884 if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
885 return false;
886 lo->plh_return_iomode = 0;
887 pnfs_get_layout_hdr(lo);
888 clear_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags);
889 return true;
890}
891
940static int 892static int
941pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid, 893pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid,
942 enum pnfs_iomode iomode, bool sync) 894 enum pnfs_iomode iomode, bool sync)
@@ -971,6 +923,48 @@ out:
971 return status; 923 return status;
972} 924}
973 925
926/* Return true if layoutreturn is needed */
927static bool
928pnfs_layout_need_return(struct pnfs_layout_hdr *lo)
929{
930 struct pnfs_layout_segment *s;
931
932 if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags))
933 return false;
934
935 /* Defer layoutreturn until all lsegs are done */
936 list_for_each_entry(s, &lo->plh_segs, pls_list) {
937 if (test_bit(NFS_LSEG_LAYOUTRETURN, &s->pls_flags))
938 return false;
939 }
940
941 return true;
942}
943
944static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo)
945{
946 struct inode *inode= lo->plh_inode;
947
948 if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags))
949 return;
950 spin_lock(&inode->i_lock);
951 if (pnfs_layout_need_return(lo)) {
952 nfs4_stateid stateid;
953 enum pnfs_iomode iomode;
954 bool send;
955
956 nfs4_stateid_copy(&stateid, &lo->plh_stateid);
957 iomode = lo->plh_return_iomode;
958 send = pnfs_prepare_layoutreturn(lo);
959 spin_unlock(&inode->i_lock);
960 if (send) {
961 /* Send an async layoutreturn so we dont deadlock */
962 pnfs_send_layoutreturn(lo, &stateid, iomode, false);
963 }
964 } else
965 spin_unlock(&inode->i_lock);
966}
967
974/* 968/*
975 * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr 969 * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
976 * when the layout segment list is empty. 970 * when the layout segment list is empty.
@@ -1091,7 +1085,7 @@ bool pnfs_roc(struct inode *ino)
1091 1085
1092 nfs4_stateid_copy(&stateid, &lo->plh_stateid); 1086 nfs4_stateid_copy(&stateid, &lo->plh_stateid);
1093 /* always send layoutreturn if being marked so */ 1087 /* always send layoutreturn if being marked so */
1094 if (test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, 1088 if (test_and_clear_bit(NFS_LAYOUT_RETURN_REQUESTED,
1095 &lo->plh_flags)) 1089 &lo->plh_flags))
1096 layoutreturn = pnfs_prepare_layoutreturn(lo); 1090 layoutreturn = pnfs_prepare_layoutreturn(lo);
1097 1091
@@ -1772,7 +1766,7 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
1772 pnfs_set_plh_return_iomode(lo, return_range->iomode); 1766 pnfs_set_plh_return_iomode(lo, return_range->iomode);
1773 if (!mark_lseg_invalid(lseg, tmp_list)) 1767 if (!mark_lseg_invalid(lseg, tmp_list))
1774 remaining++; 1768 remaining++;
1775 set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, 1769 set_bit(NFS_LAYOUT_RETURN_REQUESTED,
1776 &lo->plh_flags); 1770 &lo->plh_flags);
1777 } 1771 }
1778 return remaining; 1772 return remaining;
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 9f4e2a47f4aa..1ac1db5f6dad 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -94,8 +94,8 @@ enum {
94 NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */ 94 NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */
95 NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */ 95 NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */
96 NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */ 96 NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */
97 NFS_LAYOUT_RETURN, /* Return this layout ASAP */ 97 NFS_LAYOUT_RETURN, /* layoutreturn in progress */
98 NFS_LAYOUT_RETURN_BEFORE_CLOSE, /* Return this layout before close */ 98 NFS_LAYOUT_RETURN_REQUESTED, /* Return this layout ASAP */
99 NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */ 99 NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */
100 NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */ 100 NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */
101}; 101};