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 | 85 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 795df630d76..5f87d2be8d8 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -184,9 +184,11 @@ #define xfs_parent_irec_from_disk libxfs_parent_irec_from_disk #define xfs_parent_irec_hashname libxfs_parent_irec_hashname #define xfs_parent_lookup libxfs_parent_lookup +#define xfs_parent_set libxfs_parent_set #define xfs_parent_start libxfs_parent_start #define xfs_parent_namecheck libxfs_parent_namecheck #define xfs_parent_valuecheck libxfs_parent_valuecheck +#define xfs_parent_unset libxfs_parent_unset #define xfs_perag_get libxfs_perag_get #define xfs_perag_put libxfs_perag_put #define xfs_prealloc_blocks libxfs_prealloc_blocks diff --git a/repair/pptr.c b/repair/pptr.c index dcd7c7574ff..ae5cc260e1f 100644 --- a/repair/pptr.c +++ b/repair/pptr.c @@ -677,6 +677,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_parent_name_irec pptr_rec = { + .p_ino = ag_pptr->parent_ino, + .p_gen = ag_pptr->parent_gen, + .p_namelen = ag_pptr->namelen, + }; + struct xfs_parent_scratch scratch; + + memcpy(pptr_rec.p_name, name, ag_pptr->namelen); + libxfs_parent_irec_hashname(ip->i_mount, &pptr_rec); + return -libxfs_parent_set(ip, ip->i_ino, &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_parent_name_irec pptr_rec = { + .p_ino = file_pptr->parent_ino, + .p_gen = file_pptr->parent_gen, + .p_namelen = file_pptr->namelen, + }; + struct xfs_parent_scratch scratch; + + memcpy(pptr_rec.p_name, name, file_pptr->namelen); + libxfs_parent_irec_hashname(ip->i_mount, &pptr_rec); + return -libxfs_parent_unset(ip, ip->i_ino, &pptr_rec, &scratch); +} + /* Remove all pptrs from @ip. */ static void clear_all_pptrs( @@ -733,7 +771,16 @@ add_missing_parent_ptr( ag_pptr->namelen, 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. */ @@ -775,7 +822,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)); } /* @@ -847,7 +903,30 @@ compare_parent_ptrs( ag_pptr->namelen, name1); - /* XXX do the work */ + if (ag_pptr->parent_gen != file_pptr->parent_gen || + ag_pptr->namehash != file_pptr->namehash) { + 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)); + } + + error = add_file_pptr(ip, ag_pptr, name1); + if (error) + 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