aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2010-01-11 06:47:45 -0500
committerAlex Elder <aelder@sgi.com>2010-01-15 16:34:04 -0500
commitaed3bb90abaf0b42e8c8747e192f7bb97f445279 (patch)
tree4619214ed42821792b05f4417cb95bde90abb562 /fs/xfs
parent1c1c6ebcf5284aee4910f3b906ac90c20e510c82 (diff)
xfs: Reference count per-ag structures
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>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_ag.h4
-rw-r--r--fs/xfs/xfs_mount.c1
-rw-r--r--fs/xfs/xfs_mount.h11
3 files changed, 12 insertions, 4 deletions
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 6702bd865811..18ae43f4255d 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -196,8 +196,8 @@ typedef struct xfs_perag_busy {
196#define XFS_PAGB_NUM_SLOTS 128 196#define XFS_PAGB_NUM_SLOTS 128
197#endif 197#endif
198 198
199typedef struct xfs_perag 199typedef struct xfs_perag {
200{ 200 atomic_t pag_ref; /* perag reference count */
201 char pagf_init; /* this agf's entry is initialized */ 201 char pagf_init; /* this agf's entry is initialized */
202 char pagi_init; /* this agi's entry is initialized */ 202 char pagi_init; /* this agi's entry is initialized */
203 char pagf_metadata; /* the agf is preferred to be metadata */ 203 char pagf_metadata; /* the agf is preferred to be metadata */
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index c04dd83cb57c..f241fec26070 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -215,6 +215,7 @@ xfs_free_perag(
215 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { 215 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
216 spin_lock(&mp->m_perag_lock); 216 spin_lock(&mp->m_perag_lock);
217 pag = radix_tree_delete(&mp->m_perag_tree, agno); 217 pag = radix_tree_delete(&mp->m_perag_tree, agno);
218 ASSERT(atomic_read(&pag->pag_ref) == 0);
218 spin_unlock(&mp->m_perag_lock); 219 spin_unlock(&mp->m_perag_lock);
219 ASSERT(pag); 220 ASSERT(pag);
220 kmem_free(pag->pagb_list); 221 kmem_free(pag->pagb_list);
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index cfa7a5d22e72..16b22120b98f 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -384,7 +384,7 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
384} 384}
385 385
386/* 386/*
387 * perag get/put wrappers for eventual ref counting 387 * perag get/put wrappers for ref counting
388 */ 388 */
389static inline struct xfs_perag * 389static inline struct xfs_perag *
390xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno) 390xfs_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)
393 393
394 spin_lock(&mp->m_perag_lock); 394 spin_lock(&mp->m_perag_lock);
395 pag = radix_tree_lookup(&mp->m_perag_tree, agno); 395 pag = radix_tree_lookup(&mp->m_perag_tree, agno);
396 if (pag) {
397 ASSERT(atomic_read(&pag->pag_ref) >= 0);
398 /* catch leaks in the positive direction during testing */
399 ASSERT(atomic_read(&pag->pag_ref) < 1000);
400 atomic_inc(&pag->pag_ref);
401 }
396 spin_unlock(&mp->m_perag_lock); 402 spin_unlock(&mp->m_perag_lock);
397 return pag; 403 return pag;
398} 404}
@@ -400,7 +406,8 @@ xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno)
400static inline void 406static inline void
401xfs_perag_put(struct xfs_perag *pag) 407xfs_perag_put(struct xfs_perag *pag)
402{ 408{
403 /* nothing to see here, move along */ 409 ASSERT(atomic_read(&pag->pag_ref) > 0);
410 atomic_dec(&pag->pag_ref);
404} 411}
405 412
406/* 413/*