brintos

brintos / linux-shallow public Read only

0
0
Text · 40.5 KiB · 7b42b7f Raw
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