@@ -246,3 +246,72 @@ xfs_imeta_cancel_update(
xfs_imeta_teardown(upd, error);
}
+
+/* Create a metadata for the last component of the path. */
+STATIC int
+xfs_imeta_mkdir(
+ struct xfs_mount *mp,
+ const struct xfs_imeta_path *path)
+{
+ struct xfs_imeta_update upd;
+ struct xfs_inode *ip = NULL;
+ int error;
+
+ if (xfs_is_shutdown(mp))
+ return -EIO;
+
+ /* Allocate a transaction to create the last directory. */
+ error = xfs_imeta_start_create(mp, path, &upd);
+ if (error)
+ return error;
+
+ /* Create the subdirectory and take our reference. */
+ error = xfs_imeta_create(&upd, S_IFDIR, &ip);
+ if (error)
+ goto out_cancel;
+
+ error = xfs_imeta_commit_update(&upd);
+
+ /*
+ * We don't pass the directory we just created to the caller, so finish
+ * setting up the inode, then release the dir and the dquots.
+ */
+ goto out_irele;
+
+out_cancel:
+ xfs_imeta_cancel_update(&upd, error);
+out_irele:
+ /* Have to finish setting up the inode to ensure it's deleted. */
+ if (ip)
+ xfs_irele(ip);
+ return error;
+}
+
+/*
+ * Make sure that every metadata directory path component exists and is a
+ * directory.
+ */
+int
+xfs_imeta_ensure_dirpath(
+ struct xfs_mount *mp,
+ const struct xfs_imeta_path *path)
+{
+ struct xfs_imeta_path temp_path = {
+ .im_path = path->im_path,
+ .im_depth = 1,
+ .im_ftype = XFS_DIR3_FT_DIR,
+ };
+ unsigned int i;
+ int error = 0;
+
+ if (!xfs_has_metadir(mp))
+ return 0;
+
+ for (i = 0; i < path->im_depth - 1; i++, temp_path.im_depth++) {
+ error = xfs_imeta_mkdir(mp, &temp_path);
+ if (error && error != -EEXIST)
+ return error;
+ }
+
+ return 0;
+}
@@ -18,6 +18,9 @@ int xfs_imeta_start_unlink(struct xfs_mount *mp,
const struct xfs_imeta_path *path,
struct xfs_inode *ip, struct xfs_imeta_update *upd);
+int xfs_imeta_ensure_dirpath(struct xfs_mount *mp,
+ const struct xfs_imeta_path *path);
+
int xfs_imeta_commit_update(struct xfs_imeta_update *upd);
void xfs_imeta_cancel_update(struct xfs_imeta_update *upd, int error);
@@ -178,6 +178,7 @@
#define xfs_imeta_commit_update libxfs_imeta_commit_update
#define xfs_imeta_create libxfs_imeta_create
#define xfs_imeta_create_space_res libxfs_imeta_create_space_res
+#define xfs_imeta_ensure_dirpath libxfs_imeta_ensure_dirpath
#define xfs_imeta_iget libxfs_imeta_iget
#define xfs_imeta_irele libxfs_imeta_irele
#define xfs_imeta_link libxfs_imeta_link
@@ -754,6 +754,10 @@ rtbitmap_create(
struct xfs_inode *rbmip;
int error;
+ error = -libxfs_imeta_ensure_dirpath(mp, &XFS_IMETA_RTBITMAP);
+ if (error)
+ fail(_("Realtime bitmap directory allocation failed"), error);
+
error = -libxfs_imeta_start_create(mp, &XFS_IMETA_RTBITMAP, &upd);
if (error)
res_failed(error);
@@ -783,6 +787,10 @@ rtsummary_create(
struct xfs_inode *rsumip;
int error;
+ error = -libxfs_imeta_ensure_dirpath(mp, &XFS_IMETA_RTSUMMARY);
+ if (error)
+ fail(_("Realtime summary directory allocation failed"), error);
+
error = -libxfs_imeta_start_create(mp, &XFS_IMETA_RTSUMMARY, &upd);
if (error)
res_failed(error);