+++ /dev/null
-From: Darrick J. Wong <darrick.wong@oracle.com>\r
-\r
-When we added a new defer op type for agfl block freeing to the kernel,\r
-we forgot to add that type to the userspace side of things. This will\r
-cause spontaneous combustion in xfs_repair if we try to rebuild\r
-directories.\r
-\r
-Fixes: d5c1b462232 ("xfs: defer agfl block frees when dfops is available")\r
-Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>\r
----\r
- libxfs/defer_item.c | 44 ++++++++++++++++++++++++++++++++++++++++++++\r
- 1 file changed, 44 insertions(+)\r
-\r
-diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c\r
-index b7185c1a..82aa32a8 100644\r
---- a/libxfs/defer_item.c\r
-+++ b/libxfs/defer_item.c\r
-@@ -118,11 +118,55 @@ static const struct xfs_defer_op_type xfs_extent_free_defer_type = {\r
- .cancel_item = xfs_extent_free_cancel_item,\r
- };\r
- \r
-+/*\r
-+ * AGFL blocks are accounted differently in the reserve pools and are not\r
-+ * inserted into the busy extent list.\r
-+ */\r
-+STATIC int\r
-+xfs_agfl_free_finish_item(\r
-+ struct xfs_trans *tp,\r
-+ struct list_head *item,\r
-+ void *done_item,\r
-+ void **state)\r
-+{\r
-+ struct xfs_mount *mp = tp->t_mountp;\r
-+ struct xfs_extent_free_item *free;\r
-+ struct xfs_buf *agbp;\r
-+ int error;\r
-+ xfs_agnumber_t agno;\r
-+ xfs_agblock_t agbno;\r
-+\r
-+ free = container_of(item, struct xfs_extent_free_item, xefi_list);\r
-+ ASSERT(free->xefi_blockcount == 1);\r
-+ agno = XFS_FSB_TO_AGNO(mp, free->xefi_startblock);\r
-+ agbno = XFS_FSB_TO_AGBNO(mp, free->xefi_startblock);\r
-+\r
-+ error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);\r
-+ if (!error)\r
-+ error = xfs_free_agfl_block(tp, agno, agbno, agbp,\r
-+ &free->xefi_oinfo);\r
-+ kmem_free(free);\r
-+ return error;\r
-+}\r
-+\r
-+/* sub-type with special handling for AGFL deferred frees */\r
-+static const struct xfs_defer_op_type xfs_agfl_free_defer_type = {\r
-+ .type = XFS_DEFER_OPS_TYPE_AGFL_FREE,\r
-+ .diff_items = xfs_extent_free_diff_items,\r
-+ .create_intent = xfs_extent_free_create_intent,\r
-+ .abort_intent = xfs_extent_free_abort_intent,\r
-+ .log_item = xfs_extent_free_log_item,\r
-+ .create_done = xfs_extent_free_create_done,\r
-+ .finish_item = xfs_agfl_free_finish_item,\r
-+ .cancel_item = xfs_extent_free_cancel_item,\r
-+};\r
-+\r
- /* Register the deferred op type. */\r
- void\r
- xfs_extent_free_init_defer_op(void)\r
- {\r
- xfs_defer_init_op_type(&xfs_extent_free_defer_type);\r
-+ xfs_defer_init_op_type(&xfs_agfl_free_defer_type);\r
- }\r
- \r
- /* Reverse Mapping */\r
-Subject: [PATCH 1/2] xfs_repair: initialize realloced bplist in\r
- longform_dir2_entry_check\r
-From: Eric Sandeen <sandeen@sandeen.net>\r
-\r
-If we need to realloc the bplist[] array holding buffers for a given\r
-directory, we don't initialize the new slots. This causes a problem\r
-if the directory has holes, because those slots never get filled in.\r
-\r
-At the end of the function we call libxfs_putbuf for every non-null\r
-slot, and any uninitialized slots are segfault landmines.\r
-\r
-Make sure we initialize all new slots to NULL for this reason.\r
-\r
-Reported-by: Oleg Davydov <burunduk3@gmail.com>\r
-Signed-off-by: Eric Sandeen <sandeen@redhat.com>\r
----\r
-\r
-diff --git a/repair/phase6.c b/repair/phase6.c\r
-index b87c751..9d24a4f 100644\r
---- a/repair/phase6.c\r
-+++ b/repair/phase6.c\r
-@@ -2348,6 +2348,8 @@ longform_dir2_entry_check(xfs_mount_t *mp,\r
- \r
- db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);\r
- if (db >= num_bps) {\r
-+ int last_size = num_bps;\r
-+\r
- /* more data blocks than expected */\r
- num_bps = db + 1;\r
- bplist = realloc(bplist, num_bps * sizeof(struct xfs_buf*));\r
-@@ -2355,6 +2357,9 @@ longform_dir2_entry_check(xfs_mount_t *mp,\r
- do_error(_("realloc failed in %s (%zu bytes)\n"),\r
- __func__,\r
- num_bps * sizeof(struct xfs_buf*));\r
-+ /* Initialize the new elements */\r
-+ for (i = last_size; i < num_bps; i++)\r
-+ bplist[i] = NULL;\r
- }\r
- \r
- if (isblock)\r
-\r
-Subject: [PATCH 2/2] xfs_repair: continue after xfs_bunmapi deadlock avoidance\r
-From: Eric Sandeen <sandeen@sandeen.net>\r
-\r
-After commit:\r
-\r
-15a8bcc xfs: fix multi-AG deadlock in xfs_bunmapi\r
-\r
-xfs_bunmapi can legitimately return before all work is done.\r
-Sadly nobody told xfs_repair, so it fires an assert:\r
-\r
- phase6.c:1410: longform_dir2_rebuild: Assertion `done' failed. \r
-\r
-Fix this by calling back in until all work is done, as we do\r
-in the kernel.\r
-\r
-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1641116\r
-Reported-by: Tomasz Torcz <tomek@pipebreaker.pl>\r
-Signed-off-by: Eric Sandeen <sandeen@redhat.com>\r
----\r
-\r
-diff --git a/repair/phase6.c b/repair/phase6.c\r
-index e017326..b87c751 100644\r
---- a/repair/phase6.c\r
-+++ b/repair/phase6.c\r
-@@ -1317,7 +1317,7 @@ longform_dir2_rebuild(\r
- xfs_fileoff_t lastblock;\r
- xfs_inode_t pip;\r
- dir_hash_ent_t *p;\r
-- int done;\r
-+ int done = 0;\r
- \r
- /*\r
- * trash directory completely and rebuild from scratch using the\r
-@@ -1352,12 +1352,25 @@ longform_dir2_rebuild(\r
- error);\r
- \r
- /* free all data, leaf, node and freespace blocks */\r
-- error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA, 0,\r
-- &firstblock, &dfops, &done);\r
-- if (error) {\r
-- do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);\r
-- goto out_bmap_cancel;\r
-- }\r
-+ while (!done) {\r
-+ error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA,\r
-+ 0, &firstblock, &dfops, &done);\r
-+ if (error) {\r
-+ do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);\r
-+ goto out_bmap_cancel;\r
-+ }\r
-+ error = xfs_defer_finish(&tp, &dfops);\r
-+ if (error) {\r
-+ do_warn(("defer_finish failed -- error - %d\n"), error);\r
-+ goto out_bmap_cancel;\r
-+ }\r
-+ /*\r
-+ * Close out trans and start the next one in the chain.\r
-+ */\r
-+ error = xfs_trans_roll_inode(&tp, ip);\r
-+ if (error)\r
-+ goto out_bmap_cancel;\r
-+ }\r
- \r
- ASSERT(done);\r
- \r
-\r
-From: "Darrick J. Wong" <darrick.wong@oracle.com>\r
-Subject: [PATCH] libxfs: check all defer ops types\r
-\r
-From: Darrick J. Wong <darrick.wong@oracle.com>\r
-\r
-Make sure we have all the defer ops types loaded before proceeding.\r
-\r
-Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>\r
----\r
- libxfs/init.c | 5 +++++\r
- libxfs/xfs_defer.c | 12 ++++++++++++\r
- libxfs/xfs_defer.h | 1 +\r
- 3 files changed, 18 insertions(+)\r
-\r
-diff --git a/libxfs/init.c b/libxfs/init.c\r
-index 750b8f20..d1fdc3a8 100644\r
---- a/libxfs/init.c\r
-+++ b/libxfs/init.c\r
-@@ -253,6 +253,11 @@ libxfs_init(libxfs_init_t *a)\r
- xfs_rmap_update_init_defer_op();\r
- xfs_refcount_update_init_defer_op();\r
- xfs_bmap_update_init_defer_op();\r
-+ if (!xfs_defer_check_all_present()) {\r
-+ fprintf(stderr, _("%s: defer ops not all there\n"),\r
-+ progname);\r
-+ goto done;\r
-+ }\r
- \r
- radix_tree_init();\r
- \r
-diff --git a/libxfs/xfs_defer.c b/libxfs/xfs_defer.c\r
-index 5a6da0f3..cd3a8ef3 100644\r
---- a/libxfs/xfs_defer.c\r
-+++ b/libxfs/xfs_defer.c\r
-@@ -545,3 +545,15 @@ xfs_defer_move(\r
- \r
- xfs_defer_reset(stp);\r
- }\r
-+\r
-+/* Make sure we filled out all the defer_ops types. */\r
-+bool\r
-+xfs_defer_check_all_present(void)\r
-+{\r
-+ int x;\r
-+\r
-+ for(x = 0; x < XFS_DEFER_OPS_TYPE_MAX; x++)\r
-+ if (defer_op_types[x] == NULL)\r
-+ return false;\r
-+ return true;\r
-+}\r
-diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h\r
-index 2584a5b9..bc7ae7ff 100644\r
---- a/libxfs/xfs_defer.h\r
-+++ b/libxfs/xfs_defer.h\r
-@@ -57,5 +57,6 @@ struct xfs_defer_op_type {\r
- };\r
- \r
- void xfs_defer_init_op_type(const struct xfs_defer_op_type *type);\r
-+bool xfs_defer_check_all_present(void);\r
- \r
- #endif /* __XFS_DEFER_H__ */\r