Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * Copyright (C) 2021-2023 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_log_format.h"
13 : #include "xfs_trans.h"
14 : #include "xfs_inode.h"
15 : #include "xfs_ialloc.h"
16 : #include "xfs_quota.h"
17 : #include "xfs_trans_space.h"
18 : #include "xfs_dir2.h"
19 : #include "xfs_icache.h"
20 : #include "xfs_bmap.h"
21 : #include "xfs_bmap_btree.h"
22 : #include "xfs_parent.h"
23 : #include "xfs_da_format.h"
24 : #include "xfs_da_btree.h"
25 : #include "xfs_xattr.h"
26 : #include "xfs_attr_sf.h"
27 : #include "scrub/scrub.h"
28 : #include "scrub/common.h"
29 : #include "scrub/repair.h"
30 : #include "scrub/trace.h"
31 : #include "scrub/orphanage.h"
32 : #include "scrub/readdir.h"
33 :
34 : #include <linux/namei.h>
35 :
36 : /* Make the orphanage owned by root. */
37 5141593 : STATIC int
38 : xrep_chown_orphanage(
39 : struct xfs_scrub *sc,
40 : struct xfs_inode *dp)
41 5141593 : {
42 5141593 : struct xfs_trans *tp;
43 5141593 : struct xfs_mount *mp = sc->mp;
44 5141593 : struct xfs_dquot *udqp = NULL, *gdqp = NULL, *pdqp = NULL;
45 5141593 : struct xfs_dquot *oldu = NULL, *oldg = NULL, *oldp = NULL;
46 5141593 : struct inode *inode = VFS_I(dp);
47 : int error;
48 5141593 :
49 : error = xfs_qm_vop_dqalloc(dp, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, 0,
50 5141593 : XFS_QMOPT_QUOTALL, &udqp, &gdqp, &pdqp);
51 : if (error)
52 : return error;
53 5141593 :
54 5141593 : error = xfs_trans_alloc_ichange(dp, udqp, gdqp, pdqp, true, &tp);
55 0 : if (error)
56 : goto out_dqrele;
57 :
58 : /*
59 : * Always clear setuid/setgid on the orphanage since we don't normally
60 : * want that functionality on this directory and xfs_repair doesn't
61 : * create it this way either. Leave the other access bits unchanged.
62 5141593 : */
63 : inode->i_mode &= ~(S_ISUID | S_ISGID);
64 :
65 : /*
66 : * Change the ownerships and register quota modifications
67 : * in the transaction.
68 5141593 : */
69 0 : if (!uid_eq(inode->i_uid, GLOBAL_ROOT_UID)) {
70 0 : if (XFS_IS_UQUOTA_ON(mp))
71 0 : oldu = xfs_qm_vop_chown(tp, dp, &dp->i_udquot, udqp);
72 : inode->i_uid = GLOBAL_ROOT_UID;
73 5141593 : }
74 0 : if (!gid_eq(inode->i_gid, GLOBAL_ROOT_GID)) {
75 0 : if (XFS_IS_GQUOTA_ON(mp))
76 0 : oldg = xfs_qm_vop_chown(tp, dp, &dp->i_gdquot, gdqp);
77 : inode->i_gid = GLOBAL_ROOT_GID;
78 5141593 : }
79 0 : if (dp->i_projid != 0) {
80 0 : if (XFS_IS_PQUOTA_ON(mp))
81 0 : oldp = xfs_qm_vop_chown(tp, dp, &dp->i_pdquot, pdqp);
82 : dp->i_projid = 0;
83 : }
84 5141593 :
85 5141593 : dp->i_diflags &= ~(XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT);
86 : xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
87 5141593 :
88 : XFS_STATS_INC(mp, xs_ig_attrchg);
89 5141593 :
90 0 : if (xfs_has_wsync(mp))
91 5141593 : xfs_trans_set_sync(tp);
92 : error = xfs_trans_commit(tp);
93 5141593 :
94 5141593 : xfs_qm_dqrele(oldu);
95 5141593 : xfs_qm_dqrele(oldg);
96 : xfs_qm_dqrele(oldp);
97 5141593 :
98 5141593 : out_dqrele:
99 5141593 : xfs_qm_dqrele(udqp);
100 5141593 : xfs_qm_dqrele(gdqp);
101 5141593 : xfs_qm_dqrele(pdqp);
102 : return error;
103 : }
104 :
105 : /*
106 : * Enable logged extended attributes for parent pointers. This must get done
107 : * before we create transactions and start making changes.
108 : */
109 5141559 : STATIC int
110 : xrep_adoption_grab_log_assist(
111 : struct xfs_scrub *sc)
112 5141559 : {
113 : int error;
114 5141559 :
115 : if (!xfs_has_parent(sc->mp))
116 : return 0;
117 5009167 :
118 : ASSERT(!(sc->flags & XREP_FSGATES_LARP));
119 5009167 :
120 5009108 : error = xfs_attr_grab_log_assist(sc->mp);
121 : if (error)
122 : return error;
123 5009086 :
124 : trace_xchk_fsgates_enable(sc, XREP_FSGATES_LARP);
125 5009060 :
126 5009060 : sc->flags |= XREP_FSGATES_LARP;
127 : return 0;
128 : }
129 :
130 : #define ORPHANAGE "lost+found"
131 :
132 : /* Create the orphanage directory, and set sc->orphanage to it. */
133 5150063 : int
134 : xrep_orphanage_create(
135 : struct xfs_scrub *sc)
136 5150063 : {
137 5150063 : struct xfs_mount *mp = sc->mp;
138 5150063 : struct dentry *root_dentry, *orphanage_dentry;
139 5150063 : struct inode *root_inode = VFS_I(sc->mp->m_rootip);
140 5150063 : struct inode *orphanage_inode;
141 : int error;
142 10300126 :
143 : if (xfs_is_shutdown(mp))
144 10300126 : return -EIO;
145 0 : if (xfs_is_readonly(mp)) {
146 0 : sc->orphanage = NULL;
147 : return 0;
148 : }
149 5150063 :
150 5150063 : ASSERT(sc->tp == NULL);
151 : ASSERT(sc->orphanage == NULL);
152 :
153 5150063 : /* Find the dentry for the root directory... */
154 5150732 : root_dentry = d_find_alias(root_inode);
155 0 : if (!root_dentry) {
156 0 : error = -EFSCORRUPTED;
157 : goto out;
158 : }
159 :
160 5150732 : /* ...which is a directory, right? */
161 0 : if (!d_is_dir(root_dentry)) {
162 0 : error = -EFSCORRUPTED;
163 : goto out_dput_root;
164 : }
165 :
166 5150732 : /* Try to find the orphanage directory. */
167 5150831 : inode_lock_nested(root_inode, I_MUTEX_PARENT);
168 : orphanage_dentry = lookup_one_len(ORPHANAGE, root_dentry,
169 5150831 : strlen(ORPHANAGE));
170 0 : if (IS_ERR(orphanage_dentry)) {
171 0 : error = PTR_ERR(orphanage_dentry);
172 : goto out_unlock_root;
173 : }
174 :
175 : /*
176 : * Nothing found? Call mkdir to create the orphanage. Create the
177 : * directory without group or other-user access because we're live and
178 : * someone could have been relying partly on minimal access to a parent
179 : * directory to control access to a file we put in here.
180 5150831 : */
181 10284 : if (d_really_is_negative(orphanage_dentry)) {
182 : error = vfs_mkdir(&nop_mnt_idmap, root_inode, orphanage_dentry,
183 10284 : 0700);
184 9238 : if (error)
185 : goto out_dput_orphanage;
186 : }
187 :
188 5141593 : /* Not a directory? Bail out. */
189 0 : if (!d_is_dir(orphanage_dentry)) {
190 0 : error = -ENOTDIR;
191 : goto out_dput_orphanage;
192 : }
193 :
194 : /*
195 : * Grab a reference to the orphanage. This /should/ succeed since
196 : * we hold the root directory locked and therefore nobody can delete
197 : * the orphanage.
198 5141593 : */
199 5141593 : orphanage_inode = igrab(d_inode(orphanage_dentry));
200 0 : if (!orphanage_inode) {
201 0 : error = -ENOENT;
202 : goto out_dput_orphanage;
203 : }
204 :
205 5141593 : /* Make sure the orphanage is owned by root. */
206 5141593 : error = xrep_chown_orphanage(sc, XFS_I(orphanage_inode));
207 0 : if (error)
208 : goto out_dput_orphanage;
209 :
210 5141593 : /* Stash the reference for later and bail out. */
211 5141593 : sc->orphanage = XFS_I(orphanage_inode);
212 : sc->orphanage_ilock_flags = 0;
213 5150831 :
214 5150831 : out_dput_orphanage:
215 5150831 : dput(orphanage_dentry);
216 5150831 : out_unlock_root:
217 5150823 : inode_unlock(VFS_I(sc->mp->m_rootip));
218 5150823 : out_dput_root:
219 : dput(root_dentry);
220 : out:
221 : /*
222 : * Turn on whatever log features are required for an adoption to be
223 : * committed correctly.
224 5150816 : */
225 5141579 : if (!error)
226 : error = xrep_adoption_grab_log_assist(sc);
227 : return error;
228 : }
229 :
230 0 : void
231 : xrep_orphanage_ilock(
232 : struct xfs_scrub *sc,
233 : unsigned int ilock_flags)
234 0 : {
235 0 : sc->orphanage_ilock_flags |= ilock_flags;
236 0 : xfs_ilock(sc->orphanage, ilock_flags);
237 : }
238 :
239 99822529 : bool
240 : xrep_orphanage_ilock_nowait(
241 : struct xfs_scrub *sc,
242 : unsigned int ilock_flags)
243 99822529 : {
244 99822527 : if (xfs_ilock_nowait(sc->orphanage, ilock_flags)) {
245 99822527 : sc->orphanage_ilock_flags |= ilock_flags;
246 : return true;
247 : }
248 :
249 : return false;
250 : }
251 :
252 199636346 : void
253 : xrep_orphanage_iunlock(
254 : struct xfs_scrub *sc,
255 : unsigned int ilock_flags)
256 199636346 : {
257 199640676 : xfs_iunlock(sc->orphanage, ilock_flags);
258 4330 : sc->orphanage_ilock_flags &= ~ilock_flags;
259 : }
260 :
261 : /* Grab the IOLOCK of the orphanage and sc->ip. */
262 99818174 : int
263 : xrep_orphanage_iolock_two(
264 : struct xfs_scrub *sc)
265 99818174 : {
266 : int error = 0;
267 99822506 :
268 99822506 : while (true) {
269 1 : if (xchk_should_terminate(sc, &error))
270 : return error;
271 :
272 : /*
273 : * Normal XFS takes the IOLOCK before grabbing a transaction.
274 : * Scrub holds a transaction, which means that we can't block
275 : * on either IOLOCK.
276 99822505 : */
277 99822503 : if (xrep_orphanage_ilock_nowait(sc, XFS_IOLOCK_EXCL)) {
278 : if (xchk_ilock_nowait(sc, XFS_IOLOCK_EXCL))
279 4330 : break;
280 : xrep_orphanage_iunlock(sc, XFS_IOLOCK_EXCL);
281 4332 : }
282 : delay(1);
283 : }
284 :
285 : return 0;
286 : }
287 :
288 : /*
289 : * Set up the adoption structure and compute the block reservations needed to
290 : * add sc->ip to the orphanage.
291 : */
292 99818198 : int
293 : xrep_adoption_init(
294 : struct xfs_scrub *sc,
295 : struct xrep_adoption *adopt)
296 99818198 : {
297 99818198 : struct xfs_mount *mp = sc->mp;
298 : unsigned int child_blkres = 0;
299 99818198 :
300 99818198 : adopt->sc = sc;
301 99818198 : adopt->orphanage_blkres = xfs_link_space_res(mp, MAXNAMELEN);
302 35814123 : if (S_ISDIR(VFS_I(sc->ip)->i_mode))
303 35814123 : child_blkres = xfs_rename_space_res(mp, 0, false,
304 99818198 : xfs_name_dotdot.len, false);
305 : if (xfs_has_parent(sc->mp))
306 99818198 : child_blkres += XFS_ADDAFORK_SPACE_RES(sc->mp);
307 99346501 : adopt->child_blkres = child_blkres;
308 99346501 :
309 : if (xfs_has_parent(mp)) {
310 471697 : ASSERT(sc->flags & XREP_FSGATES_LARP);
311 : return xfs_parent_start_locked(mp, &adopt->parent);
312 : } else {
313 471697 : adopt->parent = NULL;
314 : }
315 :
316 : return 0;
317 : }
318 :
319 : /*
320 : * Compute the xfs_name for the directory entry that we're adding to the
321 : * orphanage. Caller must hold ILOCKs of sc->ip and the orphanage and must not
322 24 : * reuse namebuf until the adoption completes or is cancelled.
323 : */
324 : int
325 : xrep_adoption_compute_name(
326 24 : struct xrep_adoption *adopt,
327 24 : unsigned char *namebuf)
328 24 : {
329 24 : struct xfs_name *xname = &adopt->xname;
330 24 : struct xfs_scrub *sc = adopt->sc;
331 : xfs_ino_t ino;
332 24 : unsigned int incr = 0;
333 24 : int error = 0;
334 24 :
335 : xname->name = namebuf;
336 : xname->len = snprintf(namebuf, MAXNAMELEN, "%llu", sc->ip->i_ino);
337 24 : xname->type = xfs_mode_to_ftype(VFS_I(sc->ip)->i_mode);
338 24 :
339 0 : /* Make sure the filename is unique in the lost+found. */
340 0 : error = xchk_dir_lookup(sc, sc->orphanage, xname, &ino);
341 0 : while (error == 0 && incr < 10000) {
342 : xname->len = snprintf(namebuf, MAXNAMELEN, "%llu.%u",
343 24 : sc->ip->i_ino, ++incr);
344 : error = xchk_dir_lookup(sc, sc->orphanage, xname, &ino);
345 : }
346 : if (error == 0) {
347 : /* We already have 10,000 entries in the orphanage? */
348 24 : return -EFSCORRUPTED;
349 0 : }
350 :
351 : if (error != -ENOENT)
352 : return error;
353 : return 0;
354 : }
355 :
356 : /*
357 : * Prepare to send a child to the orphanage.
358 : *
359 : * Reserve more space in the transaction, take the ILOCKs of the orphanage and
360 : * sc->ip, join them to the transaction, and reserve quota to reparent the
361 99818197 : * latter. Caller must hold the IOLOCK of the orphanage and sc->ip.
362 : */
363 : int
364 99818197 : xrep_adoption_prep(
365 99818197 : struct xrep_adoption *adopt)
366 : {
367 : struct xfs_scrub *sc = adopt->sc;
368 : int error;
369 :
370 : /*
371 99818197 : * Reserve space to the transaction to handle expansion of both the
372 99818197 : * orphanage and the child directory.
373 99818197 : */
374 : error = xfs_trans_reserve_more(sc->tp,
375 : adopt->orphanage_blkres + adopt->child_blkres, 0);
376 99818197 : if (error)
377 : return error;
378 99818197 :
379 99818197 : xfs_lock_two_inodes(sc->orphanage, XFS_ILOCK_EXCL,
380 : sc->ip, XFS_ILOCK_EXCL);
381 99818197 : sc->ilock_flags |= XFS_ILOCK_EXCL;
382 99818197 : sc->orphanage_ilock_flags |= XFS_ILOCK_EXCL;
383 :
384 : xfs_trans_ijoin(sc->tp, sc->orphanage, 0);
385 : xfs_trans_ijoin(sc->tp, sc->ip, 0);
386 :
387 : /*
388 : * Reserve enough quota in the orphan directory to add the new name.
389 : * Normally the orphanage should have user/group/project ids of zero
390 99818197 : * and hence is not subject to quota enforcement, but we're allowed to
391 99818197 : * exceed quota to reattach disconnected parts of the directory tree.
392 99818197 : */
393 : error = xfs_trans_reserve_quota_nblks(sc->tp, sc->orphanage,
394 : adopt->orphanage_blkres, 0, true);
395 : if (error)
396 : return error;
397 :
398 : /*
399 : * Reserve enough quota in the child directory to change dotdot.
400 99818197 : * Here we're also allowed to exceed file quota to repair inconsistent
401 35814123 : * metadata.
402 : */
403 35814123 : if (adopt->child_blkres) {
404 0 : error = xfs_trans_reserve_quota_nblks(sc->tp, sc->ip,
405 : adopt->child_blkres, 0, true);
406 : if (error)
407 : return error;
408 : }
409 :
410 : return 0;
411 : }
412 :
413 : /*
414 : * Make sure the dcache does not have a positive dentry for the name we've
415 : * chosen. The caller should have checked with the ondisk directory, so any
416 0 : * discrepancy is a sign that something is seriously wrong.
417 : */
418 : static int
419 0 : xrep_orphanage_check_dcache(
420 : struct xrep_adoption *adopt)
421 0 : {
422 0 : struct qstr qname = QSTR_INIT(adopt->xname.name,
423 : adopt->xname.len);
424 0 : struct dentry *d_orphanage, *d_child;
425 0 : int error = 0;
426 :
427 : d_orphanage = d_find_alias(VFS_I(adopt->sc->orphanage));
428 0 : if (!d_orphanage)
429 0 : return 0;
430 0 :
431 : d_child = d_hash_and_lookup(d_orphanage, &qname);
432 0 : if (d_child) {
433 0 : trace_xrep_orphanage_check_child(adopt->sc->mp, d_child);
434 0 :
435 : if (d_is_positive(d_child)) {
436 : ASSERT(d_is_negative(d_child));
437 0 : error = -EFSCORRUPTED;
438 : }
439 :
440 0 : dput(d_child);
441 0 : }
442 :
443 : dput(d_orphanage);
444 : if (error)
445 : return error;
446 :
447 : /*
448 : * Do we need to update d_parent of the dentry for the file being
449 0 : * repaired? In theory there shouldn't be one since the file had
450 0 : * nonzero nlink but wasn't connected to any parent dir.
451 0 : */
452 0 : d_child = d_find_alias(VFS_I(adopt->sc->ip));
453 : if (d_child) {
454 0 : trace_xrep_orphanage_check_alias(adopt->sc->mp, d_child);
455 0 : ASSERT(d_child->d_parent == NULL);
456 :
457 : dput(d_child);
458 : return -EFSCORRUPTED;
459 : }
460 :
461 : return 0;
462 : }
463 :
464 : /*
465 : * Remove all negative dentries from the dcache. There should not be any
466 : * positive entries, since we've maintained our lock on the orphanage
467 0 : * directory.
468 : */
469 : static void
470 0 : xrep_orphanage_zap_dcache(
471 : struct xrep_adoption *adopt)
472 0 : {
473 : struct qstr qname = QSTR_INIT(adopt->xname.name,
474 0 : adopt->xname.len);
475 0 : struct dentry *d_orphanage, *d_child;
476 0 :
477 : d_orphanage = d_find_alias(VFS_I(adopt->sc->orphanage));
478 0 : if (!d_orphanage)
479 0 : return;
480 0 :
481 : d_child = d_hash_and_lookup(d_orphanage, &qname);
482 0 : while (d_child != NULL) {
483 0 : trace_xrep_orphanage_invalidate_child(adopt->sc->mp, d_child);
484 0 :
485 0 : ASSERT(d_is_negative(d_child));
486 : d_invalidate(d_child);
487 : dput(d_child);
488 0 : d_child = d_lookup(d_orphanage, &qname);
489 : }
490 :
491 : dput(d_orphanage);
492 : }
493 :
494 : static inline int
495 : xrep_pptr_attr_sizeof(
496 : const struct xrep_adoption *adopt)
497 : {
498 : size_t res = sizeof(struct xfs_attr_sf_hdr);
499 :
500 0 : res += xfs_attr_sf_entsize_byname(sizeof(struct xfs_parent_name_rec),
501 : adopt->xname.len);
502 : return res;
503 0 : }
504 0 :
505 0 : /*
506 0 : * Move the current file to the orphanage.
507 : *
508 0 : * The caller must hold the IOLOCKs and the ILOCKs for both sc->ip and the
509 : * orphanage. The directory entry name must have been computed, and quota
510 0 : * reserved. The function returns with both inodes joined and ILOCKed to the
511 0 : * transaction.
512 0 : */
513 : int
514 : xrep_adoption_commit(
515 0 : struct xrep_adoption *adopt)
516 : {
517 0 : struct xfs_scrub *sc = adopt->sc;
518 0 : struct xfs_name *xname = &adopt->xname;
519 : bool isdir = S_ISDIR(VFS_I(sc->ip)->i_mode);
520 : int error;
521 :
522 : trace_xrep_adoption_commit(sc->orphanage, &adopt->xname, sc->ip->i_ino);
523 :
524 0 : error = xrep_orphanage_check_dcache(adopt);
525 : if (error)
526 0 : goto out_parent;
527 0 :
528 0 : /*
529 : * If this filesystem has parent pointers, ensure that the file being
530 : * moved to the orphanage has an attribute fork. This is required
531 0 : * because the parent pointer code does not itself add attr forks.
532 0 : */
533 : if (!xfs_inode_has_attr_fork(sc->ip) && xfs_has_parent(sc->mp)) {
534 : int sf_size = xrep_pptr_attr_sizeof(adopt);
535 0 :
536 0 : error = xfs_bmap_add_attrfork(sc->tp, sc->ip, sf_size, true);
537 0 : if (error)
538 0 : goto out_parent;
539 0 : }
540 :
541 : /* Create the new name in the orphanage. */
542 : error = xfs_dir_createname(sc->tp, sc->orphanage, xname, sc->ip->i_ino,
543 0 : adopt->orphanage_blkres);
544 0 : if (error)
545 : goto out_parent;
546 0 :
547 0 : /*
548 : * Bump the link count of the orphanage if we just added a
549 : * subdirectory, and update its timestamps.
550 : */
551 : xfs_trans_ichgtime(sc->tp, sc->orphanage,
552 : XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
553 : if (isdir)
554 : xfs_bumplink(sc->tp, sc->orphanage);
555 0 : xfs_trans_log_inode(sc->tp, sc->orphanage, XFS_ILOG_CORE);
556 0 :
557 0 : /* Bump the link count of the child. */
558 0 : if (adopt->bump_child_nlink) {
559 : xfs_bumplink(sc->tp, sc->ip);
560 : xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
561 0 : }
562 0 :
563 0 : /* Replace the dotdot entry if the child is a subdirectory. */
564 0 : if (isdir) {
565 0 : error = xfs_dir_replace(sc->tp, sc->ip, &xfs_name_dotdot,
566 : sc->orphanage->i_ino, adopt->child_blkres);
567 : if (error)
568 : goto out_parent;
569 : }
570 99818197 :
571 : /* Add a parent pointer from the file back to the lost+found. */
572 : if (adopt->parent) {
573 : error = xfs_parent_add(sc->tp, adopt->parent, sc->orphanage,
574 99818197 : xname, sc->ip);
575 : if (error)
576 : goto out_parent;
577 : }
578 :
579 : /*
580 : * Notify dirent hooks that we moved the file to /lost+found, and
581 : * finish all the deferred work so that we know the adoption is fully
582 99818197 : * recorded in the log.
583 99818197 : */
584 99818197 : xfs_dir_update_hook(sc->orphanage, sc->ip, 1, xname);
585 99818197 : error = xrep_defer_finish(sc);
586 : if (error)
587 : goto out_parent;
588 :
589 875962031 : /* Remove negative dentries from the lost+found's dcache */
590 : xrep_orphanage_zap_dcache(adopt);
591 : out_parent:
592 875962031 : xfs_parent_finish(sc->mp, adopt->parent);
593 : adopt->parent = NULL;
594 : return error;
595 5124669 : }
596 24 :
597 : /* Cancel a proposed relocation of a file to the orphanage. */
598 5124669 : void
599 5134699 : xrep_adoption_cancel(
600 : struct xrep_adoption *adopt,
601 : int error)
602 : {
603 : struct xfs_scrub *sc = adopt->sc;
604 :
605 : /*
606 : * Setting up (and hence cancelling) an adoption is the last thing that
607 : * repair code does. Hence we don't bother giving back the quota or
608 : * space reservations or unlock the inodes. Later when we have incore
609 : * state to manage, we'll need to give that back.
610 : */
611 : trace_xrep_adoption_cancel(sc->orphanage, sc->ip, error);
612 : xfs_parent_finish(sc->mp, adopt->parent);
613 : adopt->parent = NULL;
614 : }
615 :
616 : /* Release the orphanage. */
617 : void
618 : xrep_orphanage_rele(
619 : struct xfs_scrub *sc)
620 : {
621 : if (!sc->orphanage)
622 : return;
623 :
624 : if (sc->orphanage_ilock_flags)
625 : xfs_iunlock(sc->orphanage, sc->orphanage_ilock_flags);
626 :
627 : xchk_irele(sc, sc->orphanage);
628 : sc->orphanage = NULL;
629 : }
630 :
631 : /* Can the orphanage adopt this file? */
632 : bool
633 : xrep_orphanage_can_adopt(
634 : struct xfs_scrub *sc)
635 : {
636 : ASSERT(sc->ip != NULL);
637 :
638 : if (!sc->orphanage)
639 : return false;
640 : if (sc->ip == sc->orphanage)
641 : return false;
642 : if (xfs_internal_inum(sc->mp, sc->ip->i_ino))
643 : return false;
644 : if (xfs_is_metadata_inode(sc->ip))
645 : return false;
646 : return true;
647 : }
|