]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
xfs: Reference count per-ag structures
authorDave Chinner <david@fromorbit.com>
Mon, 11 Jan 2010 11:47:45 +0000 (11:47 +0000)
committerAlex Elder <aelder@sgi.com>
Fri, 15 Jan 2010 21:34:04 +0000 (15:34 -0600)
Reference count the per-ag structures to ensure that we keep get/put
pairs balanced. Assert that the reference counts are zero at unmount
time to catch leaks. In future, reference counts will enable us to
safely remove perag structures by allowing us to detect when they
are no longer in use.

Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
fs/xfs/xfs_ag.h
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h

index 6702bd865811d49fc09cda25bb176da256153599..18ae43f4255d4a6676e605dc056d5dfda3b28b78 100644 (file)
@@ -196,8 +196,8 @@ typedef struct xfs_perag_busy {
 #define XFS_PAGB_NUM_SLOTS     128
 #endif
 
-typedef struct xfs_perag
-{
+typedef struct xfs_perag {
+       atomic_t        pag_ref;        /* perag reference count */
        char            pagf_init;      /* this agf's entry is initialized */
        char            pagi_init;      /* this agi's entry is initialized */
        char            pagf_metadata;  /* the agf is preferred to be metadata */
index c04dd83cb57c0b82b812f86c0c717ad220b79bc3..f241fec26070ac4e4a737e1c45012b7776458a83 100644 (file)
@@ -215,6 +215,7 @@ xfs_free_perag(
        for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
                spin_lock(&mp->m_perag_lock);
                pag = radix_tree_delete(&mp->m_perag_tree, agno);
+               ASSERT(atomic_read(&pag->pag_ref) == 0);
                spin_unlock(&mp->m_perag_lock);
                ASSERT(pag);
                kmem_free(pag->pagb_list);
index cfa7a5d22e7256239b13fdee4f6dad9a0bacfccb..16b22120b98fa45fe12050944dc08dfa8c2e5a0e 100644 (file)
@@ -384,7 +384,7 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
 }
 
 /*
- * perag get/put wrappers for eventual ref counting
+ * perag get/put wrappers for ref counting
  */
 static inline struct xfs_perag *
 xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno)
@@ -393,6 +393,12 @@ xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno)
 
        spin_lock(&mp->m_perag_lock);
        pag = radix_tree_lookup(&mp->m_perag_tree, agno);
+       if (pag) {
+               ASSERT(atomic_read(&pag->pag_ref) >= 0);
+               /* catch leaks in the positive direction during testing */
+               ASSERT(atomic_read(&pag->pag_ref) < 1000);
+               atomic_inc(&pag->pag_ref);
+       }
        spin_unlock(&mp->m_perag_lock);
        return pag;
 }
@@ -400,7 +406,8 @@ xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno)
 static inline void
 xfs_perag_put(struct xfs_perag *pag)
 {
-       /* nothing to see here, move along */
+       ASSERT(atomic_read(&pag->pag_ref) > 0);
+       atomic_dec(&pag->pag_ref);
 }
 
 /*