From nobody Sat Sep 03 21:48:40 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4MKpLx086kz4bdx8; Sat, 3 Sep 2022 21:48:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4MKpLw6HLpz4DZx; Sat, 3 Sep 2022 21:48:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1662241720; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1Bmcvt4vih7W7ZsRnjQ4jZFgkr+AD4DU0KXGcZ6rPU4=; b=PEhD+KVMnbZ2cg4NIRVi5u6LVZhhsduE7L3cMucMinuxQpYkGnzXP7EjhVFMicDlFoWhnq idEUCfBc4v2POnkpzq2OpjEXn4hRDPXEksZaQWvzU11XrnC4BNda4j3knD69NFoY4HYQpK JE6ofqIlB57AdTRu7xdcWal1xwNqDFF5pRxFlP1fI2J/Td9lWwSkDMrd1n693vIjeHy6RC 78NDoQ9OzBtt8lTyLFpzBRckdncaQL3VCNxMFtue1NsZ1ffw+tK3LcasEUF1zH5PI8ZhDq jHCN1IuneG1cBTJTZou8eo/BYYqBK2yc7C7rdfhNkNTMSN15ZUaBU8bIcUqWDg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4MKpLw5F5SzHKf; Sat, 3 Sep 2022 21:48:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 283Lme7s020722; Sat, 3 Sep 2022 21:48:40 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 283Lmep1020721; Sat, 3 Sep 2022 21:48:40 GMT (envelope-from git) Date: Sat, 3 Sep 2022 21:48:40 GMT Message-Id: <202209032148.283Lmep1020721@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kirk McKusick Subject: git: f4fc3895243b - main - Properly handle the replacement of a partially allocated root directory. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mckusick X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: f4fc3895243b9a8ae0577e731a3e450377071196 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1662241720; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1Bmcvt4vih7W7ZsRnjQ4jZFgkr+AD4DU0KXGcZ6rPU4=; b=gRVaI8Vo+Ekb55z9/70xG93ditTDr3O6/yW/2Mcg9tyvY2LTl3mE/A3cvCV7pHzdR1aNPu QyQMonxE4K0XqynjBZA9FgTCslmu9TnspIRUbSmUrgay29jhXGiLCLQeVqjdx95eoz15e+ n1VRDersedwD5BcjbKXwYN4EKtmSdS2nGxQ0BdwHskxKKxmdzaOuCkqEhbCyzG216dTH3C 3RF1aiSEvkWWqQ95bwpUPaUUU53ri7rRjFNRvq+EQMt4Z/LLoFilKw1ylS+oroaUzxdWM/ ddY6fQ0AMZXbPAO/h2k3ZEIu8CGU2ncHGqOKfRTSDn4LosAzBkW5Kw710KJnoA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1662241720; a=rsa-sha256; cv=none; b=sF0285lgCX78RWAfMbhVUywWyutW0OJj5HMQfVuL8L7NSZJBeCm8bcEHptgY73/QInzVIe hFN1Eyn9j7pUu40oLV9+BR+vlJ7WoLnd+8cNX8fk53mefBIA5QOVwzcSeo9CMuJJAHU4KM dMJPlPO+SLCEhTnztl4q+bDq6NkYGGkBJanwOLvh4qEVYB6WNiy69OHVjBRIEYuxoMu8SI npZJ7dyKeLm3C6otTanjSitO16480w8w55Ip4TjnVlm4YfW4YkEmuIGrCP6EQ/EQ21/n7J RxGvzi0UPYEQIb0cMt+5kF4Y1SHBT8CPsNZh3AePrEDooDoNQ2TCYJF8XSCv7A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by mckusick: URL: https://cgit.FreeBSD.org/src/commit/?id=f4fc3895243b9a8ae0577e731a3e450377071196 commit f4fc3895243b9a8ae0577e731a3e450377071196 Author: Kirk McKusick AuthorDate: 2022-09-03 21:46:50 +0000 Commit: Kirk McKusick CommitDate: 2022-09-03 21:48:34 +0000 Properly handle the replacement of a partially allocated root directory. If the root directory exists but has a bad block number Pass1 will accept it and setup an inoinfo structure for it. When Pass2 runs and cannot read the root inode's content because of a bad (or duplicate) block number, it removes the bad root inode and replaces it. As part of creating the replacement root inode, it creates an inoinfo entry for it. But Pass2 did delete the inoinfo entry that Pass1 had set up for the root inode so ended up with two inoinfo structures for it. The final step of Pass2 checks that all the ".." entries are correct adding them if they are missing which resulted in a second ".." entry being added to the root directory which definitely did not go over well in the kernel name cache! Reported by: Peter Holm Sponsored by: The FreeBSD Foundation --- sbin/fsck_ffs/dir.c | 18 +++++++++++++----- sbin/fsck_ffs/fsck.h | 8 +++++++- sbin/fsck_ffs/inode.c | 6 ++++-- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c index 42ecf4112253..87e3e34cc1ad 100644 --- a/sbin/fsck_ffs/dir.c +++ b/sbin/fsck_ffs/dir.c @@ -474,6 +474,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name) union dinode *dp; int lostdir; ino_t oldlfdir; + struct inoinfo *inp; struct inodesc idesc; char tempname[BUFSIZ]; @@ -581,10 +582,12 @@ linkup(ino_t orphan, ino_t parentdir, char *name) inodirty(&ip); inoinfo(lfdir)->ino_linkcnt++; pwarn("DIR I=%lu CONNECTED. ", (u_long)orphan); - if (parentdir != (ino_t)-1) { + inp = getinoinfo(parentdir); + if (parentdir != (ino_t)-1 && (inp->i_flags & INFO_NEW) == 0) { printf("PARENT WAS I=%lu\n", (u_long)parentdir); /* - * The parent directory, because of the ordering + * If the parent directory did not have to + * be replaced then because of the ordering * guarantees, has had the link count incremented * for the child, but no entry was made. This * fixes the parent link count so that fsck does @@ -823,7 +826,12 @@ allocdir(ino_t parent, ino_t request, int mode) inodirty(&ip); if (ino == UFS_ROOTINO) { inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink); - cacheino(dp, ino); + if ((inp = getinoinfo(ino)) == NULL) + inp = cacheino(dp, ino); + else + inp->i_flags = INFO_NEW; + inp->i_parent = parent; + inp->i_dotdot = parent; irelse(&ip); return(ino); } @@ -832,8 +840,8 @@ allocdir(ino_t parent, ino_t request, int mode) irelse(&ip); return (0); } - cacheino(dp, ino); - inp = getinoinfo(ino); + if ((inp = getinoinfo(ino)) == NULL) + inp = cacheino(dp, ino); inp->i_parent = parent; inp->i_dotdot = parent; inoinfo(ino)->ino_state = inoinfo(parent)->ino_state; diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 65c7056532be..d1b45a0850da 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -311,9 +311,15 @@ extern struct inoinfo { ino_t i_parent; /* inode number of parent */ ino_t i_dotdot; /* inode number of `..' */ size_t i_isize; /* size of inode */ + u_int i_flags; /* flags, see below */ u_int i_numblks; /* size of block array in bytes */ ufs2_daddr_t i_blks[1]; /* actually longer */ } **inphead, **inpsort; +/* + * flags for struct inoinfo + */ +#define INFO_NEW 0x0000001 /* replaced broken directory */ + extern long dirhash, inplast; extern unsigned long numdirs, listmax; extern long countdirs; /* number of directories we actually found */ @@ -446,7 +452,7 @@ void blwrite(int fd, char *buf, ufs2_daddr_t blk, ssize_t size); void blerase(int fd, ufs2_daddr_t blk, long size); void blzero(int fd, ufs2_daddr_t blk, long size); void brelse(struct bufarea *); -void cacheino(union dinode *dp, ino_t inumber); +struct inoinfo *cacheino(union dinode *dp, ino_t inumber); void catch(int); void catchquit(int); void cgdirty(struct bufarea *); diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c index f0699aabe349..cbdd756e5d17 100644 --- a/sbin/fsck_ffs/inode.c +++ b/sbin/fsck_ffs/inode.c @@ -698,12 +698,14 @@ freeinodebuf(void) * * Enter inodes into the cache. */ -void +struct inoinfo * cacheino(union dinode *dp, ino_t inumber) { struct inoinfo *inp, **inpp; int i, blks; + if (getinoinfo(inumber) != NULL) + pfatal("cacheino: duplicate entry for ino %ld\n", inumber); if (howmany(DIP(dp, di_size), sblock.fs_bsize) > UFS_NDADDR) blks = UFS_NDADDR + UFS_NIADDR; else if (DIP(dp, di_size) > 0) @@ -735,6 +737,7 @@ cacheino(union dinode *dp, ino_t inumber) errx(EEXIT, "cannot increase directory list"); } inpsort[inplast++] = inp; + return (inp); } /* @@ -750,7 +753,6 @@ getinoinfo(ino_t inumber) continue; return (inp); } - errx(EEXIT, "cannot find inode %ju", (uintmax_t)inumber); return ((struct inoinfo *)0); }