diff options
author | Peng Tao <tao.peng@primarydata.com> | 2014-09-05 12:53:25 -0400 |
---|---|---|
committer | Tom Haynes <loghyr@primarydata.com> | 2015-02-03 14:06:42 -0500 |
commit | aa1e0e3a8e3f16ff50a72a8c623d7e1c467383bc (patch) | |
tree | c72526b4d63a188484fbe9b371cc5c356641f4d1 /fs/nfs | |
parent | ce6ab4f238cb76d356229e97e1fefb7192388e13 (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.c | 38 |
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 | */ |
51 | static LIST_HEAD(pnfs_modules_tbl); | 51 | static LIST_HEAD(pnfs_modules_tbl); |
52 | 52 | ||
53 | static int | ||
54 | pnfs_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 */ |
54 | static struct pnfs_layoutdriver_type * | 58 | static struct pnfs_layoutdriver_type * |
55 | find_pnfs_driver_locked(u32 id) | 59 | find_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 */ | ||
345 | static bool | ||
346 | pnfs_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 | |||
340 | void | 367 | void |
341 | pnfs_put_lseg(struct pnfs_layout_segment *lseg) | 368 | pnfs_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 | } |
362 | EXPORT_SYMBOL_GPL(pnfs_put_lseg); | 398 | EXPORT_SYMBOL_GPL(pnfs_put_lseg); |