summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorGrigoriy Orlov <gluk@cvs.openbsd.org>2001-05-28 21:22:48 +0000
committerGrigoriy Orlov <gluk@cvs.openbsd.org>2001-05-28 21:22:48 +0000
commitef3eb9521d508777e6f29b4faad924d844922b58 (patch)
tree86a47377687e7ac4bec0d73c88a59fa98f29d5b2 /sbin
parent900ff3db497d920bda2371ccbfa85ac08f6f1a37 (diff)
Fix directory state tracking.
- If the lost+found directory is created by fsck, it will do a cacheino() which sets the inoinfo's i_parent and i_dotdot to 0, but they never get set to ROOTINO. This means that propagate will never find lost+found and its descendents, subdirectories will remain DSTATE (instead of DFOUND) even though they are correctly linked in, and pass4.c will try to clear them unsuccessfully, thinking that there is no link count from the DSTATE directory's parent. The result is that you need to run fsck twice and get "EXTRANEOUS HARD LINK TO DIRECTORY" error (which are unexpected and fatal when running in preen mode). The fix is to set i_parent and i_dotdot to "parent" after the second cacheino() call in dir.c:allocdir(). From NetBSD via FreeBSD. - modify propagate() so it be able to start from any point in the tree. - minor tweaks to get more generality in state propagation. In other words fsck doesn't leave unremovable directories anymore. costa@ ok.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/fsck_ffs/dir.c44
-rw-r--r--sbin/fsck_ffs/extern.h4
-rw-r--r--sbin/fsck_ffs/pass2.c25
-rw-r--r--sbin/fsck_ffs/pass3.c23
4 files changed, 54 insertions, 42 deletions
diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c
index 4e5b32746bb..52996a6f46a 100644
--- a/sbin/fsck_ffs/dir.c
+++ b/sbin/fsck_ffs/dir.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dir.c,v 1.8 2001/03/02 08:33:55 art Exp $ */
+/* $OpenBSD: dir.c,v 1.9 2001/05/28 21:22:47 gluk Exp $ */
/* $NetBSD: dir.c,v 1.20 1996/09/27 22:45:11 christos Exp $ */
/*
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)dir.c 8.5 (Berkeley) 12/8/94";
#else
-static char rcsid[] = "$OpenBSD: dir.c,v 1.8 2001/03/02 08:33:55 art Exp $";
+static char rcsid[] = "$OpenBSD: dir.c,v 1.9 2001/05/28 21:22:47 gluk Exp $";
#endif
#endif /* not lint */
@@ -80,31 +80,21 @@ static int chgino __P((struct inodesc *));
* Propagate connected state through the tree.
*/
void
-propagate()
+propagate(inumber)
+ ino_t inumber;
{
- register struct inoinfo **inpp, *inp, *pinp;
- struct inoinfo **inpend;
-
- /*
- * Create a list of children for each directory.
- */
- inpend = &inpsort[inplast];
- for (inpp = inpsort; inpp < inpend; inpp++) {
- inp = *inpp;
- if (inp->i_parent == 0 ||
- inp->i_number == ROOTINO)
- continue;
- pinp = getinoinfo(inp->i_parent);
- inp->i_parentp = pinp;
- inp->i_sibling = pinp->i_child;
- pinp->i_child = inp;
- }
- inp = getinoinfo(ROOTINO);
- while (inp) {
- statemap[inp->i_number] = DFOUND;
+ struct inoinfo *inp;
+ char state;
+
+ inp = getinoinfo(inumber);
+ state = statemap[inp->i_number];
+ for (;;) {
+ statemap[inp->i_number] = state;
if (inp->i_child &&
- statemap[inp->i_child->i_number] == DSTATE)
+ statemap[inp->i_child->i_number] != state)
inp = inp->i_child;
+ else if (inp->i_number == inumber)
+ break;
else if (inp->i_sibling)
inp = inp->i_sibling;
else
@@ -432,8 +422,6 @@ linkup(orphan, parentdir)
else
if (reply("RECONNECT") == 0)
return (0);
- if (parentdir != 0)
- lncntp[parentdir]++;
if (lfdir == 0) {
dp = ginode(ROOTINO);
idesc.id_name = lfname;
@@ -651,6 +639,7 @@ allocdir(parent, request, mode)
struct dinode *dp;
register struct bufarea *bp;
struct dirtemplate *dirp;
+ struct inoinfo *inp;
ino = allocino(request, IFDIR|mode);
if (newinofmt)
@@ -683,6 +672,9 @@ allocdir(parent, request, mode)
return (0);
}
cacheino(dp, ino);
+ inp = getinoinfo(ino);
+ inp->i_parent = parent;
+ inp->i_dotdot = parent;
statemap[ino] = statemap[parent];
if (statemap[ino] == DSTATE) {
lncntp[ino] = dp->di_nlink;
diff --git a/sbin/fsck_ffs/extern.h b/sbin/fsck_ffs/extern.h
index cda19a371ba..45e9c080e15 100644
--- a/sbin/fsck_ffs/extern.h
+++ b/sbin/fsck_ffs/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.4 1999/03/01 07:45:17 d Exp $ */
+/* $OpenBSD: extern.h,v 1.5 2001/05/28 21:22:47 gluk Exp $ */
/* $NetBSD: extern.h,v 1.6 1996/09/27 22:45:12 christos Exp $ */
/*
@@ -65,7 +65,7 @@ int pass1check __P((struct inodesc *));
int pass4check __P((struct inodesc *));
void pass5 __P((void));
void pinode __P((ino_t));
-void propagate __P((void));
+void propagate __P((ino_t));
int reply __P((char *));
void resetinodebuf __P((void));
int setup __P((char *));
diff --git a/sbin/fsck_ffs/pass2.c b/sbin/fsck_ffs/pass2.c
index 69fced5af54..0280ebcf6e7 100644
--- a/sbin/fsck_ffs/pass2.c
+++ b/sbin/fsck_ffs/pass2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pass2.c,v 1.8 2001/03/02 08:33:55 art Exp $ */
+/* $OpenBSD: pass2.c,v 1.9 2001/05/28 21:22:47 gluk Exp $ */
/* $NetBSD: pass2.c,v 1.17 1996/09/27 22:45:15 christos Exp $ */
/*
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)pass2.c 8.6 (Berkeley) 10/27/94";
#else
-static char rcsid[] = "$OpenBSD: pass2.c,v 1.8 2001/03/02 08:33:55 art Exp $";
+static char rcsid[] = "$OpenBSD: pass2.c,v 1.9 2001/05/28 21:22:47 gluk Exp $";
#endif
#endif /* not lint */
@@ -86,7 +86,7 @@ void
pass2()
{
register struct dinode *dp;
- register struct inoinfo **inpp, *inp;
+ register struct inoinfo **inpp, *inp, *pinp;
struct inoinfo **inpend;
struct inodesc curino;
struct dinode dino;
@@ -143,6 +143,7 @@ pass2()
default:
errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);
}
+ statemap[ROOTINO] = DFOUND;
if (newinofmt) {
statemap[WINO] = FSTATE;
typemap[WINO] = DT_WHT;
@@ -235,9 +236,23 @@ pass2()
}
info_fn = NULL;
/*
+ * Create a list of children for each directory.
+ */
+ inpend = &inpsort[inplast];
+ for (inpp = inpsort; inpp < inpend; inpp++) {
+ inp = *inpp;
+ if (inp->i_parent == 0 ||
+ inp->i_number == ROOTINO)
+ continue;
+ pinp = getinoinfo(inp->i_parent);
+ inp->i_parentp = pinp;
+ inp->i_sibling = pinp->i_child;
+ pinp->i_child = inp;
+ }
+ /*
* Mark all the directories that can be found from the root.
*/
- propagate();
+ propagate(ROOTINO);
}
static int
@@ -467,7 +482,7 @@ again:
n = 1;
break;
}
- else if ((n = reply("REMOVE")) == 1)
+ if ((n = reply("REMOVE")) == 1)
break;
}
if (idesc->id_entryno > 2)
diff --git a/sbin/fsck_ffs/pass3.c b/sbin/fsck_ffs/pass3.c
index 2c7903649ae..eb4ecbd728e 100644
--- a/sbin/fsck_ffs/pass3.c
+++ b/sbin/fsck_ffs/pass3.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pass3.c,v 1.3 1999/03/01 07:45:18 d Exp $ */
+/* $OpenBSD: pass3.c,v 1.4 2001/05/28 21:22:47 gluk Exp $ */
/* $NetBSD: pass3.c,v 1.8 1995/03/18 14:55:54 cgd Exp $ */
/*
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)pass3.c 8.1 (Berkeley) 6/5/93";
#else
-static char rcsid[] = "$OpenBSD: pass3.c,v 1.3 1999/03/01 07:45:18 d Exp $";
+static char rcsid[] = "$OpenBSD: pass3.c,v 1.4 2001/05/28 21:22:47 gluk Exp $";
#endif
#endif /* not lint */
@@ -64,7 +64,7 @@ pass3_info(buf, buflen)
void
pass3()
{
- register struct inoinfo **inpp, *inp;
+ register struct inoinfo **inpp, *inp, *pinp;
ino_t orphan;
int loopcnt;
@@ -73,7 +73,7 @@ pass3()
info_pos++;
inp = *inpp;
if (inp->i_number == ROOTINO ||
- !(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE))
+ (inp->i_parent != 0 && statemap[inp->i_number] != DSTATE))
continue;
if (statemap[inp->i_number] == DCLEAR)
continue;
@@ -85,11 +85,16 @@ pass3()
break;
inp = getinoinfo(inp->i_parent);
}
- (void)linkup(orphan, inp->i_dotdot);
- inp->i_parent = inp->i_dotdot = lfdir;
- lncntp[lfdir]--;
- statemap[orphan] = DFOUND;
- propagate();
+ if (linkup(orphan, inp->i_dotdot)) {
+ inp->i_parent = inp->i_dotdot = lfdir;
+ lncntp[lfdir]--;
+ pinp = getinoinfo(inp->i_parent);
+ inp->i_parentp = pinp;
+ inp->i_sibling = pinp->i_child;
+ pinp->i_child = inp;
+ statemap[orphan] = statemap[inp->i_parent];
+ }
+ propagate(orphan);
}
info_fn = NULL;
}