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> --- include/kmem.h | 5 ++++- libxfs/libxfs_api_defs.h | 2 ++ libxfs/xfs_imeta.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_imeta.h | 15 +++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/include/kmem.h b/include/kmem.h index 8ae919c7066..c71e311cabc 100644 --- a/include/kmem.h +++ b/include/kmem.h @@ -26,7 +26,7 @@ typedef unsigned int __bitwise gfp_t; #define __GFP_NOFAIL ((__force gfp_t)0) #define __GFP_NOLOCKDEP ((__force gfp_t)0) -#define __GFP_ZERO (__force gfp_t)1 +#define __GFP_ZERO ((__force gfp_t)1) struct kmem_cache * kmem_cache_create(const char *name, unsigned int size, unsigned int align, unsigned int slab_flags, @@ -65,6 +65,9 @@ static inline void *kmalloc(size_t size, gfp_t flags) return kvmalloc(size, flags); } +#define kvcalloc(nr, size, gfp) kvmalloc((nr) * (size), (gfp) | __GFP_ZERO) +#define kzalloc(size, gfp) kvmalloc((size), (gfp) | __GFP_ZERO) + static inline void kfree(const void *ptr) { return kmem_free(ptr); diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index e08be764a49..ca8e231c0fd 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -177,8 +177,10 @@ #define xfs_imeta_cancel_update libxfs_imeta_cancel_update #define xfs_imeta_commit_update libxfs_imeta_commit_update #define xfs_imeta_create libxfs_imeta_create +#define xfs_imeta_create_file_path libxfs_imeta_create_file_path #define xfs_imeta_create_space_res libxfs_imeta_create_space_res #define xfs_imeta_ensure_dirpath libxfs_imeta_ensure_dirpath +#define xfs_imeta_free_path libxfs_imeta_free_path #define xfs_imeta_iget libxfs_imeta_iget #define xfs_imeta_irele libxfs_imeta_irele #define xfs_imeta_link libxfs_imeta_link diff --git a/libxfs/xfs_imeta.c b/libxfs/xfs_imeta.c index 2defee9562b..ad429c82b47 100644 --- a/libxfs/xfs_imeta.c +++ b/libxfs/xfs_imeta.c @@ -1014,3 +1014,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/libxfs/xfs_imeta.h b/libxfs/xfs_imeta.h index b8e360bbdfb..3b5953efc01 100644 --- a/libxfs/xfs_imeta.h +++ b/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);