[PATCH 3/4] xfs: add a reference count to the CIL context

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



For the upcoming asynchronoyus discard support we need to be able to delay
freeing the CIL context until the last discard request that reference it
has completed.  Add a reference count to the CIL context, and only clear
the busy extents and free the CIL context structure when it reaches zero,
and a work item to allow freeing it from irq context.

Note that this means delaying the clearing of the busy extents for a little
bit even on non-discard mounts, but with the new busy extent trim/reuse
code there is no real life impact of this change.

Signed-off-by: Christoph Hellwig <hch@xxxxxx>

Index: xfs/fs/xfs/xfs_log_cil.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_cil.c	2011-05-03 12:00:49.000000000 +0200
+++ xfs/fs/xfs/xfs_log_cil.c	2011-05-03 12:17:19.399350953 +0200
@@ -20,7 +20,7 @@
 #include "xfs_types.h"
 #include "xfs_bit.h"
 #include "xfs_log.h"
-#include "xfs_inum.h"
+#include "xfs_inum.h" 
 #include "xfs_trans.h"
 #include "xfs_trans_priv.h"
 #include "xfs_log_priv.h"
@@ -31,6 +31,46 @@
 #include "xfs_alloc.h"
 #include "xfs_discard.h"
 
+static void
+xlog_cil_ctx_free(
+	struct xfs_cil_ctx	*ctx)
+{
+	if (!list_empty(&ctx->busy_extents)) {
+		xfs_alloc_busy_clear(ctx->cil->xc_log->l_mp,
+				     &ctx->busy_extents, false);
+	}
+	kmem_free(ctx);
+}
+
+static void
+xlog_cil_ctx_free_work(
+	struct work_struct	*work)
+{
+	xlog_cil_ctx_free(container_of(work, struct xfs_cil_ctx, work));
+}
+
+static void
+xlog_cil_ctx_init(
+	struct xfs_cil_ctx	*ctx,
+	struct xfs_cil		*cil,
+	xfs_lsn_t		sequence)
+{
+	INIT_LIST_HEAD(&ctx->committing);
+	INIT_LIST_HEAD(&ctx->busy_extents);
+	ctx->sequence = sequence;
+	ctx->cil = cil;
+	atomic_set(&ctx->ref, 1);
+	INIT_WORK(&ctx->work, xlog_cil_ctx_free_work);
+	cil->xc_ctx = ctx;
+
+	/*
+	 * Mirror the sequence into the cil structure so that we can do
+	 * unlocked checks against the current sequence in log forces without
+	 * risking deferencing a freed context pointer.
+	 */
+	cil->xc_current_sequence = ctx->sequence;
+}
+
 /*
  * Perform initial CIL structure initialisation. If the CIL is not
  * enabled in this filesystem, ensure the log->l_cilp is null so
@@ -64,12 +104,7 @@ xlog_cil_init(
 	init_rwsem(&cil->xc_ctx_lock);
 	init_waitqueue_head(&cil->xc_commit_wait);
 
-	INIT_LIST_HEAD(&ctx->committing);
-	INIT_LIST_HEAD(&ctx->busy_extents);
-	ctx->sequence = 1;
-	ctx->cil = cil;
-	cil->xc_ctx = ctx;
-	cil->xc_current_sequence = ctx->sequence;
+	xlog_cil_ctx_init(ctx, cil, 1);
 
 	cil->xc_log = log;
 	log->l_cilp = cil;
@@ -381,10 +416,10 @@ xlog_cil_committed(
 		ASSERT(mp->m_flags & XFS_MOUNT_DISCARD);
 
 		xfs_discard_extents(mp, &ctx->busy_extents);
-		xfs_alloc_busy_clear(mp, &ctx->busy_extents, false);
 	}
 
-	kmem_free(ctx);
+	if (atomic_dec_and_test(&ctx->ref))
+		xlog_cil_ctx_free(ctx);
 }
 
 /*
@@ -491,18 +526,7 @@ xlog_cil_push(
 	 * during log forces to extract the commit lsn of the sequence that
 	 * needs to be forced.
 	 */
-	INIT_LIST_HEAD(&new_ctx->committing);
-	INIT_LIST_HEAD(&new_ctx->busy_extents);
-	new_ctx->sequence = ctx->sequence + 1;
-	new_ctx->cil = cil;
-	cil->xc_ctx = new_ctx;
-
-	/*
-	 * mirror the new sequence into the cil structure so that we can do
-	 * unlocked checks against the current sequence in log forces without
-	 * risking deferencing a freed context pointer.
-	 */
-	cil->xc_current_sequence = new_ctx->sequence;
+	xlog_cil_ctx_init(new_ctx, cil, ctx->sequence + 1);
 
 	/*
 	 * The switch is now done, so we can drop the context lock and move out
Index: xfs/fs/xfs/xfs_log_priv.h
===================================================================
--- xfs.orig/fs/xfs/xfs_log_priv.h	2011-05-03 11:41:29.000000000 +0200
+++ xfs/fs/xfs/xfs_log_priv.h	2011-05-03 12:13:49.743820088 +0200
@@ -390,6 +390,8 @@ struct xfs_cil_ctx {
 	struct xfs_log_vec	*lv_chain;	/* logvecs being pushed */
 	xfs_log_callback_t	log_cb;		/* completion callback hook. */
 	struct list_head	committing;	/* ctx committing list */
+	atomic_t		ref;		/* reference count */
+	struct work_struct	work;		/* for deferred freeing */
 };
 
 /*

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs


[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux