From: Darrick J. Wong <djwong@xxxxxxxxxx> Now that xfs_attr_list can pass local xattr values to the put_listent function, build a new version of the GETPARENTS backend that supplies a custom put_listent function to format parent pointer info directly into the caller's buffer. This uses a lot less memory and obviates the iterate list and then grab the values logic, since parent pointers aren't supposed to have remote values anyway. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- libxfs/xfs_parent.c | 40 ++++++++++++++++++++++++++++++---------- libxfs/xfs_parent.h | 21 +++++++++++++++++++-- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c index 654eaec7..74c7f1f7 100644 --- a/libxfs/xfs_parent.c +++ b/libxfs/xfs_parent.c @@ -30,16 +30,6 @@ struct kmem_cache *xfs_parent_intent_cache; -/* Initializes a xfs_parent_ptr from an xfs_parent_name_rec */ -void -xfs_init_parent_ptr(struct xfs_parent_ptr *xpp, - const struct xfs_parent_name_rec *rec) -{ - xpp->xpp_ino = be64_to_cpu(rec->p_ino); - xpp->xpp_gen = be32_to_cpu(rec->p_gen); - xpp->xpp_diroffset = be32_to_cpu(rec->p_diroffset); -} - /* * Parent pointer attribute handling. * @@ -116,6 +106,36 @@ xfs_init_parent_name_rec( rec->p_diroffset = cpu_to_be32(p_diroffset); } +/* + * Convert an ondisk parent_name xattr to its incore format. If @value is + * NULL, set @irec->p_namelen to zero and leave @irec->p_name untouched. + */ +void +xfs_parent_irec_from_disk( + struct xfs_parent_name_irec *irec, + const struct xfs_parent_name_rec *rec, + const void *value, + int valuelen) +{ + irec->p_ino = be64_to_cpu(rec->p_ino); + irec->p_gen = be32_to_cpu(rec->p_gen); + irec->p_diroffset = be32_to_cpu(rec->p_diroffset); + + if (!value) { + irec->p_namelen = 0; + return; + } + + ASSERT(valuelen > 0); + ASSERT(valuelen < MAXNAMELEN); + + valuelen = min(valuelen, MAXNAMELEN); + + irec->p_namelen = valuelen; + memcpy(irec->p_name, value, valuelen); + memset(&irec->p_name[valuelen], 0, sizeof(irec->p_name) - valuelen); +} + int __xfs_parent_init( struct xfs_mount *mp, diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h index 4ffcb81d..f4f5887d 100644 --- a/libxfs/xfs_parent.h +++ b/libxfs/xfs_parent.h @@ -15,6 +15,25 @@ bool xfs_parent_namecheck(struct xfs_mount *mp, bool xfs_parent_valuecheck(struct xfs_mount *mp, const void *value, size_t valuelen); +/* + * Incore version of a parent pointer, also contains dirent name so callers + * can pass/obtain all the parent pointer information in a single structure + */ +struct xfs_parent_name_irec { + /* Key fields for looking up a particular parent pointer. */ + xfs_ino_t p_ino; + uint32_t p_gen; + xfs_dir2_dataptr_t p_diroffset; + + /* Attributes of a parent pointer. */ + uint8_t p_namelen; + unsigned char p_name[MAXNAMELEN]; +}; + +void xfs_parent_irec_from_disk(struct xfs_parent_name_irec *irec, + const struct xfs_parent_name_rec *rec, + const void *value, int valuelen); + /* * Dynamically allocd structure used to wrap the needed data to pass around * the defer ops machinery @@ -32,8 +51,6 @@ struct xfs_parent_defer { void xfs_init_parent_name_rec(struct xfs_parent_name_rec *rec, struct xfs_inode *ip, uint32_t p_diroffset); -void xfs_init_parent_ptr(struct xfs_parent_ptr *xpp, - const struct xfs_parent_name_rec *rec); int __xfs_parent_init(struct xfs_mount *mp, bool grab_log, struct xfs_parent_defer **parentp);