1613 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2020-2024 Oracle. All Rights Reserved.4 * Author: Darrick J. Wong <djwong@kernel.org>5 */6#include "xfs.h"7#include "xfs_fs.h"8#include "xfs_shared.h"9#include "xfs_format.h"10#include "xfs_trans_resv.h"11#include "xfs_mount.h"12#include "xfs_defer.h"13#include "xfs_bit.h"14#include "xfs_log_format.h"15#include "xfs_trans.h"16#include "xfs_sb.h"17#include "xfs_inode.h"18#include "xfs_icache.h"19#include "xfs_da_format.h"20#include "xfs_da_btree.h"21#include "xfs_dir2.h"22#include "xfs_bmap_btree.h"23#include "xfs_dir2_priv.h"24#include "xfs_trans_space.h"25#include "xfs_health.h"26#include "xfs_exchmaps.h"27#include "xfs_parent.h"28#include "xfs_attr.h"29#include "xfs_bmap.h"30#include "xfs_ag.h"31#include "scrub/xfs_scrub.h"32#include "scrub/scrub.h"33#include "scrub/common.h"34#include "scrub/trace.h"35#include "scrub/repair.h"36#include "scrub/iscan.h"37#include "scrub/findparent.h"38#include "scrub/readdir.h"39#include "scrub/tempfile.h"40#include "scrub/tempexch.h"41#include "scrub/orphanage.h"42#include "scrub/xfile.h"43#include "scrub/xfarray.h"44#include "scrub/xfblob.h"45#include "scrub/attr_repair.h"46#include "scrub/listxattr.h"47 48/*49 * Repairing The Directory Parent Pointer50 * ======================================51 *52 * Currently, only directories support parent pointers (in the form of '..'53 * entries), so we simply scan the filesystem and update the '..' entry.54 *55 * Note that because the only parent pointer is the dotdot entry, we won't56 * touch an unhealthy directory, since the directory repair code is perfectly57 * capable of rebuilding a directory with the proper parent inode.58 *59 * See the section on locking issues in dir_repair.c for more information about60 * conflicts with the VFS. The findparent code wll keep our incore parent61 * inode up to date.62 *63 * If parent pointers are enabled, we instead reconstruct the parent pointer64 * information by visiting every directory entry of every directory in the65 * system and translating the relevant dirents into parent pointers. In this66 * case, it is advantageous to stash all parent pointers created from dirents67 * from a single parent file before replaying them into the temporary file. To68 * save memory, the live filesystem scan reuses the findparent object. Parent69 * pointer repair chooses either directory scanning or findparent, but not70 * both.71 *72 * When salvaging completes, the remaining stashed entries are replayed to the73 * temporary file. All non-parent pointer extended attributes are copied to74 * the temporary file's extended attributes. An atomic file mapping exchange75 * is used to commit the new xattr blocks to the file being repaired. This76 * will disrupt attrmulti cursors.77 */78 79/* Create a parent pointer in the tempfile. */80#define XREP_PPTR_ADD (1)81 82/* Remove a parent pointer from the tempfile. */83#define XREP_PPTR_REMOVE (2)84 85/* A stashed parent pointer update. */86struct xrep_pptr {87 /* Cookie for retrieval of the pptr name. */88 xfblob_cookie name_cookie;89 90 /* Parent pointer record. */91 struct xfs_parent_rec pptr_rec;92 93 /* Length of the pptr name. */94 uint8_t namelen;95 96 /* XREP_PPTR_{ADD,REMOVE} */97 uint8_t action;98};99 100/*101 * Stash up to 8 pages of recovered parent pointers in pptr_recs and102 * pptr_names before we write them to the temp file.103 */104#define XREP_PARENT_MAX_STASH_BYTES (PAGE_SIZE * 8)105 106struct xrep_parent {107 struct xfs_scrub *sc;108 109 /* Fixed-size array of xrep_pptr structures. */110 struct xfarray *pptr_recs;111 112 /* Blobs containing parent pointer names. */113 struct xfblob *pptr_names;114 115 /* xattr keys */116 struct xfarray *xattr_records;117 118 /* xattr values */119 struct xfblob *xattr_blobs;120 121 /* Scratch buffers for saving extended attributes */122 unsigned char *xattr_name;123 void *xattr_value;124 unsigned int xattr_value_sz;125 126 /*127 * Information used to exchange the attr fork mappings, if the fs128 * supports parent pointers.129 */130 struct xrep_tempexch tx;131 132 /*133 * Information used to scan the filesystem to find the inumber of the134 * dotdot entry for this directory. On filesystems without parent135 * pointers, we use the findparent_* functions on this object and136 * access only the parent_ino field directly.137 *138 * When parent pointers are enabled, the directory entry scanner uses139 * the iscan, hooks, and lock fields of this object directly.140 * @pscan.lock coordinates access to pptr_recs, pptr_names, pptr, and141 * pptr_scratch. This reduces the memory requirements of this142 * structure.143 *144 * The lock also controls access to xattr_records and xattr_blobs(?)145 */146 struct xrep_parent_scan_info pscan;147 148 /* Orphanage reparenting request. */149 struct xrep_adoption adoption;150 151 /* Directory entry name, plus the trailing null. */152 struct xfs_name xname;153 unsigned char namebuf[MAXNAMELEN];154 155 /* Scratch buffer for scanning pptr xattrs */156 struct xfs_da_args pptr_args;157 158 /* Have we seen any live updates of parent pointers recently? */159 bool saw_pptr_updates;160 161 /* Number of parents we found after all other repairs */162 unsigned long long parents;163};164 165struct xrep_parent_xattr {166 /* Cookie for retrieval of the xattr name. */167 xfblob_cookie name_cookie;168 169 /* Cookie for retrieval of the xattr value. */170 xfblob_cookie value_cookie;171 172 /* XFS_ATTR_* flags */173 int flags;174 175 /* Length of the value and name. */176 uint32_t valuelen;177 uint16_t namelen;178};179 180/*181 * Stash up to 8 pages of attrs in xattr_records/xattr_blobs before we write182 * them to the temp file.183 */184#define XREP_PARENT_XATTR_MAX_STASH_BYTES (PAGE_SIZE * 8)185 186/* Tear down all the incore stuff we created. */187static void188xrep_parent_teardown(189 struct xrep_parent *rp)190{191 xrep_findparent_scan_teardown(&rp->pscan);192 kvfree(rp->xattr_name);193 rp->xattr_name = NULL;194 kvfree(rp->xattr_value);195 rp->xattr_value = NULL;196 if (rp->xattr_blobs)197 xfblob_destroy(rp->xattr_blobs);198 rp->xattr_blobs = NULL;199 if (rp->xattr_records)200 xfarray_destroy(rp->xattr_records);201 rp->xattr_records = NULL;202 if (rp->pptr_names)203 xfblob_destroy(rp->pptr_names);204 rp->pptr_names = NULL;205 if (rp->pptr_recs)206 xfarray_destroy(rp->pptr_recs);207 rp->pptr_recs = NULL;208}209 210/* Set up for a parent repair. */211int212xrep_setup_parent(213 struct xfs_scrub *sc)214{215 struct xrep_parent *rp;216 int error;217 218 xchk_fsgates_enable(sc, XCHK_FSGATES_DIRENTS);219 220 rp = kvzalloc(sizeof(struct xrep_parent), XCHK_GFP_FLAGS);221 if (!rp)222 return -ENOMEM;223 rp->sc = sc;224 rp->xname.name = rp->namebuf;225 sc->buf = rp;226 227 error = xrep_tempfile_create(sc, S_IFREG);228 if (error)229 return error;230 231 return xrep_orphanage_try_create(sc);232}233 234/*235 * Scan all files in the filesystem for a child dirent that we can turn into236 * the dotdot entry for this directory.237 */238STATIC int239xrep_parent_find_dotdot(240 struct xrep_parent *rp)241{242 struct xfs_scrub *sc = rp->sc;243 xfs_ino_t ino;244 unsigned int sick, checked;245 int error;246 247 /*248 * Avoid sick directories. There shouldn't be anyone else clearing the249 * directory's sick status.250 */251 xfs_inode_measure_sickness(sc->ip, &sick, &checked);252 if (sick & XFS_SICK_INO_DIR)253 return -EFSCORRUPTED;254 255 ino = xrep_findparent_self_reference(sc);256 if (ino != NULLFSINO) {257 xrep_findparent_scan_finish_early(&rp->pscan, ino);258 return 0;259 }260 261 /*262 * Drop the ILOCK on this directory so that we can scan for the dotdot263 * entry. Figure out who is going to be the parent of this directory,264 * then retake the ILOCK so that we can salvage directory entries.265 */266 xchk_iunlock(sc, XFS_ILOCK_EXCL);267 268 /* Does the VFS dcache have an answer for us? */269 ino = xrep_findparent_from_dcache(sc);270 if (ino != NULLFSINO) {271 error = xrep_findparent_confirm(sc, &ino);272 if (!error && ino != NULLFSINO) {273 xrep_findparent_scan_finish_early(&rp->pscan, ino);274 goto out_relock;275 }276 }277 278 /* Scan the entire filesystem for a parent. */279 error = xrep_findparent_scan(&rp->pscan);280out_relock:281 xchk_ilock(sc, XFS_ILOCK_EXCL);282 283 return error;284}285 286/*287 * Add this stashed incore parent pointer to the temporary file.288 * The caller must hold the tempdir's IOLOCK, must not hold any ILOCKs, and289 * must not be in transaction context.290 */291STATIC int292xrep_parent_replay_update(293 struct xrep_parent *rp,294 const struct xfs_name *xname,295 struct xrep_pptr *pptr)296{297 struct xfs_scrub *sc = rp->sc;298 299 switch (pptr->action) {300 case XREP_PPTR_ADD:301 /* Create parent pointer. */302 trace_xrep_parent_replay_parentadd(sc->tempip, xname,303 &pptr->pptr_rec);304 305 return xfs_parent_set(sc->tempip, sc->ip->i_ino, xname,306 &pptr->pptr_rec, &rp->pptr_args);307 case XREP_PPTR_REMOVE:308 /* Remove parent pointer. */309 trace_xrep_parent_replay_parentremove(sc->tempip, xname,310 &pptr->pptr_rec);311 312 return xfs_parent_unset(sc->tempip, sc->ip->i_ino, xname,313 &pptr->pptr_rec, &rp->pptr_args);314 }315 316 ASSERT(0);317 return -EIO;318}319 320/*321 * Flush stashed parent pointer updates that have been recorded by the scanner.322 * This is done to reduce the memory requirements of the parent pointer323 * rebuild, since files can have a lot of hardlinks and the fs can be busy.324 *325 * Caller must not hold transactions or ILOCKs. Caller must hold the tempfile326 * IOLOCK.327 */328STATIC int329xrep_parent_replay_updates(330 struct xrep_parent *rp)331{332 xfarray_idx_t array_cur;333 int error;334 335 mutex_lock(&rp->pscan.lock);336 foreach_xfarray_idx(rp->pptr_recs, array_cur) {337 struct xrep_pptr pptr;338 339 error = xfarray_load(rp->pptr_recs, array_cur, &pptr);340 if (error)341 goto out_unlock;342 343 error = xfblob_loadname(rp->pptr_names, pptr.name_cookie,344 &rp->xname, pptr.namelen);345 if (error)346 goto out_unlock;347 rp->xname.len = pptr.namelen;348 mutex_unlock(&rp->pscan.lock);349 350 error = xrep_parent_replay_update(rp, &rp->xname, &pptr);351 if (error)352 return error;353 354 mutex_lock(&rp->pscan.lock);355 }356 357 /* Empty out both arrays now that we've added the entries. */358 xfarray_truncate(rp->pptr_recs);359 xfblob_truncate(rp->pptr_names);360 mutex_unlock(&rp->pscan.lock);361 return 0;362out_unlock:363 mutex_unlock(&rp->pscan.lock);364 return error;365}366 367/*368 * Remember that we want to create a parent pointer in the tempfile. These369 * stashed actions will be replayed later.370 */371STATIC int372xrep_parent_stash_parentadd(373 struct xrep_parent *rp,374 const struct xfs_name *name,375 const struct xfs_inode *dp)376{377 struct xrep_pptr pptr = {378 .action = XREP_PPTR_ADD,379 .namelen = name->len,380 };381 int error;382 383 trace_xrep_parent_stash_parentadd(rp->sc->tempip, dp, name);384 385 xfs_inode_to_parent_rec(&pptr.pptr_rec, dp);386 error = xfblob_storename(rp->pptr_names, &pptr.name_cookie, name);387 if (error)388 return error;389 390 return xfarray_append(rp->pptr_recs, &pptr);391}392 393/*394 * Remember that we want to remove a parent pointer from the tempfile. These395 * stashed actions will be replayed later.396 */397STATIC int398xrep_parent_stash_parentremove(399 struct xrep_parent *rp,400 const struct xfs_name *name,401 const struct xfs_inode *dp)402{403 struct xrep_pptr pptr = {404 .action = XREP_PPTR_REMOVE,405 .namelen = name->len,406 };407 int error;408 409 trace_xrep_parent_stash_parentremove(rp->sc->tempip, dp, name);410 411 xfs_inode_to_parent_rec(&pptr.pptr_rec, dp);412 error = xfblob_storename(rp->pptr_names, &pptr.name_cookie, name);413 if (error)414 return error;415 416 return xfarray_append(rp->pptr_recs, &pptr);417}418 419/*420 * Examine an entry of a directory. If this dirent leads us back to the file421 * whose parent pointers we're rebuilding, add a pptr to the temporary422 * directory.423 */424STATIC int425xrep_parent_scan_dirent(426 struct xfs_scrub *sc,427 struct xfs_inode *dp,428 xfs_dir2_dataptr_t dapos,429 const struct xfs_name *name,430 xfs_ino_t ino,431 void *priv)432{433 struct xrep_parent *rp = priv;434 int error;435 436 /* Dirent doesn't point to this directory. */437 if (ino != rp->sc->ip->i_ino)438 return 0;439 440 /* No weird looking names. */441 if (name->len == 0 || !xfs_dir2_namecheck(name->name, name->len))442 return -EFSCORRUPTED;443 444 /* No mismatching ftypes. */445 if (name->type != xfs_mode_to_ftype(VFS_I(sc->ip)->i_mode))446 return -EFSCORRUPTED;447 448 /* Don't pick up dot or dotdot entries; we only want child dirents. */449 if (xfs_dir2_samename(name, &xfs_name_dotdot) ||450 xfs_dir2_samename(name, &xfs_name_dot))451 return 0;452 453 /*454 * Transform this dirent into a parent pointer and queue it for later455 * addition to the temporary file.456 */457 mutex_lock(&rp->pscan.lock);458 error = xrep_parent_stash_parentadd(rp, name, dp);459 mutex_unlock(&rp->pscan.lock);460 return error;461}462 463/*464 * Decide if we want to look for dirents in this directory. Skip the file465 * being repaired and any files being used to stage repairs.466 */467static inline bool468xrep_parent_want_scan(469 struct xrep_parent *rp,470 const struct xfs_inode *ip)471{472 return ip != rp->sc->ip && !xrep_is_tempfile(ip);473}474 475/*476 * Take ILOCK on a file that we want to scan.477 *478 * Select ILOCK_EXCL if the file is a directory with an unloaded data bmbt.479 * Otherwise, take ILOCK_SHARED.480 */481static inline unsigned int482xrep_parent_scan_ilock(483 struct xrep_parent *rp,484 struct xfs_inode *ip)485{486 uint lock_mode = XFS_ILOCK_SHARED;487 488 /* Still need to take the shared ILOCK to advance the iscan cursor. */489 if (!xrep_parent_want_scan(rp, ip))490 goto lock;491 492 if (S_ISDIR(VFS_I(ip)->i_mode) && xfs_need_iread_extents(&ip->i_df)) {493 lock_mode = XFS_ILOCK_EXCL;494 goto lock;495 }496 497lock:498 xfs_ilock(ip, lock_mode);499 return lock_mode;500}501 502/*503 * Scan this file for relevant child dirents that point to the file whose504 * parent pointers we're rebuilding.505 */506STATIC int507xrep_parent_scan_file(508 struct xrep_parent *rp,509 struct xfs_inode *ip)510{511 unsigned int lock_mode;512 int error = 0;513 514 lock_mode = xrep_parent_scan_ilock(rp, ip);515 516 if (!xrep_parent_want_scan(rp, ip))517 goto scan_done;518 519 if (S_ISDIR(VFS_I(ip)->i_mode)) {520 /*521 * If the directory looks as though it has been zapped by the522 * inode record repair code, we cannot scan for child dirents.523 */524 if (xchk_dir_looks_zapped(ip)) {525 error = -EBUSY;526 goto scan_done;527 }528 529 error = xchk_dir_walk(rp->sc, ip, xrep_parent_scan_dirent, rp);530 if (error)531 goto scan_done;532 }533 534scan_done:535 xchk_iscan_mark_visited(&rp->pscan.iscan, ip);536 xfs_iunlock(ip, lock_mode);537 return error;538}539 540/* Decide if we've stashed too much pptr data in memory. */541static inline bool542xrep_parent_want_flush_stashed(543 struct xrep_parent *rp)544{545 unsigned long long bytes;546 547 bytes = xfarray_bytes(rp->pptr_recs) + xfblob_bytes(rp->pptr_names);548 return bytes > XREP_PARENT_MAX_STASH_BYTES;549}550 551/*552 * Scan all directories in the filesystem to look for dirents that we can turn553 * into parent pointers.554 */555STATIC int556xrep_parent_scan_dirtree(557 struct xrep_parent *rp)558{559 struct xfs_scrub *sc = rp->sc;560 struct xfs_inode *ip;561 int error;562 563 /*564 * Filesystem scans are time consuming. Drop the file ILOCK and all565 * other resources for the duration of the scan and hope for the best.566 * The live update hooks will keep our scan information up to date.567 */568 xchk_trans_cancel(sc);569 if (sc->ilock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL))570 xchk_iunlock(sc, sc->ilock_flags & (XFS_ILOCK_SHARED |571 XFS_ILOCK_EXCL));572 error = xchk_trans_alloc_empty(sc);573 if (error)574 return error;575 576 while ((error = xchk_iscan_iter(&rp->pscan.iscan, &ip)) == 1) {577 bool flush;578 579 error = xrep_parent_scan_file(rp, ip);580 xchk_irele(sc, ip);581 if (error)582 break;583 584 /* Flush stashed pptr updates to constrain memory usage. */585 mutex_lock(&rp->pscan.lock);586 flush = xrep_parent_want_flush_stashed(rp);587 mutex_unlock(&rp->pscan.lock);588 if (flush) {589 xchk_trans_cancel(sc);590 591 error = xrep_tempfile_iolock_polled(sc);592 if (error)593 break;594 595 error = xrep_parent_replay_updates(rp);596 xrep_tempfile_iounlock(sc);597 if (error)598 break;599 600 error = xchk_trans_alloc_empty(sc);601 if (error)602 break;603 }604 605 if (xchk_should_terminate(sc, &error))606 break;607 }608 xchk_iscan_iter_finish(&rp->pscan.iscan);609 if (error) {610 /*611 * If we couldn't grab an inode that was busy with a state612 * change, change the error code so that we exit to userspace613 * as quickly as possible.614 */615 if (error == -EBUSY)616 return -ECANCELED;617 return error;618 }619 620 /*621 * Retake sc->ip's ILOCK now that we're done flushing stashed parent622 * pointers. We end this function with an empty transaction and the623 * ILOCK.624 */625 xchk_ilock(rp->sc, XFS_ILOCK_EXCL);626 return 0;627}628 629/*630 * Capture dirent updates being made by other threads which are relevant to the631 * file being repaired.632 */633STATIC int634xrep_parent_live_update(635 struct notifier_block *nb,636 unsigned long action,637 void *data)638{639 struct xfs_dir_update_params *p = data;640 struct xrep_parent *rp;641 struct xfs_scrub *sc;642 int error;643 644 rp = container_of(nb, struct xrep_parent, pscan.dhook.dirent_hook.nb);645 sc = rp->sc;646 647 /*648 * This thread updated a dirent that points to the file that we're649 * repairing, so stash the update for replay against the temporary650 * file.651 */652 if (p->ip->i_ino == sc->ip->i_ino &&653 xchk_iscan_want_live_update(&rp->pscan.iscan, p->dp->i_ino)) {654 mutex_lock(&rp->pscan.lock);655 if (p->delta > 0)656 error = xrep_parent_stash_parentadd(rp, p->name, p->dp);657 else658 error = xrep_parent_stash_parentremove(rp, p->name,659 p->dp);660 if (!error)661 rp->saw_pptr_updates = true;662 mutex_unlock(&rp->pscan.lock);663 if (error)664 goto out_abort;665 }666 667 return NOTIFY_DONE;668out_abort:669 xchk_iscan_abort(&rp->pscan.iscan);670 return NOTIFY_DONE;671}672 673/* Reset a directory's dotdot entry, if needed. */674STATIC int675xrep_parent_reset_dotdot(676 struct xrep_parent *rp)677{678 struct xfs_scrub *sc = rp->sc;679 xfs_ino_t ino;680 unsigned int spaceres;681 int error = 0;682 683 ASSERT(sc->ilock_flags & XFS_ILOCK_EXCL);684 685 error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot, &ino);686 if (error || ino == rp->pscan.parent_ino)687 return error;688 689 xfs_trans_ijoin(sc->tp, sc->ip, 0);690 691 trace_xrep_parent_reset_dotdot(sc->ip, rp->pscan.parent_ino);692 693 /*694 * Reserve more space just in case we have to expand the dir. We're695 * allowed to exceed quota to repair inconsistent metadata.696 */697 spaceres = xfs_rename_space_res(sc->mp, 0, false, xfs_name_dotdot.len,698 false);699 error = xfs_trans_reserve_more_inode(sc->tp, sc->ip, spaceres, 0,700 true);701 if (error)702 return error;703 704 error = xfs_dir_replace(sc->tp, sc->ip, &xfs_name_dotdot,705 rp->pscan.parent_ino, spaceres);706 if (error)707 return error;708 709 /*710 * Roll transaction to detach the inode from the transaction but retain711 * ILOCK_EXCL.712 */713 return xfs_trans_roll(&sc->tp);714}715 716/* Pass back the parent inumber if this a parent pointer */717STATIC int718xrep_parent_lookup_pptr(719 struct xfs_scrub *sc,720 struct xfs_inode *ip,721 unsigned int attr_flags,722 const unsigned char *name,723 unsigned int namelen,724 const void *value,725 unsigned int valuelen,726 void *priv)727{728 xfs_ino_t *inop = priv;729 xfs_ino_t parent_ino;730 int error;731 732 if (!(attr_flags & XFS_ATTR_PARENT))733 return 0;734 735 error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,736 valuelen, &parent_ino, NULL);737 if (error)738 return error;739 740 *inop = parent_ino;741 return -ECANCELED;742}743 744/*745 * Find the first parent of the scrub target by walking parent pointers for746 * the purpose of deciding if we're going to move it to the orphanage.747 * We don't care if the attr fork is zapped.748 */749STATIC int750xrep_parent_lookup_pptrs(751 struct xfs_scrub *sc,752 xfs_ino_t *inop)753{754 int error;755 756 *inop = NULLFSINO;757 758 error = xchk_xattr_walk(sc, sc->ip, xrep_parent_lookup_pptr, NULL,759 inop);760 if (error && error != -ECANCELED)761 return error;762 return 0;763}764 765/*766 * Move the current file to the orphanage.767 *768 * Caller must hold IOLOCK_EXCL on @sc->ip, and no other inode locks. Upon769 * successful return, the scrub transaction will have enough extra reservation770 * to make the move; it will hold IOLOCK_EXCL and ILOCK_EXCL of @sc->ip and the771 * orphanage; and both inodes will be ijoined.772 */773STATIC int774xrep_parent_move_to_orphanage(775 struct xrep_parent *rp)776{777 struct xfs_scrub *sc = rp->sc;778 xfs_ino_t orig_parent, new_parent;779 int error;780 781 if (S_ISDIR(VFS_I(sc->ip)->i_mode)) {782 /*783 * We are about to drop the ILOCK on sc->ip to lock the784 * orphanage and prepare for the adoption. Therefore, look up785 * the old dotdot entry for sc->ip so that we can compare it786 * after we re-lock sc->ip.787 */788 error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot,789 &orig_parent);790 if (error)791 return error;792 } else {793 /*794 * We haven't dropped the ILOCK since we committed the new795 * xattr structure (and hence the new parent pointer records),796 * which means that the file cannot have been moved in the797 * directory tree, and there are no parents.798 */799 orig_parent = NULLFSINO;800 }801 802 /*803 * Drop the ILOCK on the scrub target and commit the transaction.804 * Adoption computes its own resource requirements and gathers the805 * necessary components.806 */807 error = xrep_trans_commit(sc);808 if (error)809 return error;810 xchk_iunlock(sc, XFS_ILOCK_EXCL);811 812 /* If we can take the orphanage's iolock then we're ready to move. */813 if (!xrep_orphanage_ilock_nowait(sc, XFS_IOLOCK_EXCL)) {814 xchk_iunlock(sc, sc->ilock_flags);815 error = xrep_orphanage_iolock_two(sc);816 if (error)817 return error;818 }819 820 /* Grab transaction and ILOCK the two files. */821 error = xrep_adoption_trans_alloc(sc, &rp->adoption);822 if (error)823 return error;824 825 error = xrep_adoption_compute_name(&rp->adoption, &rp->xname);826 if (error)827 return error;828 829 /*830 * Now that we've reacquired the ILOCK on sc->ip, look up the dotdot831 * entry again. If the parent changed or the child was unlinked while832 * the child directory was unlocked, we don't need to move the child to833 * the orphanage after all. For a non-directory, we have to scan for834 * the first parent pointer to see if one has been added.835 */836 if (S_ISDIR(VFS_I(sc->ip)->i_mode))837 error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot,838 &new_parent);839 else840 error = xrep_parent_lookup_pptrs(sc, &new_parent);841 if (error)842 return error;843 844 /*845 * Attach to the orphanage if we still have a linked directory and it846 * hasn't been moved.847 */848 if (orig_parent == new_parent && VFS_I(sc->ip)->i_nlink > 0) {849 error = xrep_adoption_move(&rp->adoption);850 if (error)851 return error;852 }853 854 /*855 * Launder the scrub transaction so we can drop the orphanage ILOCK856 * and IOLOCK. Return holding the scrub target's ILOCK and IOLOCK.857 */858 error = xrep_adoption_trans_roll(&rp->adoption);859 if (error)860 return error;861 862 xrep_orphanage_iunlock(sc, XFS_ILOCK_EXCL);863 xrep_orphanage_iunlock(sc, XFS_IOLOCK_EXCL);864 return 0;865}866 867/* Ensure that the xattr value buffer is large enough. */868STATIC int869xrep_parent_alloc_xattr_value(870 struct xrep_parent *rp,871 size_t bufsize)872{873 void *new_val;874 875 if (rp->xattr_value_sz >= bufsize)876 return 0;877 878 if (rp->xattr_value) {879 kvfree(rp->xattr_value);880 rp->xattr_value = NULL;881 rp->xattr_value_sz = 0;882 }883 884 new_val = kvmalloc(bufsize, XCHK_GFP_FLAGS);885 if (!new_val)886 return -ENOMEM;887 888 rp->xattr_value = new_val;889 rp->xattr_value_sz = bufsize;890 return 0;891}892 893/* Retrieve the (remote) value of a non-pptr xattr. */894STATIC int895xrep_parent_fetch_xattr_remote(896 struct xrep_parent *rp,897 struct xfs_inode *ip,898 unsigned int attr_flags,899 const unsigned char *name,900 unsigned int namelen,901 unsigned int valuelen)902{903 struct xfs_scrub *sc = rp->sc;904 struct xfs_da_args args = {905 .attr_filter = attr_flags & XFS_ATTR_NSP_ONDISK_MASK,906 .geo = sc->mp->m_attr_geo,907 .whichfork = XFS_ATTR_FORK,908 .dp = ip,909 .name = name,910 .namelen = namelen,911 .trans = sc->tp,912 .valuelen = valuelen,913 .owner = ip->i_ino,914 };915 int error;916 917 /*918 * If we need a larger value buffer, try to allocate one. If that919 * fails, return with -EDEADLOCK to try harder.920 */921 error = xrep_parent_alloc_xattr_value(rp, valuelen);922 if (error == -ENOMEM)923 return -EDEADLOCK;924 if (error)925 return error;926 927 args.value = rp->xattr_value;928 xfs_attr_sethash(&args);929 return xfs_attr_get_ilocked(&args);930}931 932/* Stash non-pptr attributes for later replay into the temporary file. */933STATIC int934xrep_parent_stash_xattr(935 struct xfs_scrub *sc,936 struct xfs_inode *ip,937 unsigned int attr_flags,938 const unsigned char *name,939 unsigned int namelen,940 const void *value,941 unsigned int valuelen,942 void *priv)943{944 struct xrep_parent_xattr key = {945 .valuelen = valuelen,946 .namelen = namelen,947 .flags = attr_flags & XFS_ATTR_NSP_ONDISK_MASK,948 };949 struct xrep_parent *rp = priv;950 int error;951 952 if (attr_flags & (XFS_ATTR_INCOMPLETE | XFS_ATTR_PARENT))953 return 0;954 955 if (!value) {956 error = xrep_parent_fetch_xattr_remote(rp, ip, attr_flags,957 name, namelen, valuelen);958 if (error)959 return error;960 961 value = rp->xattr_value;962 }963 964 trace_xrep_parent_stash_xattr(rp->sc->tempip, key.flags, (void *)name,965 key.namelen, key.valuelen);966 967 error = xfblob_store(rp->xattr_blobs, &key.name_cookie, name,968 key.namelen);969 if (error)970 return error;971 972 error = xfblob_store(rp->xattr_blobs, &key.value_cookie, value,973 key.valuelen);974 if (error)975 return error;976 977 return xfarray_append(rp->xattr_records, &key);978}979 980/* Insert one xattr key/value. */981STATIC int982xrep_parent_insert_xattr(983 struct xrep_parent *rp,984 const struct xrep_parent_xattr *key)985{986 struct xfs_da_args args = {987 .dp = rp->sc->tempip,988 .attr_filter = key->flags,989 .namelen = key->namelen,990 .valuelen = key->valuelen,991 .owner = rp->sc->ip->i_ino,992 .geo = rp->sc->mp->m_attr_geo,993 .whichfork = XFS_ATTR_FORK,994 .op_flags = XFS_DA_OP_OKNOENT,995 };996 int error;997 998 ASSERT(!(key->flags & XFS_ATTR_PARENT));999 1000 /*1001 * Grab pointers to the scrub buffer so that we can use them to insert1002 * attrs into the temp file.1003 */1004 args.name = rp->xattr_name;1005 args.value = rp->xattr_value;1006 1007 /*1008 * The attribute name is stored near the end of the in-core buffer,1009 * though we reserve one more byte to ensure null termination.1010 */1011 rp->xattr_name[XATTR_NAME_MAX] = 0;1012 1013 error = xfblob_load(rp->xattr_blobs, key->name_cookie, rp->xattr_name,1014 key->namelen);1015 if (error)1016 return error;1017 1018 error = xfblob_free(rp->xattr_blobs, key->name_cookie);1019 if (error)1020 return error;1021 1022 error = xfblob_load(rp->xattr_blobs, key->value_cookie, args.value,1023 key->valuelen);1024 if (error)1025 return error;1026 1027 error = xfblob_free(rp->xattr_blobs, key->value_cookie);1028 if (error)1029 return error;1030 1031 rp->xattr_name[key->namelen] = 0;1032 1033 trace_xrep_parent_insert_xattr(rp->sc->tempip, key->flags,1034 rp->xattr_name, key->namelen, key->valuelen);1035 1036 xfs_attr_sethash(&args);1037 return xfs_attr_set(&args, XFS_ATTRUPDATE_UPSERT, false);1038}1039 1040/*1041 * Periodically flush salvaged attributes to the temporary file. This is done1042 * to reduce the memory requirements of the xattr rebuild because files can1043 * contain millions of attributes.1044 */1045STATIC int1046xrep_parent_flush_xattrs(1047 struct xrep_parent *rp)1048{1049 xfarray_idx_t array_cur;1050 int error;1051 1052 /*1053 * Entering this function, the scrub context has a reference to the1054 * inode being repaired, the temporary file, and the empty scrub1055 * transaction that we created for the xattr scan. We hold ILOCK_EXCL1056 * on the inode being repaired.1057 *1058 * To constrain kernel memory use, we occasionally flush salvaged1059 * xattrs from the xfarray and xfblob structures into the temporary1060 * file in preparation for exchanging the xattr structures at the end.1061 * Updating the temporary file requires a transaction, so we commit the1062 * scrub transaction and drop the ILOCK so that xfs_attr_set can1063 * allocate whatever transaction it wants.1064 *1065 * We still hold IOLOCK_EXCL on the inode being repaired, which1066 * prevents anyone from adding xattrs (or parent pointers) while we're1067 * flushing.1068 */1069 xchk_trans_cancel(rp->sc);1070 xchk_iunlock(rp->sc, XFS_ILOCK_EXCL);1071 1072 /*1073 * Take the IOLOCK of the temporary file while we modify xattrs. This1074 * isn't strictly required because the temporary file is never revealed1075 * to userspace, but we follow the same locking rules. We still hold1076 * sc->ip's IOLOCK.1077 */1078 error = xrep_tempfile_iolock_polled(rp->sc);1079 if (error)1080 return error;1081 1082 /* Add all the salvaged attrs to the temporary file. */1083 foreach_xfarray_idx(rp->xattr_records, array_cur) {1084 struct xrep_parent_xattr key;1085 1086 error = xfarray_load(rp->xattr_records, array_cur, &key);1087 if (error)1088 return error;1089 1090 error = xrep_parent_insert_xattr(rp, &key);1091 if (error)1092 return error;1093 }1094 1095 /* Empty out both arrays now that we've added the entries. */1096 xfarray_truncate(rp->xattr_records);1097 xfblob_truncate(rp->xattr_blobs);1098 1099 xrep_tempfile_iounlock(rp->sc);1100 1101 /* Recreate the empty transaction and relock the inode. */1102 error = xchk_trans_alloc_empty(rp->sc);1103 if (error)1104 return error;1105 xchk_ilock(rp->sc, XFS_ILOCK_EXCL);1106 return 0;1107}1108 1109/* Decide if we've stashed too much xattr data in memory. */1110static inline bool1111xrep_parent_want_flush_xattrs(1112 struct xrep_parent *rp)1113{1114 unsigned long long bytes;1115 1116 bytes = xfarray_bytes(rp->xattr_records) +1117 xfblob_bytes(rp->xattr_blobs);1118 return bytes > XREP_PARENT_XATTR_MAX_STASH_BYTES;1119}1120 1121/* Flush staged attributes to the temporary file if we're over the limit. */1122STATIC int1123xrep_parent_try_flush_xattrs(1124 struct xfs_scrub *sc,1125 void *priv)1126{1127 struct xrep_parent *rp = priv;1128 int error;1129 1130 if (!xrep_parent_want_flush_xattrs(rp))1131 return 0;1132 1133 error = xrep_parent_flush_xattrs(rp);1134 if (error)1135 return error;1136 1137 /*1138 * If there were any parent pointer updates to the xattr structure1139 * while we dropped the ILOCK, the xattr structure is now stale.1140 * Signal to the attr copy process that we need to start over, but1141 * this time without opportunistic attr flushing.1142 *1143 * This is unlikely to happen, so we're ok with restarting the copy.1144 */1145 mutex_lock(&rp->pscan.lock);1146 if (rp->saw_pptr_updates)1147 error = -ESTALE;1148 mutex_unlock(&rp->pscan.lock);1149 return error;1150}1151 1152/* Copy all the non-pptr extended attributes into the temporary file. */1153STATIC int1154xrep_parent_copy_xattrs(1155 struct xrep_parent *rp)1156{1157 struct xfs_scrub *sc = rp->sc;1158 int error;1159 1160 /*1161 * Clear the pptr updates flag. We hold sc->ip ILOCKed, so there1162 * can't be any parent pointer updates in progress.1163 */1164 mutex_lock(&rp->pscan.lock);1165 rp->saw_pptr_updates = false;1166 mutex_unlock(&rp->pscan.lock);1167 1168 /* Copy xattrs, stopping periodically to flush the incore buffers. */1169 error = xchk_xattr_walk(sc, sc->ip, xrep_parent_stash_xattr,1170 xrep_parent_try_flush_xattrs, rp);1171 if (error && error != -ESTALE)1172 return error;1173 1174 if (error == -ESTALE) {1175 /*1176 * The xattr copy collided with a parent pointer update.1177 * Restart the copy, but this time hold the ILOCK all the way1178 * to the end to lock out any directory parent pointer updates.1179 */1180 error = xchk_xattr_walk(sc, sc->ip, xrep_parent_stash_xattr,1181 NULL, rp);1182 if (error)1183 return error;1184 }1185 1186 /* Flush any remaining stashed xattrs to the temporary file. */1187 if (xfarray_bytes(rp->xattr_records) == 0)1188 return 0;1189 1190 return xrep_parent_flush_xattrs(rp);1191}1192 1193/*1194 * Ensure that @sc->ip and @sc->tempip both have attribute forks before we head1195 * into the attr fork exchange transaction. All files on a filesystem with1196 * parent pointers must have an attr fork because the parent pointer code does1197 * not itself add attribute forks.1198 *1199 * Note: Unlinkable unlinked files don't need one, but the overhead of having1200 * an unnecessary attr fork is not justified by the additional code complexity1201 * that would be needed to track that state correctly.1202 */1203STATIC int1204xrep_parent_ensure_attr_fork(1205 struct xrep_parent *rp)1206{1207 struct xfs_scrub *sc = rp->sc;1208 int error;1209 1210 error = xfs_attr_add_fork(sc->tempip,1211 sizeof(struct xfs_attr_sf_hdr), 1);1212 if (error)1213 return error;1214 return xfs_attr_add_fork(sc->ip, sizeof(struct xfs_attr_sf_hdr), 1);1215}1216 1217/*1218 * Finish replaying stashed parent pointer updates, allocate a transaction for1219 * exchanging extent mappings, and take the ILOCKs of both files before we1220 * commit the new attribute structure.1221 */1222STATIC int1223xrep_parent_finalize_tempfile(1224 struct xrep_parent *rp)1225{1226 struct xfs_scrub *sc = rp->sc;1227 int error;1228 1229 /*1230 * Repair relies on the ILOCK to quiesce all possible xattr updates.1231 * Replay all queued parent pointer updates into the tempfile before1232 * exchanging the contents, even if that means dropping the ILOCKs and1233 * the transaction.1234 */1235 do {1236 error = xrep_parent_replay_updates(rp);1237 if (error)1238 return error;1239 1240 error = xrep_parent_ensure_attr_fork(rp);1241 if (error)1242 return error;1243 1244 error = xrep_tempexch_trans_alloc(sc, XFS_ATTR_FORK, &rp->tx);1245 if (error)1246 return error;1247 1248 if (xfarray_length(rp->pptr_recs) == 0)1249 break;1250 1251 xchk_trans_cancel(sc);1252 xrep_tempfile_iunlock_both(sc);1253 } while (!xchk_should_terminate(sc, &error));1254 return error;1255}1256 1257/*1258 * Replay all the stashed parent pointers into the temporary file, copy all1259 * the non-pptr xattrs from the file being repaired into the temporary file,1260 * and exchange the attr fork contents atomically.1261 */1262STATIC int1263xrep_parent_rebuild_pptrs(1264 struct xrep_parent *rp)1265{1266 struct xfs_scrub *sc = rp->sc;1267 xfs_ino_t parent_ino = NULLFSINO;1268 int error;1269 1270 /*1271 * Copy non-ppttr xattrs from the file being repaired into the1272 * temporary file's xattr structure. We hold sc->ip's IOLOCK, which1273 * prevents setxattr/removexattr calls from occurring, but renames1274 * update the parent pointers without holding IOLOCK. If we detect1275 * stale attr structures, we restart the scan but only flush at the1276 * end.1277 */1278 error = xrep_parent_copy_xattrs(rp);1279 if (error)1280 return error;1281 1282 /*1283 * Cancel the empty transaction that we used to walk and copy attrs,1284 * and drop the ILOCK so that we can take the IOLOCK on the temporary1285 * file. We still hold sc->ip's IOLOCK.1286 */1287 xchk_trans_cancel(sc);1288 xchk_iunlock(sc, XFS_ILOCK_EXCL);1289 1290 error = xrep_tempfile_iolock_polled(sc);1291 if (error)1292 return error;1293 1294 /*1295 * Allocate transaction, lock inodes, and make sure that we've replayed1296 * all the stashed pptr updates to the tempdir. After this point,1297 * we're ready to exchange the attr fork mappings.1298 */1299 error = xrep_parent_finalize_tempfile(rp);1300 if (error)1301 return error;1302 1303 /* Last chance to abort before we start committing pptr fixes. */1304 if (xchk_should_terminate(sc, &error))1305 return error;1306 1307 if (xchk_iscan_aborted(&rp->pscan.iscan))1308 return -ECANCELED;1309 1310 /*1311 * Exchange the attr fork contents and junk the old attr fork contents,1312 * which are now in the tempfile.1313 */1314 error = xrep_xattr_swap(sc, &rp->tx);1315 if (error)1316 return error;1317 error = xrep_xattr_reset_tempfile_fork(sc);1318 if (error)1319 return error;1320 1321 /*1322 * Roll to get a transaction without any inodes joined to it. Then we1323 * can drop the tempfile's ILOCK and IOLOCK before doing more work on1324 * the scrub target file.1325 */1326 error = xfs_trans_roll(&sc->tp);1327 if (error)1328 return error;1329 xrep_tempfile_iunlock(sc);1330 xrep_tempfile_iounlock(sc);1331 1332 /*1333 * We've committed the new parent pointers. Find at least one parent1334 * so that we can decide if we're moving this file to the orphanage.1335 * For this purpose, root directories are their own parents.1336 */1337 if (sc->ip == sc->mp->m_rootip) {1338 xrep_findparent_scan_found(&rp->pscan, sc->ip->i_ino);1339 } else {1340 error = xrep_parent_lookup_pptrs(sc, &parent_ino);1341 if (error)1342 return error;1343 if (parent_ino != NULLFSINO)1344 xrep_findparent_scan_found(&rp->pscan, parent_ino);1345 }1346 return 0;1347}1348 1349/*1350 * Commit the new parent pointer structure (currently only the dotdot entry) to1351 * the file that we're repairing.1352 */1353STATIC int1354xrep_parent_rebuild_tree(1355 struct xrep_parent *rp)1356{1357 int error;1358 1359 if (xfs_has_parent(rp->sc->mp)) {1360 error = xrep_parent_rebuild_pptrs(rp);1361 if (error)1362 return error;1363 }1364 1365 if (rp->pscan.parent_ino == NULLFSINO) {1366 if (xrep_orphanage_can_adopt(rp->sc))1367 return xrep_parent_move_to_orphanage(rp);1368 return -EFSCORRUPTED;1369 }1370 1371 if (S_ISDIR(VFS_I(rp->sc->ip)->i_mode))1372 return xrep_parent_reset_dotdot(rp);1373 1374 return 0;1375}1376 1377/* Count the number of parent pointers. */1378STATIC int1379xrep_parent_count_pptr(1380 struct xfs_scrub *sc,1381 struct xfs_inode *ip,1382 unsigned int attr_flags,1383 const unsigned char *name,1384 unsigned int namelen,1385 const void *value,1386 unsigned int valuelen,1387 void *priv)1388{1389 struct xrep_parent *rp = priv;1390 int error;1391 1392 if (!(attr_flags & XFS_ATTR_PARENT))1393 return 0;1394 1395 error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,1396 valuelen, NULL, NULL);1397 if (error)1398 return error;1399 1400 rp->parents++;1401 return 0;1402}1403 1404/*1405 * After all parent pointer rebuilding and adoption activity completes, reset1406 * the link count of this nondirectory, having scanned the fs to rebuild all1407 * parent pointers.1408 */1409STATIC int1410xrep_parent_set_nondir_nlink(1411 struct xrep_parent *rp)1412{1413 struct xfs_scrub *sc = rp->sc;1414 struct xfs_inode *ip = sc->ip;1415 struct xfs_perag *pag;1416 bool joined = false;1417 int error;1418 1419 /* Count parent pointers so we can reset the file link count. */1420 rp->parents = 0;1421 error = xchk_xattr_walk(sc, ip, xrep_parent_count_pptr, NULL, rp);1422 if (error)1423 return error;1424 1425 if (rp->parents > 0 && xfs_inode_on_unlinked_list(ip)) {1426 xfs_trans_ijoin(sc->tp, sc->ip, 0);1427 joined = true;1428 1429 /*1430 * The file is on the unlinked list but we found parents.1431 * Remove the file from the unlinked list.1432 */1433 pag = xfs_perag_get(sc->mp, XFS_INO_TO_AGNO(sc->mp, ip->i_ino));1434 if (!pag) {1435 ASSERT(0);1436 return -EFSCORRUPTED;1437 }1438 1439 error = xfs_iunlink_remove(sc->tp, pag, ip);1440 xfs_perag_put(pag);1441 if (error)1442 return error;1443 } else if (rp->parents == 0 && !xfs_inode_on_unlinked_list(ip)) {1444 xfs_trans_ijoin(sc->tp, sc->ip, 0);1445 joined = true;1446 1447 /*1448 * The file is not on the unlinked list but we found no1449 * parents. Add the file to the unlinked list.1450 */1451 error = xfs_iunlink(sc->tp, ip);1452 if (error)1453 return error;1454 }1455 1456 /* Set the correct link count. */1457 if (VFS_I(ip)->i_nlink != rp->parents) {1458 if (!joined) {1459 xfs_trans_ijoin(sc->tp, sc->ip, 0);1460 joined = true;1461 }1462 1463 set_nlink(VFS_I(ip), min_t(unsigned long long, rp->parents,1464 XFS_NLINK_PINNED));1465 }1466 1467 /* Log the inode to keep it moving forward if we dirtied anything. */1468 if (joined)1469 xfs_trans_log_inode(sc->tp, ip, XFS_ILOG_CORE);1470 return 0;1471}1472 1473/* Set up the filesystem scan so we can look for parents. */1474STATIC int1475xrep_parent_setup_scan(1476 struct xrep_parent *rp)1477{1478 struct xfs_scrub *sc = rp->sc;1479 char *descr;1480 struct xfs_da_geometry *geo = sc->mp->m_attr_geo;1481 int max_len;1482 int error;1483 1484 if (!xfs_has_parent(sc->mp))1485 return xrep_findparent_scan_start(sc, &rp->pscan);1486 1487 /* Buffers for copying non-pptr attrs to the tempfile */1488 rp->xattr_name = kvmalloc(XATTR_NAME_MAX + 1, XCHK_GFP_FLAGS);1489 if (!rp->xattr_name)1490 return -ENOMEM;1491 1492 /*1493 * Allocate enough memory to handle loading local attr values from the1494 * xfblob data while flushing stashed attrs to the temporary file.1495 * We only realloc the buffer when salvaging remote attr values, so1496 * TRY_HARDER means we allocate the maximal attr value size.1497 */1498 if (sc->flags & XCHK_TRY_HARDER)1499 max_len = XATTR_SIZE_MAX;1500 else1501 max_len = xfs_attr_leaf_entsize_local_max(geo->blksize);1502 error = xrep_parent_alloc_xattr_value(rp, max_len);1503 if (error)1504 goto out_xattr_name;1505 1506 /* Set up some staging memory for logging parent pointer updates. */1507 descr = xchk_xfile_ino_descr(sc, "parent pointer entries");1508 error = xfarray_create(descr, 0, sizeof(struct xrep_pptr),1509 &rp->pptr_recs);1510 kfree(descr);1511 if (error)1512 goto out_xattr_value;1513 1514 descr = xchk_xfile_ino_descr(sc, "parent pointer names");1515 error = xfblob_create(descr, &rp->pptr_names);1516 kfree(descr);1517 if (error)1518 goto out_recs;1519 1520 /* Set up some storage for copying attrs before the mapping exchange */1521 descr = xchk_xfile_ino_descr(sc,1522 "parent pointer retained xattr entries");1523 error = xfarray_create(descr, 0, sizeof(struct xrep_parent_xattr),1524 &rp->xattr_records);1525 kfree(descr);1526 if (error)1527 goto out_names;1528 1529 descr = xchk_xfile_ino_descr(sc,1530 "parent pointer retained xattr values");1531 error = xfblob_create(descr, &rp->xattr_blobs);1532 kfree(descr);1533 if (error)1534 goto out_attr_keys;1535 1536 error = __xrep_findparent_scan_start(sc, &rp->pscan,1537 xrep_parent_live_update);1538 if (error)1539 goto out_attr_values;1540 1541 return 0;1542 1543out_attr_values:1544 xfblob_destroy(rp->xattr_blobs);1545 rp->xattr_blobs = NULL;1546out_attr_keys:1547 xfarray_destroy(rp->xattr_records);1548 rp->xattr_records = NULL;1549out_names:1550 xfblob_destroy(rp->pptr_names);1551 rp->pptr_names = NULL;1552out_recs:1553 xfarray_destroy(rp->pptr_recs);1554 rp->pptr_recs = NULL;1555out_xattr_value:1556 kvfree(rp->xattr_value);1557 rp->xattr_value = NULL;1558out_xattr_name:1559 kvfree(rp->xattr_name);1560 rp->xattr_name = NULL;1561 return error;1562}1563 1564int1565xrep_parent(1566 struct xfs_scrub *sc)1567{1568 struct xrep_parent *rp = sc->buf;1569 int error;1570 1571 /*1572 * When the parent pointers feature is enabled, repairs are committed1573 * by atomically committing a new xattr structure and reaping the old1574 * attr fork. Reaping requires rmap and exchange-range to be enabled.1575 */1576 if (xfs_has_parent(sc->mp)) {1577 if (!xfs_has_rmapbt(sc->mp))1578 return -EOPNOTSUPP;1579 if (!xfs_has_exchange_range(sc->mp))1580 return -EOPNOTSUPP;1581 }1582 1583 error = xrep_parent_setup_scan(rp);1584 if (error)1585 return error;1586 1587 if (xfs_has_parent(sc->mp))1588 error = xrep_parent_scan_dirtree(rp);1589 else1590 error = xrep_parent_find_dotdot(rp);1591 if (error)1592 goto out_teardown;1593 1594 /* Last chance to abort before we start committing dotdot fixes. */1595 if (xchk_should_terminate(sc, &error))1596 goto out_teardown;1597 1598 error = xrep_parent_rebuild_tree(rp);1599 if (error)1600 goto out_teardown;1601 if (xfs_has_parent(sc->mp) && !S_ISDIR(VFS_I(sc->ip)->i_mode)) {1602 error = xrep_parent_set_nondir_nlink(rp);1603 if (error)1604 goto out_teardown;1605 }1606 1607 error = xrep_defer_finish(sc);1608 1609out_teardown:1610 xrep_parent_teardown(rp);1611 return error;1612}1613