diff options
author | Peng Tao <tao.peng@primarydata.com> | 2014-07-03 01:05:01 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-07-12 18:23:04 -0400 |
commit | fe08c54691f26cbdaf8c88c9c946a3e07d6feb00 (patch) | |
tree | f5f842e99fb59308d82644c29772eaa4ee97aeef /fs/nfs | |
parent | 15bb3afe900dfe1714ba7c53b2582517627da995 (diff) |
nfs41: return layout on last close
If client has valid delegation, do not return layout on close at all.
Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1300013e9b4e..734f7da10241 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2655,6 +2655,48 @@ static const struct rpc_call_ops nfs4_close_ops = { | |||
2655 | .rpc_release = nfs4_free_closedata, | 2655 | .rpc_release = nfs4_free_closedata, |
2656 | }; | 2656 | }; |
2657 | 2657 | ||
2658 | static bool nfs4_state_has_opener(struct nfs4_state *state) | ||
2659 | { | ||
2660 | /* first check existing openers */ | ||
2661 | if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0 && | ||
2662 | state->n_rdonly != 0) | ||
2663 | return true; | ||
2664 | |||
2665 | if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0 && | ||
2666 | state->n_wronly != 0) | ||
2667 | return true; | ||
2668 | |||
2669 | if (test_bit(NFS_O_RDWR_STATE, &state->flags) != 0 && | ||
2670 | state->n_rdwr != 0) | ||
2671 | return true; | ||
2672 | |||
2673 | return false; | ||
2674 | } | ||
2675 | |||
2676 | static bool nfs4_roc(struct inode *inode) | ||
2677 | { | ||
2678 | struct nfs_inode *nfsi = NFS_I(inode); | ||
2679 | struct nfs_open_context *ctx; | ||
2680 | struct nfs4_state *state; | ||
2681 | |||
2682 | spin_lock(&inode->i_lock); | ||
2683 | list_for_each_entry(ctx, &nfsi->open_files, list) { | ||
2684 | state = ctx->state; | ||
2685 | if (state == NULL) | ||
2686 | continue; | ||
2687 | if (nfs4_state_has_opener(state)) { | ||
2688 | spin_unlock(&inode->i_lock); | ||
2689 | return false; | ||
2690 | } | ||
2691 | } | ||
2692 | spin_unlock(&inode->i_lock); | ||
2693 | |||
2694 | if (nfs4_check_delegation(inode, FMODE_READ)) | ||
2695 | return false; | ||
2696 | |||
2697 | return pnfs_roc(inode); | ||
2698 | } | ||
2699 | |||
2658 | /* | 2700 | /* |
2659 | * It is possible for data to be read/written from a mem-mapped file | 2701 | * It is possible for data to be read/written from a mem-mapped file |
2660 | * after the sys_close call (which hits the vfs layer as a flush). | 2702 | * after the sys_close call (which hits the vfs layer as a flush). |
@@ -2705,7 +2747,7 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait) | |||
2705 | calldata->res.fattr = &calldata->fattr; | 2747 | calldata->res.fattr = &calldata->fattr; |
2706 | calldata->res.seqid = calldata->arg.seqid; | 2748 | calldata->res.seqid = calldata->arg.seqid; |
2707 | calldata->res.server = server; | 2749 | calldata->res.server = server; |
2708 | calldata->roc = pnfs_roc(state->inode); | 2750 | calldata->roc = nfs4_roc(state->inode); |
2709 | nfs_sb_active(calldata->inode->i_sb); | 2751 | nfs_sb_active(calldata->inode->i_sb); |
2710 | 2752 | ||
2711 | msg.rpc_argp = &calldata->arg; | 2753 | msg.rpc_argp = &calldata->arg; |