From: Fred Isaman <iisaman@xxxxxxxxxx> Prepare put_lseg and get_lseg to be called from the pNFS I/O code. Pull common code from pnfs_lseg_locked to call from pnfs_lseg. Signed-off-by: Fred Isaman <iisaman@xxxxxxxxxx> Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx> --- fs/nfs/pnfs.c | 53 +++++++++++++++++++++++++++++++++++++++++------------ fs/nfs/pnfs.h | 20 ++++++++++++++++++++ 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 7d031cd..f0a9578 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -230,6 +230,21 @@ static void free_lseg(struct pnfs_layout_segment *lseg) put_layout_hdr(NFS_I(ino)->layout); } +static void +_put_lseg_common(struct pnfs_layout_segment *lseg) +{ + struct inode *ino = lseg->pls_layout->plh_inode; + + BUG_ON(test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); + list_del(&lseg->pls_list); + if (list_empty(&lseg->pls_layout->plh_segs)) { + set_bit(NFS_LAYOUT_DESTROYED, &lseg->pls_layout->plh_flags); + /* Matched by initial refcount set in alloc_init_layout_hdr */ + put_layout_hdr_locked(lseg->pls_layout); + } + rpc_wake_up(&NFS_SERVER(ino)->roc_rpcwaitq); +} + /* The use of tmp_list is necessary because pnfs_curr_ld->free_lseg * could sleep, so must be called outside of the lock. * Returns 1 if object was removed, otherwise return 0. @@ -242,22 +257,35 @@ put_lseg_locked(struct pnfs_layout_segment *lseg, atomic_read(&lseg->pls_refcount), test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); if (atomic_dec_and_test(&lseg->pls_refcount)) { - struct inode *ino = lseg->pls_layout->plh_inode; - - BUG_ON(test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); - list_del(&lseg->pls_list); - if (list_empty(&lseg->pls_layout->plh_segs)) { - set_bit(NFS_LAYOUT_DESTROYED, &lseg->pls_layout->plh_flags); - /* Matched by initial refcount set in alloc_init_layout_hdr */ - put_layout_hdr_locked(lseg->pls_layout); - } - rpc_wake_up(&NFS_SERVER(ino)->roc_rpcwaitq); + _put_lseg_common(lseg); list_add(&lseg->pls_list, tmp_list); return 1; } return 0; } +static void +put_lseg(struct pnfs_layout_segment *lseg) +{ + struct inode *ino; + + if (!lseg) + return; + + dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg, + atomic_read(&lseg->pls_refcount), + test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); + ino = lseg->pls_layout->plh_inode; + if (atomic_dec_and_lock(&lseg->pls_refcount, &ino->i_lock)) { + LIST_HEAD(free_me); + + _put_lseg_common(lseg); + list_add(&lseg->pls_list, &free_me); + spin_unlock(&ino->i_lock); + pnfs_free_lseg_list(&free_me); + } +} + static bool should_free_lseg(u32 lseg_iomode, u32 recall_iomode) { @@ -689,7 +717,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode) list_for_each_entry(lseg, &lo->plh_segs, pls_list) { if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) && is_matching_lseg(lseg, iomode)) { - ret = lseg; + ret = get_lseg(lseg); break; } if (cmp_layout(iomode, lseg->pls_range.iomode) > 0) @@ -769,6 +797,7 @@ pnfs_update_layout(struct inode *ino, out: dprintk("%s end, state 0x%lx lseg %p\n", __func__, nfsi->layout ? nfsi->layout->plh_flags : -1, lseg); + put_lseg(lseg); /* STUB - callers currently ignore return value */ return lseg; out_unlock: spin_unlock(&ino->i_lock); @@ -821,7 +850,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) } init_lseg(lo, lseg); lseg->pls_range = res->range; - *lgp->lsegpp = lseg; + *lgp->lsegpp = get_lseg(lseg); pnfs_insert_layout(lo, lseg); if (res->return_on_close) { diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index e2612ea..9a994bc 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -177,6 +177,16 @@ static inline int lo_fail_bit(u32 iomode) NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED; } +static inline struct pnfs_layout_segment * +get_lseg(struct pnfs_layout_segment *lseg) +{ + if (lseg) { + atomic_inc(&lseg->pls_refcount); + smp_mb__after_atomic_inc(); + } + return lseg; +} + /* Return true if a layout driver is being used for this mountpoint */ static inline int pnfs_enabled_sb(struct nfs_server *nfss) { @@ -194,6 +204,16 @@ static inline void pnfs_destroy_layout(struct nfs_inode *nfsi) } static inline struct pnfs_layout_segment * +get_lseg(struct pnfs_layout_segment *lseg) +{ + return NULL; +} + +static inline void put_lseg(struct pnfs_layout_segment *lseg) +{ +} + +static inline struct pnfs_layout_segment * pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, enum pnfs_iomode access_type) { -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html