From patchwork Mon Feb 14 19:18:28 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Adamson X-Patchwork-Id: 556621 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p1EJIhtL015648 for ; Mon, 14 Feb 2011 19:18:52 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752843Ab1BNTSt (ORCPT ); Mon, 14 Feb 2011 14:18:49 -0500 Received: from mx2.netapp.com ([216.240.18.37]:41287 "EHLO mx2.netapp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752692Ab1BNTSs (ORCPT ); Mon, 14 Feb 2011 14:18:48 -0500 X-IronPort-AV: E=Sophos;i="4.60,469,1291622400"; d="scan'208";a="518337359" Received: from smtp1.corp.netapp.com ([10.57.156.124]) by mx2-out.netapp.com with ESMTP; 14 Feb 2011 11:18:48 -0800 Received: from fedora-3.dros.org (beaupre2-lxp.hq.netapp.com [10.58.48.75]) by smtp1.corp.netapp.com (8.13.1/8.13.1/NTAP-1.6) with ESMTP id p1EJIfbD024294; Mon, 14 Feb 2011 11:18:47 -0800 (PST) From: andros@netapp.com To: trond.myklebust@netapp.com Cc: linux-nfs@vger.kernel.org, Fred Isaman , Benny Halevy Subject: [PATCH 08/16] pnfs: wave 3: lseg refcounting Date: Mon, 14 Feb 2011 14:18:28 -0500 Message-Id: <1297711116-3139-9-git-send-email-andros@netapp.com> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <1297711116-3139-1-git-send-email-andros@netapp.com> References: <1297711116-3139-1-git-send-email-andros@netapp.com> Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 14 Feb 2011 19:19:12 +0000 (UTC) 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) {