]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libxfs: plumb in refcount deferred op log items
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 25 Oct 2016 22:14:31 +0000 (15:14 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 26 Oct 2016 18:13:48 +0000 (11:13 -0700)
Add a deferred op handler for refcount update actions.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
include/xfs_trans.h
libxfs/defer_item.c
libxfs/init.c

index ab5d59b8e068988dbbe1c22e96bbc464fe46b402..739a792f9bbcacf35dd270a9cee5235f3872ce7a 100644 (file)
@@ -147,5 +147,6 @@ libxfs_trans_read_buf(
 
 void xfs_extent_free_init_defer_op(void);
 void xfs_rmap_update_init_defer_op(void);
+void xfs_refcount_update_init_defer_op(void);
 
 #endif /* __XFS_TRANS_H__ */
index f60a11b74031e88c8554eea8fa8adfae94ec6f0f..1b7d037b9b5d1a6b692f0a272edb888135864899 100644 (file)
@@ -31,6 +31,7 @@
 #include "xfs_bmap.h"
 #include "xfs_alloc.h"
 #include "xfs_rmap.h"
+#include "xfs_refcount.h"
 
 /* Dummy defer item ops, since we don't do logging. */
 
@@ -257,3 +258,132 @@ xfs_rmap_update_init_defer_op(void)
 {
        xfs_defer_init_op_type(&xfs_rmap_update_defer_type);
 }
+
+/* Reference Counting */
+
+/* Sort refcount intents by AG. */
+static int
+xfs_refcount_update_diff_items(
+       void                            *priv,
+       struct list_head                *a,
+       struct list_head                *b)
+{
+       struct xfs_mount                *mp = priv;
+       struct xfs_refcount_intent      *ra;
+       struct xfs_refcount_intent      *rb;
+
+       ra = container_of(a, struct xfs_refcount_intent, ri_list);
+       rb = container_of(b, struct xfs_refcount_intent, ri_list);
+       return  XFS_FSB_TO_AGNO(mp, ra->ri_startblock) -
+               XFS_FSB_TO_AGNO(mp, rb->ri_startblock);
+}
+
+/* Get an CUI. */
+STATIC void *
+xfs_refcount_update_create_intent(
+       struct xfs_trans                *tp,
+       unsigned int                    count)
+{
+       return NULL;
+}
+
+/* Log refcount updates in the intent item. */
+STATIC void
+xfs_refcount_update_log_item(
+       struct xfs_trans                *tp,
+       void                            *intent,
+       struct list_head                *item)
+{
+}
+
+/* Get an CUD so we can process all the deferred refcount updates. */
+STATIC void *
+xfs_refcount_update_create_done(
+       struct xfs_trans                *tp,
+       void                            *intent,
+       unsigned int                    count)
+{
+       return NULL;
+}
+
+/* Process a deferred refcount update. */
+STATIC int
+xfs_refcount_update_finish_item(
+       struct xfs_trans                *tp,
+       struct xfs_defer_ops            *dop,
+       struct list_head                *item,
+       void                            *done_item,
+       void                            **state)
+{
+       struct xfs_refcount_intent      *refc;
+       xfs_fsblock_t                   new_fsb;
+       xfs_extlen_t                    new_aglen;
+       int                             error;
+
+       refc = container_of(item, struct xfs_refcount_intent, ri_list);
+       error = xfs_refcount_finish_one(tp, dop,
+                       refc->ri_type,
+                       refc->ri_startblock,
+                       refc->ri_blockcount,
+                       &new_fsb, &new_aglen,
+                       (struct xfs_btree_cur **)state);
+       /* Did we run out of reservation?  Requeue what we didn't finish. */
+       if (!error && new_aglen > 0) {
+               ASSERT(refc->ri_type == XFS_REFCOUNT_INCREASE ||
+                      refc->ri_type == XFS_REFCOUNT_DECREASE);
+               refc->ri_startblock = new_fsb;
+               refc->ri_blockcount = new_aglen;
+               return -EAGAIN;
+       }
+       kmem_free(refc);
+       return error;
+}
+
+/* Clean up after processing deferred refcounts. */
+STATIC void
+xfs_refcount_update_finish_cleanup(
+       struct xfs_trans        *tp,
+       void                    *state,
+       int                     error)
+{
+       struct xfs_btree_cur    *rcur = state;
+
+       xfs_refcount_finish_one_cleanup(tp, rcur, error);
+}
+
+/* Abort all pending CUIs. */
+STATIC void
+xfs_refcount_update_abort_intent(
+       void                            *intent)
+{
+}
+
+/* Cancel a deferred refcount update. */
+STATIC void
+xfs_refcount_update_cancel_item(
+       struct list_head                *item)
+{
+       struct xfs_refcount_intent      *refc;
+
+       refc = container_of(item, struct xfs_refcount_intent, ri_list);
+       kmem_free(refc);
+}
+
+static const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
+       .type           = XFS_DEFER_OPS_TYPE_REFCOUNT,
+       .diff_items     = xfs_refcount_update_diff_items,
+       .create_intent  = xfs_refcount_update_create_intent,
+       .abort_intent   = xfs_refcount_update_abort_intent,
+       .log_item       = xfs_refcount_update_log_item,
+       .create_done    = xfs_refcount_update_create_done,
+       .finish_item    = xfs_refcount_update_finish_item,
+       .finish_cleanup = xfs_refcount_update_finish_cleanup,
+       .cancel_item    = xfs_refcount_update_cancel_item,
+};
+
+/* Register the deferred op type. */
+void
+xfs_refcount_update_init_defer_op(void)
+{
+       xfs_defer_init_op_type(&xfs_refcount_update_defer_type);
+}
index c962d3e1ffe128a23cb87ece07fdd8163813bf5f..9d9e9287f0683612d1e8a85275385a6d4bfb27ad 100644 (file)
@@ -268,6 +268,7 @@ libxfs_init(libxfs_init_t *a)
 
        xfs_extent_free_init_defer_op();
        xfs_rmap_update_init_defer_op();
+       xfs_refcount_update_init_defer_op();
 
        radix_tree_init();