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 | 4 +++- libxfs/xfs_imeta.c | 43 +++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_imeta.h | 8 ++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/include/kmem.h b/include/kmem.h index 8ae919c7066..014983173a2 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,8 @@ 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) + static inline void kfree(const void *ptr) { return kmem_free(ptr); diff --git a/libxfs/xfs_imeta.c b/libxfs/xfs_imeta.c index 1502d4eb2e3..eaf63275c08 100644 --- a/libxfs/xfs_imeta.c +++ b/libxfs/xfs_imeta.c @@ -1148,3 +1148,46 @@ xfs_imeta_lookup_update( return error; } + +/* 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; + char **components; + + p = kmalloc(sizeof(struct xfs_imeta_path), GFP_KERNEL); + if (!p) + return -ENOMEM; + + components = kvcalloc(nr_components, sizeof(char *), GFP_KERNEL); + if (!components) { + kfree(p); + return -ENOMEM; + } + + p->im_depth = nr_components; + p->im_path = (const char **)components; + p->im_ftype = XFS_DIR3_FT_REG_FILE; + p->im_dynamicmask = 0; + *pathp = p; + return 0; +} + +/* Free a metadata directory tree path. */ +void +xfs_imeta_free_path( + struct xfs_imeta_path *path) +{ + unsigned int i; + + 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 741f426c6a4..7840087b71d 100644 --- a/libxfs/xfs_imeta.h +++ b/libxfs/xfs_imeta.h @@ -15,6 +15,7 @@ const struct xfs_imeta_path name = { \ .im_path = (path), \ .im_ftype = XFS_DIR3_FT_REG_FILE, \ .im_depth = ARRAY_SIZE(path), \ + .im_dynamicmask = 0, \ } /* Key for looking up metadata inodes. */ @@ -27,6 +28,9 @@ struct xfs_imeta_path { /* Expected file type. */ unsigned int im_ftype; + + /* Each bit corresponds to an element of im_path needing to be freed */ + unsigned long long im_dynamicmask; }; /* Cleanup widget for metadata inode creation and deletion. */ @@ -52,6 +56,10 @@ int xfs_imeta_lookup_update(struct xfs_mount *mp, const struct xfs_imeta_path *path, struct xfs_imeta_update *upd, xfs_ino_t *inop); +int xfs_imeta_create_file_path(struct xfs_mount *mp, + unsigned int nr_components, struct xfs_imeta_path **pathp); +void xfs_imeta_free_path(struct xfs_imeta_path *path); + void xfs_imeta_set_metaflag(struct xfs_trans *tp, struct xfs_inode *ip); /* Don't allocate quota for this file. */