From: Darrick J. Wong <djwong@xxxxxxxxxx> Add a few helper functions so that it's possible to allocate xfs_imeta_path objects dynamically, along with dynamically allocated path components. Eventually we're going to want to support paths of the form "/realtime/$rtgroup.rmap", and this is necessary for that. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_imeta.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_imeta.h | 15 +++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/fs/xfs/libxfs/xfs_imeta.c b/fs/xfs/libxfs/xfs_imeta.c index e3651c7bba2b3..10249a1c36c73 100644 --- a/fs/xfs/libxfs/xfs_imeta.c +++ b/fs/xfs/libxfs/xfs_imeta.c @@ -1015,3 +1015,49 @@ xfs_imeta_mount( return 0; } + +/* Create a path to a file within the metadata directory tree. */ +int +xfs_imeta_create_file_path( + struct xfs_mount *mp, + unsigned int nr_components, + struct xfs_imeta_path **pathp) +{ + struct xfs_imeta_path *p; + unsigned char **components; + + p = kzalloc(sizeof(struct xfs_imeta_path), GFP_KERNEL); + if (!p) + return -ENOMEM; + + components = kvcalloc(nr_components, sizeof(unsigned char *), + GFP_KERNEL); + if (!components) { + kfree(p); + return -ENOMEM; + } + + p->im_depth = nr_components; + p->im_path = (const unsigned char **)components; + p->im_ftype = XFS_DIR3_FT_REG_FILE; + *pathp = p; + return 0; +} + +/* Free a metadata directory tree path. */ +void +xfs_imeta_free_path( + const struct xfs_imeta_path *path) +{ + unsigned int i; + + if (path->im_flags & XFS_IMETA_PATH_STATIC) + return; + + for (i = 0; i < path->im_depth; i++) { + if ((path->im_dynamicmask & (1ULL << i)) && path->im_path[i]) + kfree(path->im_path[i]); + } + kfree(path->im_path); + kfree(path); +} diff --git a/fs/xfs/libxfs/xfs_imeta.h b/fs/xfs/libxfs/xfs_imeta.h index b8e360bbdfbe1..3b5953efc013c 100644 --- a/fs/xfs/libxfs/xfs_imeta.h +++ b/fs/xfs/libxfs/xfs_imeta.h @@ -15,6 +15,8 @@ const struct xfs_imeta_path name = { \ .im_path = (path), \ .im_ftype = XFS_DIR3_FT_REG_FILE, \ .im_depth = ARRAY_SIZE(path), \ + .im_flags = XFS_IMETA_PATH_STATIC, \ + .im_dynamicmask = 0, \ } /* Key for looking up metadata inodes. */ @@ -22,6 +24,12 @@ struct xfs_imeta_path { /* Array of string pointers. */ const unsigned char **im_path; + /* Each bit corresponds to an element of im_path needing to be freed */ + unsigned long long im_dynamicmask; + + /* XFS_IMETA_* path flags */ + uint16_t im_flags; + /* Number of strings in path. */ uint8_t im_depth; @@ -29,6 +37,9 @@ struct xfs_imeta_path { uint8_t im_ftype; }; +/* Path is statically allocated. */ +#define XFS_IMETA_PATH_STATIC (1U << 0) + /* Cleanup widget for metadata inode creation and deletion. */ struct xfs_imeta_update { struct xfs_mount *mp; @@ -72,6 +83,10 @@ int xfs_imeta_lookup(struct xfs_trans *tp, const struct xfs_imeta_path *path, int xfs_imeta_dir_parent(struct xfs_trans *tp, const struct xfs_imeta_path *path, struct xfs_inode **dpp); +int xfs_imeta_create_file_path(struct xfs_mount *mp, + unsigned int nr_components, struct xfs_imeta_path **pathp); +void xfs_imeta_free_path(const struct xfs_imeta_path *path); + void xfs_imeta_set_iflag(struct xfs_trans *tp, struct xfs_inode *ip); void xfs_imeta_clear_iflag(struct xfs_trans *tp, struct xfs_inode *ip);