From: Darrick J. Wong <djwong@xxxxxxxxxx> Update the ondisk parent pointer records as necessary. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- libxfs/libxfs_api_defs.h | 2 + repair/pptr.c | 88 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index e12f0a40b00a..df316727bd62 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -209,8 +209,10 @@ #define xfs_parent_hashval libxfs_parent_hashval #define xfs_parent_lookup libxfs_parent_lookup #define xfs_parent_removename libxfs_parent_removename +#define xfs_parent_set libxfs_parent_set #define xfs_parent_start libxfs_parent_start #define xfs_parent_from_attr libxfs_parent_from_attr +#define xfs_parent_unset libxfs_parent_unset #define xfs_perag_get libxfs_perag_get #define xfs_perag_hold libxfs_perag_hold #define xfs_perag_put libxfs_perag_put diff --git a/repair/pptr.c b/repair/pptr.c index 61466009d88b..94d6d834627c 100644 --- a/repair/pptr.c +++ b/repair/pptr.c @@ -673,6 +673,44 @@ load_file_pptr_name( name, file_pptr->namelen); } +/* Add an on disk parent pointer to a file. */ +static int +add_file_pptr( + struct xfs_inode *ip, + const struct ag_pptr *ag_pptr, + const unsigned char *name) +{ + struct xfs_name xname = { + .name = name, + .len = ag_pptr->namelen, + }; + struct xfs_parent_rec pptr_rec = { }; + struct xfs_da_args scratch; + + xfs_parent_rec_init(&pptr_rec, ag_pptr->parent_ino, + ag_pptr->parent_gen); + return -libxfs_parent_set(ip, ip->i_ino, &xname, &pptr_rec, &scratch); +} + +/* Remove an on disk parent pointer from a file. */ +static int +remove_file_pptr( + struct xfs_inode *ip, + const struct file_pptr *file_pptr, + const unsigned char *name) +{ + struct xfs_name xname = { + .name = name, + .len = file_pptr->namelen, + }; + struct xfs_parent_rec pptr_rec = { }; + struct xfs_da_args scratch; + + xfs_parent_rec_init(&pptr_rec, file_pptr->parent_ino, + file_pptr->parent_gen); + return -libxfs_parent_unset(ip, ip->i_ino, &xname, &pptr_rec, &scratch); +} + /* Remove all pptrs from @ip. */ static void clear_all_pptrs( @@ -729,7 +767,16 @@ add_missing_parent_ptr( name); } - /* XXX actually do the work */ + error = add_file_pptr(ip, ag_pptr, name); + if (error) + do_error( + _("adding ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"), + (unsigned long long)ip->i_ino, + (unsigned long long)ag_pptr->parent_ino, + ag_pptr->parent_gen, + ag_pptr->namelen, + name, + strerror(error)); } /* Remove @file_pptr from @ip. */ @@ -771,7 +818,16 @@ remove_incorrect_parent_ptr( file_pptr->namelen, name); - /* XXX actually do the work */ + error = remove_file_pptr(ip, file_pptr, name); + if (error) + do_error( + _("removing ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"), + (unsigned long long)ip->i_ino, + (unsigned long long)file_pptr->parent_ino, + file_pptr->parent_gen, + file_pptr->namelen, + name, + strerror(error)); } /* @@ -851,7 +907,33 @@ compare_parent_ptrs( ag_pptr->namelen, name1); - /* XXX do the work */ + /* Remove the parent pointer that we don't want. */ + error = remove_file_pptr(ip, file_pptr, name2); + if (error) + do_error( +_("erasing ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"), + (unsigned long long)ip->i_ino, + (unsigned long long)file_pptr->parent_ino, + file_pptr->parent_gen, + file_pptr->namelen, + name2, + strerror(error)); + + /* + * Add the parent pointer that we do want. It's possible that this + * parent pointer already exists but we haven't gotten that far in the + * scan, so we'll keep going on EEXIST. + */ + error = add_file_pptr(ip, ag_pptr, name1); + if (error && error != EEXIST) + do_error( + _("updating ino %llu pptr (ino %llu gen 0x%x name '%.*s') failed: %s\n"), + (unsigned long long)ip->i_ino, + (unsigned long long)ag_pptr->parent_ino, + ag_pptr->parent_gen, + ag_pptr->namelen, + name1, + strerror(error)); } static int