rework fsnode' into two components; fsnode' contains the name and tree

information and a link to the appropriate fsinode, and `fsinode' contains
the inode information and a reference count. multiple fsnodes may point
to the same fsinode.  this replaces the 'dup' pointer in the previous code.
This commit is contained in:
lukem 2001-12-05 11:08:53 +00:00
parent 20a3ef2b53
commit ebbf3dddb5
4 changed files with 140 additions and 120 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs.c,v 1.4 2001/11/22 02:47:26 lukem Exp $ */
/* $NetBSD: ffs.c,v 1.5 2001/12/05 11:08:53 lukem Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -71,7 +71,7 @@
#include <sys/cdefs.h>
#ifndef __lint
__RCSID("$NetBSD: ffs.c,v 1.4 2001/11/22 02:47:26 lukem Exp $");
__RCSID("$NetBSD: ffs.c,v 1.5 2001/12/05 11:08:53 lukem Exp $");
#endif /* !__lint */
#include <sys/param.h>
@ -518,14 +518,16 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
assert(strcmp(node->name, ".") == 0);
ADDDIRENT("..");
}
if (node->dup == NULL) { /* don't count duplicate names */
if ((node->inode->flags & FI_SIZED) == 0) {
/* don't count duplicate names */
node->inode->flags |= FI_SIZED;
if (debug & DEBUG_FS_SIZE_DIR_NODE)
printf("ffs_size_dir: %s size %lld\n",
node->name,
(long long)node->statbuf.st_size);
(long long)node->inode->st.st_size);
fsopts->inodes++;
if (node->type == S_IFREG)
ADDSIZE(node->statbuf.st_size);
ADDSIZE(node->inode->st.st_size);
if (node->type == S_IFLNK) {
int slen;
@ -567,23 +569,23 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
* pass 1: allocate inode numbers, build directory `file'
*/
for (cur = root; cur != NULL; cur = cur->next) {
if (cur->dup == NULL) {
if (cur == root && cur->parent)
cur->ino = cur->parent->ino;
if ((cur->inode->flags & FI_ALLOCATED) == 0) {
cur->inode->flags |= FI_ALLOCATED;
if (cur == root && cur->parent != NULL)
cur->inode->ino = cur->parent->inode->ino;
else {
cur->ino = fsopts->curinode;
cur->inode->ino = fsopts->curinode;
fsopts->curinode++;
}
} else
cur->ino = cur->dup->ino;
}
ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap);
if (cur == root) { /* we're at "."; add ".." */
ffs_make_dirbuf(&dirbuf, "..",
cur->parent == NULL ? cur : cur->parent->first,
fsopts->needswap);
root->nlink++; /* count my parent's link */
root->inode->nlink++; /* count my parent's link */
} else if (cur->child != NULL)
root->nlink++; /* count my child's link */
root->inode->nlink++; /* count my child's link */
/*
* XXX possibly write file and long symlinks here,
@ -601,8 +603,9 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
if (debug & DEBUG_FS_POPULATE)
printf("ffs_populate_dir: PASS 2 dir %s\n", dir);
for (cur = root; cur != NULL; cur = cur->next) {
if (cur->dup != NULL)
if (cur->inode->flags & FI_WRITTEN)
continue; /* skip hard-linked entries */
cur->inode->flags |= FI_WRITTEN;
if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
>= sizeof(path))
@ -613,19 +616,19 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
/* build on-disk inode */
memset(&din, 0, sizeof(din));
din.di_mode = cur->statbuf.st_mode;
din.di_nlink = cur->nlink;
din.di_size = cur->statbuf.st_size;
din.di_atime = cur->statbuf.st_atime;
din.di_atimensec = cur->statbuf.st_atimensec;
din.di_mtime = cur->statbuf.st_mtime;
din.di_mtimensec = cur->statbuf.st_mtimensec;
din.di_ctime = cur->statbuf.st_ctime;
din.di_ctimensec = cur->statbuf.st_ctimensec;
din.di_flags = cur->statbuf.st_flags;
din.di_gen = cur->statbuf.st_gen;
din.di_uid = cur->statbuf.st_uid;
din.di_gid = cur->statbuf.st_gid;
din.di_mode = cur->inode->st.st_mode;
din.di_nlink = cur->inode->nlink;
din.di_size = cur->inode->st.st_size;
din.di_atime = cur->inode->st.st_atime;
din.di_atimensec = cur->inode->st.st_atimensec;
din.di_mtime = cur->inode->st.st_mtime;
din.di_mtimensec = cur->inode->st.st_mtimensec;
din.di_ctime = cur->inode->st.st_ctime;
din.di_ctimensec = cur->inode->st.st_ctimensec;
din.di_flags = cur->inode->st.st_flags;
din.di_gen = cur->inode->st.st_gen;
din.di_uid = cur->inode->st.st_uid;
din.di_gid = cur->inode->st.st_gid;
/* not set: di_db, di_ib, di_blocks, di_spare */
membuf = NULL;
@ -635,7 +638,7 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
} else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
din.di_size = 0; /* a device */
din.di_rdev =
ufs_rw32(cur->statbuf.st_rdev, fsopts->needswap);
ufs_rw32(cur->inode->st.st_rdev, fsopts->needswap);
} else if (S_ISLNK(cur->type)) { /* symlink */
int slen;
@ -649,19 +652,19 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
if (debug & DEBUG_FS_POPULATE_NODE) {
printf("ffs_populate_dir: writing ino %d, %s",
cur->ino, inode_type(cur->type));
if (cur->nlink > 1)
printf(", nlink %d", cur->nlink);
cur->inode->ino, inode_type(cur->type));
if (cur->inode->nlink > 1)
printf(", nlink %d", cur->inode->nlink);
putchar('\n');
}
if (membuf != NULL) {
ffs_write_file(&din, cur->ino, membuf, fsopts);
ffs_write_file(&din, cur->inode->ino, membuf, fsopts);
} else if (S_ISREG(cur->type)) {
ffs_write_file(&din, cur->ino, path, fsopts);
ffs_write_file(&din, cur->inode->ino, path, fsopts);
} else {
assert (! S_ISDIR(cur->type));
ffs_write_inode(&din, cur->ino, fsopts);
ffs_write_inode(&din, cur->inode->ino, fsopts);
}
}
@ -788,7 +791,7 @@ ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap)
{
doff_t i;
struct direct *de;
u_int16_t reclen;
uint16_t reclen;
assert (dbuf != NULL);
assert (dir != NULL);
@ -812,16 +815,16 @@ static void
ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
{
struct direct de, *dp;
u_int16_t llen, reclen;
uint16_t llen, reclen;
assert (dbuf != NULL);
assert (name != NULL);
assert (node != NULL);
/* create direct entry */
(void)memset(&de, 0, sizeof(de));
de.d_ino = ufs_rw32(node->ino, needswap);
de.d_ino = ufs_rw32(node->inode->ino, needswap);
de.d_type = IFTODT(node->type);
de.d_namlen = (u_int8_t)strlen(name);
de.d_namlen = (uint8_t)strlen(name);
assert (de.d_namlen < (sizeof(de.d_name)));
strcpy(de.d_name, name);
reclen = DIRSIZ(0, &de, needswap);

View File

@ -1,4 +1,4 @@
/* $NetBSD: makefs.c,v 1.6 2001/11/25 11:22:09 lukem Exp $ */
/* $NetBSD: makefs.c,v 1.7 2001/12/05 11:08:53 lukem Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#ifndef __lint
__RCSID("$NetBSD: makefs.c,v 1.6 2001/11/25 11:22:09 lukem Exp $");
__RCSID("$NetBSD: makefs.c,v 1.7 2001/12/05 11:08:53 lukem Exp $");
#endif /* !__lint */
#include <assert.h>
@ -69,7 +69,7 @@ static fstype_t fstypes[] = {
{ NULL },
};
u_int debug;
uint debug;
struct timespec start_time;

View File

@ -1,4 +1,4 @@
/* $NetBSD: makefs.h,v 1.3 2001/11/25 11:22:09 lukem Exp $ */
/* $NetBSD: makefs.h,v 1.4 2001/12/05 11:08:53 lukem Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -39,10 +39,15 @@
/*
* fsnode - a component of the tree which contains information about the
* file system.
* fsnode -
* a component of the tree; contains a filename, a pointer to
* fsinode, optional symlink name, and tree pointers
*
* A tree of these looks like this:
* fsinode -
* equivalent to an inode, containing target file system inode number,
* refcount (nlink), and stat buffer
*
* A tree of fsnodes looks like this:
*
* name "." "bin" "netbsd"
* type S_IFDIR S_IFDIR S_IFREG
@ -61,22 +66,32 @@
* must be "." when the tree has been built; during build it may
* not be if "." hasn't yet been found by readdir(2).
*
* - if dup is not NULL, it points to an fsnode that this is a
* - if dup is not NULL, it points to an fsent that this is a
* duplicate of; only relevant for non directories with > 1 link
*/
enum fi_flags {
FI_SIZED = 1<<0, /* inode sized */
FI_ALLOCATED = 1<<1, /* fsinode->ino allocated */
FI_WRITTEN = 1<<2, /* inode written */
};
typedef struct {
uint32_t ino; /* inode number used on target fs */
uint32_t nlink; /* number of links to this entry */
enum fi_flags flags; /* flags used by fs specific code */
struct stat st; /* stat entry */
} fsinode;
typedef struct _fsnode {
struct _fsnode *parent; /* parent (NULL if root) */
struct _fsnode *child; /* child (if type == S_IFDIR) */
struct _fsnode *next; /* next */
struct _fsnode *first; /* first node of current level (".") */
struct stat statbuf; /* stat entry */
uint32_t type; /* type of entry */
fsinode *inode; /* actual inode data */
char *symlink; /* symlink target */
char *name; /* file name */
struct _fsnode *dup; /* entry this is a duplicate of
(when statbuf.st_nlink > 1) */
uint32_t nlink; /* number of links to this entry */
uint32_t type; /* type of entry */
uint32_t ino; /* inode number used on target fs */
} fsnode;
@ -151,7 +166,7 @@ void ffs_makefs(const char *, const char *, fsnode *, fsinfo_t *);
extern u_int debug;
extern uint debug;
extern struct timespec start_time;
#define DEBUG_TIME 0x00000001

View File

@ -1,4 +1,4 @@
/* $NetBSD: walk.c,v 1.5 2001/11/02 03:12:48 lukem Exp $ */
/* $NetBSD: walk.c,v 1.6 2001/12/05 11:08:53 lukem Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -77,7 +77,7 @@
#include <sys/cdefs.h>
#ifndef __lint
__RCSID("$NetBSD: walk.c,v 1.5 2001/11/02 03:12:48 lukem Exp $");
__RCSID("$NetBSD: walk.c,v 1.6 2001/12/05 11:08:53 lukem Exp $");
#endif /* !__lint */
#include <sys/param.h>
@ -98,7 +98,8 @@ __RCSID("$NetBSD: walk.c,v 1.5 2001/11/02 03:12:48 lukem Exp $");
static void apply_specdir(const char *, NODE *, fsnode *);
static void apply_specentry(const char *, NODE *, fsnode *);
static fsnode *create_fsnode(const char *, struct stat *);
static fsnode *link_check(fsnode *);
static fsinode *create_fsinode(struct stat *);
static fsinode *link_check(fsinode *);
/*
@ -141,6 +142,7 @@ walk_dir(const char *dir, fsnode *parent)
}
cur = create_fsnode(dent->d_name, &stbuf);
cur->inode = create_fsinode(&stbuf);
cur->parent = parent;
if (strcmp(dent->d_name, ".") == 0) {
/* ensure "." is at the start of the list */
@ -159,10 +161,15 @@ walk_dir(const char *dir, fsnode *parent)
continue;
}
}
if (cur->statbuf.st_nlink > 1) {
cur->dup = link_check(cur);
if (cur->dup)
cur->dup->nlink++;
if (stbuf.st_nlink > 1) {
fsinode *curino;
curino = link_check(cur->inode);
if (curino != NULL) {
free(cur->inode);
cur->inode = curino;
cur->inode->nlink++;
}
}
if (S_ISLNK(cur->type)) {
char slink[PATH_MAX+1];
@ -184,19 +191,28 @@ walk_dir(const char *dir, fsnode *parent)
}
static fsnode *
create_fsnode(const char *name, struct stat *statbuf)
create_fsnode(const char *name, struct stat *stbuf)
{
fsnode *cur;
if ((cur = calloc(1, sizeof(fsnode))) == NULL ||
(cur->name = strdup(name)) == NULL)
err(1, "Memory allocation error");
cur->statbuf = *statbuf;
cur->type = (cur->statbuf.st_mode & S_IFMT);
cur->nlink = 1;
cur->type = stbuf->st_mode & S_IFMT;
return (cur);
}
static fsinode *
create_fsinode(struct stat *statbuf)
{
fsinode *cur;
if ((cur = calloc(1, sizeof(fsinode))) == NULL)
err(1, "Memory allocation error");
cur->nlink = 1;
cur->st = *statbuf;
return (cur);
}
/*
* apply_specfile --
@ -301,6 +317,7 @@ apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode)
/* build minimal fsnode */
memset(&stbuf, 0, sizeof(stbuf));
stbuf.st_mode = nodetoino(curnode->type);
stbuf.st_nlink = 1;
stbuf.st_mtime = stbuf.st_atime =
stbuf.st_ctime = start_time.tv_sec;
stbuf.st_mtimensec = stbuf.st_atimensec =
@ -353,16 +370,6 @@ apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
if (debug & DEBUG_APPLY_SPECENTRY)
printf("apply_specentry: %s/%s\n", dir, dirnode->name);
/*
* if this is a duplicate (i.e, an existing hardlink),
* change the actual settings.
*/
if (dirnode->dup != NULL) {
if (debug & DEBUG_APPLY_SPECENTRY)
printf("\t\t\thard-linked to %s\n", dirnode->dup->name);
dirnode = dirnode->dup;
}
#define ASEPRINT(t, b, o, n) \
if (debug & DEBUG_APPLY_SPECENTRY) \
printf("\t\t\tchanging %s from " b " to " b "\n", \
@ -370,21 +377,21 @@ apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
if (specnode->flags & (F_GID | F_GNAME)) {
ASEPRINT("gid", "%d",
dirnode->statbuf.st_gid, specnode->st_gid);
dirnode->statbuf.st_gid = specnode->st_gid;
dirnode->inode->st.st_gid, specnode->st_gid);
dirnode->inode->st.st_gid = specnode->st_gid;
}
if (specnode->flags & F_MODE) {
ASEPRINT("mode", "%#o",
dirnode->statbuf.st_mode & ALLPERMS, specnode->st_mode);
dirnode->statbuf.st_mode &= ~ALLPERMS;
dirnode->statbuf.st_mode |= (specnode->st_mode & ALLPERMS);
dirnode->inode->st.st_mode & ALLPERMS, specnode->st_mode);
dirnode->inode->st.st_mode &= ~ALLPERMS;
dirnode->inode->st.st_mode |= (specnode->st_mode & ALLPERMS);
}
/* XXX: ignoring F_NLINK for now */
if (specnode->flags & F_SIZE) {
ASEPRINT("size", "%lld",
(long long)dirnode->statbuf.st_size,
(long long)dirnode->inode->st.st_size,
(long long)specnode->st_size);
dirnode->statbuf.st_size = specnode->st_size;
dirnode->inode->st.st_size = specnode->st_size;
}
if (specnode->flags & F_SLINK) {
assert(dirnode->symlink != NULL);
@ -396,29 +403,30 @@ apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
}
if (specnode->flags & F_TIME) {
ASEPRINT("time", "%ld",
(long)dirnode->statbuf.st_mtime, (long)specnode->st_mtime);
dirnode->statbuf.st_mtime = specnode->st_mtime;
dirnode->statbuf.st_mtimensec = specnode->st_mtimensec;
dirnode->statbuf.st_atime = specnode->st_mtime;
dirnode->statbuf.st_atimensec = specnode->st_mtimensec;
dirnode->statbuf.st_ctime = start_time.tv_sec;
dirnode->statbuf.st_ctimensec = start_time.tv_nsec;
(long)dirnode->inode->st.st_mtime,
(long)specnode->st_mtime);
dirnode->inode->st.st_mtime = specnode->st_mtime;
dirnode->inode->st.st_mtimensec = specnode->st_mtimensec;
dirnode->inode->st.st_atime = specnode->st_mtime;
dirnode->inode->st.st_atimensec = specnode->st_mtimensec;
dirnode->inode->st.st_ctime = start_time.tv_sec;
dirnode->inode->st.st_ctimensec = start_time.tv_nsec;
}
if (specnode->flags & (F_UID | F_UNAME)) {
ASEPRINT("uid", "%d",
dirnode->statbuf.st_uid, specnode->st_uid);
dirnode->statbuf.st_uid = specnode->st_uid;
dirnode->inode->st.st_uid, specnode->st_uid);
dirnode->inode->st.st_uid = specnode->st_uid;
}
if (specnode->flags & F_FLAGS) {
ASEPRINT("flags", "%#lX",
(u_long)dirnode->statbuf.st_flags,
(u_long)specnode->st_flags);
dirnode->statbuf.st_flags = specnode->st_flags;
(ulong)dirnode->inode->st.st_flags,
(ulong)specnode->st_flags);
dirnode->inode->st.st_flags = specnode->st_flags;
}
if (specnode->flags & F_DEV) {
ASEPRINT("rdev", "%#x",
dirnode->statbuf.st_rdev, specnode->st_rdev);
dirnode->statbuf.st_rdev = specnode->st_rdev;
dirnode->inode->st.st_rdev, specnode->st_rdev);
dirnode->inode->st.st_rdev = specnode->st_rdev;
}
#undef ASEPRINT
}
@ -451,11 +459,8 @@ dump_fsnodes(const char *dir, fsnode *root)
} else {
assert (cur->symlink == NULL);
}
if (cur->dup != NULL) {
printf(", hard-linked to %s", cur->dup->name);
}
if (cur->nlink > 1)
printf(", nlinks=%d", cur->nlink);
if (cur->inode->nlink > 1)
printf(", nlinks=%d", cur->inode->nlink);
putchar('\n');
if (cur->child) {
@ -482,21 +487,19 @@ inode_type(mode_t mode)
}
typedef struct {
int32_t dev;
int32_t ino;
fsnode *dup;
} dupnode;
/*
* link_check --
* return pointer to fsnode matching `entry's st_ino & st_dev if it exists,
* otherwise add `entry' to table and return NULL
*/
static fsnode *
link_check(fsnode *entry)
static fsinode *
link_check(fsinode *entry)
{
static dupnode *dups;
static struct dupnode {
uint32_t dev;
uint32_t ino;
fsinode *dup;
} *dups;
static int ndups, maxdups;
int i;
@ -505,27 +508,26 @@ link_check(fsnode *entry)
/* XXX; maybe traverse in reverse for speed? */
for (i = 0; i < ndups; i++) {
if (dups[i].dev == entry->statbuf.st_dev &&
dups[i].ino == entry->statbuf.st_ino) {
if (dups[i].dev == entry->st.st_dev &&
dups[i].ino == entry->st.st_ino) {
if (debug & DEBUG_WALK_DIR_LINKCHECK)
printf(
"link_check: %s (%d,%d) linked to %s\n",
entry->name, entry->statbuf.st_dev,
entry->statbuf.st_ino, dups[i].dup->name);
printf("link_check: found [%d,%d]\n",
entry->st.st_dev, entry->st.st_ino);
return (dups[i].dup);
}
}
if (debug & DEBUG_WALK_DIR_LINKCHECK)
printf("link_check: no match for %s (%d, %d)\n",
entry->name, entry->statbuf.st_dev, entry->statbuf.st_ino);
printf("link_check: no match for [%d, %d]\n",
entry->st.st_dev, entry->st.st_ino);
if (ndups == maxdups) {
maxdups += 128;
if ((dups = realloc(dups, sizeof(dupnode) * maxdups)) == NULL)
if ((dups = realloc(dups, sizeof(struct dupnode) * maxdups))
== NULL)
err(1, "Memory allocation error");
}
dups[ndups].dev = entry->statbuf.st_dev;
dups[ndups].ino = entry->statbuf.st_ino;
dups[ndups].dev = entry->st.st_dev;
dups[ndups].ino = entry->st.st_ino;
dups[ndups].dup = entry;
ndups++;