xfs_repair aborts execution due to an ASSERT at line 1419 from dir2.c
Environment
- Red Hat Enterprise Linux 7
- XFS filesystem
- xfsprogs <= 4.5.0-15.el7
Issue
xfs_repair aborts during execution in process_dir2.
xfs_repair: dir2.c:1419: process_dir2: Assertion `(ino != mp->m_sb.sb_rootino && ino != *parent) || (ino == mp->m_sb.sb_rootino && (ino == *parent || need_root_dotdot == 1))' failed.
Aborted (core dumped)
Resolution
An upstream patch for xfsprogs package has been suggested:
Author: Marco Benatto <mbenatto@redhat.com>
Date: Thu Jun 14 19:01:29 2018 -0300
xfs_repair: Fix root inode's parent when it's bogus for sf directory
Currently when root inode is in short-form and its parent ino
has an invalid value, process_sf_dir2() ends up not fixing it,
because if verify_inum() fails we never get to the next case which
would fix the root inode's parent pointer.
This behavior triggers the following assert on process_dir2():
ASSERT((ino != mp->m_sb.sb_rootino && ino != *parent) ||
(ino == mp->m_sb.sb_rootino &&
(ino == *parent || need_root_dotdot == 1)));
This patch fixes this behavior by making sure we always properly
handle rootino parent pointer in process_sf_dir2()
Signed-off-by: Marco Benatto <mbenatto@redhat.com>
Root Cause
-
Currently, if the root inode is in
short-form directoryform and its parent pointer has an invalid inode numberxfs_repairdoesn't fix it.
This happens due to a bug inprocess_sf_dir2()which handles directory parent's invalid inode numbers without taking in account the root inode directory. -
If
xfs_repairdetects root inode parent has an invalid inode number (line 499 on code snippet below) inprocess_sf_dir2()function, the secondelse ifis never reached leaving root inode's parent zeroed.
490
491 /*
492 * check parent (..) entry
493 */
494 *parent = M_DIROPS(mp)->sf_get_parent_ino(sfp);
495
496 /*
497 * if parent entry is bogus, null it out. we'll fix it later .
498 */
499 if (verify_inum(mp, *parent)) {
500
501 do_warn(
502 _("bogus .. inode number (%" PRIu64 ") in directory inode %" PRIu64 ", "),
503 *parent, ino);
504 *parent = NULLFSINO;
505 if (!no_modify) {
506 do_warn(_("clearing inode number\n"));
507
508 M_DIROPS(mp)->sf_put_parent_ino(sfp, zero);
509 *dino_dirty = 1;
510 *repair = 1;
511 } else {
512 do_warn(_("would clear inode number\n"));
513 }
514 } else if (ino == mp->m_sb.sb_rootino && ino != *parent) {
515 /*
516 * root directories must have .. == .
517 */
518 if (!no_modify) {
519 do_warn(
520 _("corrected root directory %" PRIu64 " .. entry, was %" PRIu64 ", now %" PRIu64 "\n"),
521 ino, *parent, ino);
522 *parent = ino;
523 M_DIROPS(mp)->sf_put_parent_ino(sfp, ino);
524 *dino_dirty = 1;
525 *repair = 1;
526 } else {
527 do_warn(
528 _("would have corrected root directory %" PRIu64 " .. entry from %" PRIu64" to %" PRIu64 "\n"),
529 ino, *parent, ino);
530 }
531 } else if (ino == *parent && ino != mp->m_sb.sb_rootino) {
532 /*
533 * likewise, non-root directories can't have .. pointing
534 * to .
535 */
536 *parent = NULLFSINO;
537 do_warn(
538 _("bad .. entry in directory inode %" PRIu64 ", points to self, "),
539 ino);
540 if (!no_modify) {
541 do_warn(_("clearing inode number\n"));
542
543 M_DIROPS(mp)->sf_put_parent_ino(sfp, zero);
544 *dino_dirty = 1;
545 *repair = 1;
546 } else {
547 do_warn(_("would clear inode number\n"));
548 }
549 }
- As effect the following
ASSERT()is triggered right after, still in repair'sPhase 3:
ASSERT((ino != mp->m_sb.sb_rootino && ino != *parent) ||
(ino == mp->m_sb.sb_rootino &&
(ino == *parent || need_root_dotdot == 1)));
- The RHBZ#1590334 Bugzilla ticket has been raised for this issue.
Diagnostic Steps
1) Use xfs_db tool to open the unmounted device:
# xfs_db /dev/loop0
xfs_db>
2) Looking into superblock 0, retrieve which is the root inode number:
xfs_db> sb 0
xfs_db> p rootino
rootino = 128
3) Inspect the root inode looking to determine which directory format it's using:
xfs_db> inode 128
xfs_db> p core.format
core.format = 1 (local)
- If
core.formatis equal to 1 it means XFS is usingshort-form directoryformat to store this directory information.
4) Look to the parent value on short-form header:
xfs_db> p u.sfdir2.hdr.parent.i4
u.sfdir2.hdr.parent.i4 = 0
- On XFS filesystem the root inode's parent should point to root inode itself, in this case, it should point to
ino 128but it's pointing toino 0which is an invalid inode number.
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.
Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.
