aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorPeng Tao <tao.peng@primarydata.com>2014-09-05 12:53:25 -0400
committerTom Haynes <loghyr@primarydata.com>2015-02-03 14:06:42 -0500
commitaa1e0e3a8e3f16ff50a72a8c623d7e1c467383bc (patch)
treec72526b4d63a188484fbe9b371cc5c356641f4d1 /fs/nfs
parentce6ab4f238cb76d356229e97e1fefb7192388e13 (diff)
nfs41: send layoutreturn in last put_lseg
If current lseg is the last lseg marked with NFS_LSEG_LAYOUTRETURN, send layoutreturn. Signed-off-by: Peng Tao <tao.peng@primarydata.com> Signed-off-by: Tom Haynes <Thomas.Haynes@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/pnfs.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 853b544f2efc..e9acfcfdc9a9 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -50,6 +50,10 @@ static DEFINE_SPINLOCK(pnfs_spinlock);
50 */ 50 */
51static LIST_HEAD(pnfs_modules_tbl); 51static LIST_HEAD(pnfs_modules_tbl);
52 52
53static int
54pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, nfs4_stateid stateid,
55 enum pnfs_iomode iomode);
56
53/* Return the registered pnfs layout driver module matching given id */ 57/* Return the registered pnfs layout driver module matching given id */
54static struct pnfs_layoutdriver_type * 58static struct pnfs_layoutdriver_type *
55find_pnfs_driver_locked(u32 id) 59find_pnfs_driver_locked(u32 id)
@@ -337,6 +341,29 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo,
337 rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); 341 rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq);
338} 342}
339 343
344/* Return true if layoutreturn is needed */
345static bool
346pnfs_layout_need_return(struct pnfs_layout_hdr *lo,
347 struct pnfs_layout_segment *lseg,
348 nfs4_stateid *stateid, enum pnfs_iomode *iomode)
349{
350 struct pnfs_layout_segment *s;
351
352 if (!test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
353 return false;
354
355 list_for_each_entry(s, &lo->plh_segs, pls_list)
356 if (test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
357 return false;
358
359 *stateid = lo->plh_stateid;
360 *iomode = lo->plh_return_iomode;
361 /* decreased in pnfs_send_layoutreturn() */
362 lo->plh_block_lgets++;
363 lo->plh_return_iomode = 0;
364 return true;
365}
366
340void 367void
341pnfs_put_lseg(struct pnfs_layout_segment *lseg) 368pnfs_put_lseg(struct pnfs_layout_segment *lseg)
342{ 369{
@@ -352,11 +379,20 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)
352 lo = lseg->pls_layout; 379 lo = lseg->pls_layout;
353 inode = lo->plh_inode; 380 inode = lo->plh_inode;
354 if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) { 381 if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
382 bool need_return;
383 nfs4_stateid stateid;
384 enum pnfs_iomode iomode;
385
355 pnfs_get_layout_hdr(lo); 386 pnfs_get_layout_hdr(lo);
356 pnfs_layout_remove_lseg(lo, lseg); 387 pnfs_layout_remove_lseg(lo, lseg);
388 need_return = pnfs_layout_need_return(lo, lseg,
389 &stateid, &iomode);
357 spin_unlock(&inode->i_lock); 390 spin_unlock(&inode->i_lock);
358 pnfs_free_lseg(lseg); 391 pnfs_free_lseg(lseg);
359 pnfs_put_layout_hdr(lo); 392 if (need_return)
393 pnfs_send_layoutreturn(lo, stateid, iomode);
394 else
395 pnfs_put_layout_hdr(lo);
360 } 396 }
361} 397}
362EXPORT_SYMBOL_GPL(pnfs_put_lseg); 398EXPORT_SYMBOL_GPL(pnfs_put_lseg);