Teach fsck about snapshot files. These changes should have no

effect on operation of fsck on filesystems without snapshots.
If you get compilation errors, be sure that you have copies of
/usr/include/sys/mount.h (1.94), /usr/include/sys/stat.h (1.21),
and /usr/include/ufs/ffs/fs.h (1.16) as of July 4, 2000 or later.
This commit is contained in:
Kirk McKusick 2000-07-06 02:03:11 +00:00
parent 8b15840355
commit 142d8d2f40
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=62668
18 changed files with 363 additions and 45 deletions

View File

@ -241,7 +241,7 @@ dircheck(idesc, dp)
if (dp->d_reclen == 0 ||
dp->d_reclen > spaceleft ||
(dp->d_reclen & 0x3) != 0)
return (0);
goto bad;
if (dp->d_ino == 0)
return (1);
size = DIRSIZ(!newinofmt, dp);
@ -261,13 +261,19 @@ dircheck(idesc, dp)
idesc->id_filesize < size ||
namlen > MAXNAMLEN ||
type > 15)
return (0);
goto bad;
for (cp = dp->d_name, size = 0; size < namlen; size++)
if (*cp == '\0' || (*cp++ == '/'))
return (0);
goto bad;
if (*cp != '\0')
return (0);
goto bad;
return (1);
bad:
if (debug)
printf("Bad dir: ino %d reclen %d namlen %d type %d name %s\n",
dp->d_ino, dp->d_reclen, dp->d_namlen, dp->d_type,
dp->d_name);
return (0);
}
void

View File

@ -114,12 +114,14 @@ struct bufarea *pbp; /* current inode block */
#define cgrp (*cgblk.b_un.b_cg)
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
ino_t cursnapshot;
struct inodesc {
enum fixstate id_fix; /* policy on fixing errors */
int (*id_func)(); /* function to be applied to blocks of inode */
ino_t id_number; /* inode number described */
ino_t id_parent; /* for DATA nodes, their parent */
int id_lbn; /* logical block number of current block */
ufs_daddr_t id_blkno; /* current block number being examined */
int id_numfrags; /* number of frags contained in block */
quad_t id_filesize; /* for DATA nodes, the size of the directory */
@ -130,8 +132,9 @@ struct inodesc {
char id_type; /* type of descriptor, DATA or ADDR */
};
/* file types */
#define DATA 1
#define ADDR 2
#define DATA 1 /* a directory */
#define SNAP 2 /* a snapshot */
#define ADDR 3 /* anything but a directory or a snapshot */
/*
* Linked list of duplicate blocks.

View File

@ -71,6 +71,7 @@ ckinode(dp, idesc)
if (idesc->id_fix != IGNORE)
idesc->id_fix = DONTKNOW;
idesc->id_lbn = -1;
idesc->id_entryno = 0;
idesc->id_filesize = dp->di_size;
mode = dp->di_mode & IFMT;
@ -80,6 +81,7 @@ ckinode(dp, idesc)
dino = *dp;
ndb = howmany(dino.di_size, sblock.fs_bsize);
for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
idesc->id_lbn++;
if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
idesc->id_numfrags =
numfrags(&sblock, fragroundup(&sblock, offset));
@ -106,7 +108,7 @@ ckinode(dp, idesc)
continue;
}
idesc->id_blkno = *ap;
if (idesc->id_type == ADDR)
if (idesc->id_type != DATA)
ret = (*idesc->id_func)(idesc);
else
ret = dirscan(idesc);
@ -117,12 +119,14 @@ ckinode(dp, idesc)
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
sizepb = sblock.fs_bsize;
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
sizepb *= NINDIR(&sblock);
if (*ap) {
idesc->id_blkno = *ap;
ret = iblock(idesc, n, remsize);
if (ret & STOP)
return (ret);
} else {
idesc->id_lbn += sizepb / sblock.fs_bsize;
if (idesc->id_type == DATA && remsize > 0) {
/* An empty block in a directory XXX */
getpathname(pathbuf, idesc->id_number,
@ -141,7 +145,6 @@ ckinode(dp, idesc)
}
}
}
sizepb *= NINDIR(&sblock);
remsize -= sizepb;
}
return (KEEPON);
@ -162,7 +165,7 @@ iblock(idesc, ilevel, isize)
char pathbuf[MAXPATHLEN + 1];
struct dinode *dp;
if (idesc->id_type == ADDR) {
if (idesc->id_type != DATA) {
func = idesc->id_func;
if (((n = (*func)(idesc)) & KEEPON) == 0)
return (n);
@ -193,6 +196,8 @@ iblock(idesc, ilevel, isize)
}
aplim = &bp->b_un.b_indir[nif];
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
if (ilevel == 0)
idesc->id_lbn++;
if (*ap) {
idesc->id_blkno = *ap;
if (ilevel == 0)

View File

@ -40,6 +40,7 @@ static const char rcsid[] =
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@ -82,7 +83,6 @@ pass1()
* Find all allocated blocks.
*/
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass1check;
n_files = n_blks = 0;
for (c = 0; c < sblock.fs_ncg; c++) {
@ -306,6 +306,10 @@ checkinode(inumber, idesc)
}
badblk = dupblk = 0;
idesc->id_number = inumber;
if (dp->di_flags & SF_SNAPSHOT)
idesc->id_type = SNAP;
else
idesc->id_type = ADDR;
(void)ckinode(dp, idesc);
idesc->id_entryno *= btodb(sblock.fs_fsize);
if (dp->di_blocks != idesc->id_entryno) {
@ -341,6 +345,21 @@ pass1check(idesc)
register struct dups *dlp;
struct dups *new;
if (idesc->id_type == SNAP) {
if (blkno == BLK_NOCOPY)
return (KEEPON);
if (idesc->id_number == cursnapshot) {
if (blkno == blkstofrags(&sblock, idesc->id_lbn))
return (KEEPON);
if (blkno == BLK_SNAP) {
blkno = blkstofrags(&sblock, idesc->id_lbn);
idesc->id_entryno -= idesc->id_numfrags;
}
} else {
if (blkno == BLK_SNAP)
return (KEEPON);
}
}
if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
blkerror(idesc->id_number, "BAD", blkno);
if (badblk++ >= MAXBAD) {

View File

@ -53,12 +53,12 @@ void
pass5()
{
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
int inomapsize, blkmapsize;
int inomapsize, blkmapsize, astart, aend, ustart, uend;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
ufs_daddr_t dbase, dmax;
ufs_daddr_t d;
long i, j, k;
long i, j, k, l, m, n;
struct csum *cs;
struct csum cstotal;
struct inodesc idesc[3];
@ -314,6 +314,72 @@ pass5()
&cg_blktot(newcg)[0], (size_t)sumsize);
cgdirty();
}
if (debug) {
for (i = 0; i < inomapsize; i++) {
j = cg_inosused(newcg)[i];
k = cg_inosused(cg)[i];
if (j == k)
continue;
for (m = 0, l = 1; m < NBBY; m++, l <<= 1) {
if ((j & l) == (k & l))
continue;
n = c * fs->fs_ipg + i * NBBY + m;
if ((j & l) != 0)
pwarn("%s INODE %d MARKED %s\n",
"ALLOCATED", n, "FREE");
else
pwarn("%s INODE %d MARKED %s\n",
"UNALLOCATED", n, "USED");
}
}
astart = ustart = -1;
for (i = 0; i < blkmapsize; i++) {
j = cg_blksfree(cg)[i];
k = cg_blksfree(newcg)[i];
if (j == k)
continue;
for (m = 0, l = 1; m < NBBY; m++, l <<= 1) {
if ((j & l) == (k & l))
continue;
n = c * fs->fs_fpg + i * NBBY + m;
if ((j & l) != 0) {
if (astart == -1) {
astart = aend = n;
continue;
}
if (aend + 1 == n) {
aend = n;
continue;
}
pwarn("%s FRAGS %d-%d %s\n",
"ALLOCATED", astart, aend,
"MARKED FREE");
astart = aend = n;
} else {
if (ustart == -1) {
ustart = uend = n;
continue;
}
if (uend + 1 == n) {
uend = n;
continue;
}
pwarn("%s FRAGS %d-%d %s\n",
"UNALLOCATED", ustart, uend,
"MARKED USED");
ustart = uend = n;
}
}
}
if (astart != -1)
pwarn("%s FRAGS %d-%d %s\n",
"ALLOCATED", astart, aend,
"MARKED FREE");
if (ustart != -1)
pwarn("%s FRAGS %d-%d %s\n",
"UNALLOCATED", ustart, uend,
"MARKED USED");
}
if (usedsoftdep) {
for (i = 0; i < inomapsize; i++) {
j = cg_inosused(newcg)[i];

View File

@ -82,6 +82,7 @@ setup(dev)
havesb = 0;
fswritefd = -1;
cursnapshot = 0;
skipclean = fflag ? 0 : preen;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
@ -89,9 +90,13 @@ setup(dev)
}
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
(statb.st_mode & S_IFMT) != S_IFBLK) {
pfatal("%s is not a disk device", dev);
if (reply("CONTINUE") == 0)
return (0);
if ((statb.st_flags & SF_SNAPSHOT) != 0) {
cursnapshot = statb.st_ino;
} else {
pfatal("%s is not a disk device", dev);
if (reply("CONTINUE") == 0)
return (0);
}
}
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
printf("Can't open %s: %s\n", dev, strerror(errno));
@ -378,6 +383,8 @@ readsb(listerr)
memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp);
altsblock.fs_maxcluster = sblock.fs_maxcluster;
memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt);
memmove(altsblock.fs_snapinum, sblock.fs_snapinum,
sizeof sblock.fs_snapinum);
memmove(altsblock.fs_sparecon,
sblock.fs_sparecon, sizeof sblock.fs_sparecon);
/*

View File

@ -241,7 +241,7 @@ dircheck(idesc, dp)
if (dp->d_reclen == 0 ||
dp->d_reclen > spaceleft ||
(dp->d_reclen & 0x3) != 0)
return (0);
goto bad;
if (dp->d_ino == 0)
return (1);
size = DIRSIZ(!newinofmt, dp);
@ -261,13 +261,19 @@ dircheck(idesc, dp)
idesc->id_filesize < size ||
namlen > MAXNAMLEN ||
type > 15)
return (0);
goto bad;
for (cp = dp->d_name, size = 0; size < namlen; size++)
if (*cp == '\0' || (*cp++ == '/'))
return (0);
goto bad;
if (*cp != '\0')
return (0);
goto bad;
return (1);
bad:
if (debug)
printf("Bad dir: ino %d reclen %d namlen %d type %d name %s\n",
dp->d_ino, dp->d_reclen, dp->d_namlen, dp->d_type,
dp->d_name);
return (0);
}
void

View File

@ -114,12 +114,14 @@ struct bufarea *pbp; /* current inode block */
#define cgrp (*cgblk.b_un.b_cg)
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
ino_t cursnapshot;
struct inodesc {
enum fixstate id_fix; /* policy on fixing errors */
int (*id_func)(); /* function to be applied to blocks of inode */
ino_t id_number; /* inode number described */
ino_t id_parent; /* for DATA nodes, their parent */
int id_lbn; /* logical block number of current block */
ufs_daddr_t id_blkno; /* current block number being examined */
int id_numfrags; /* number of frags contained in block */
quad_t id_filesize; /* for DATA nodes, the size of the directory */
@ -130,8 +132,9 @@ struct inodesc {
char id_type; /* type of descriptor, DATA or ADDR */
};
/* file types */
#define DATA 1
#define ADDR 2
#define DATA 1 /* a directory */
#define SNAP 2 /* a snapshot */
#define ADDR 3 /* anything but a directory or a snapshot */
/*
* Linked list of duplicate blocks.

View File

@ -71,6 +71,7 @@ ckinode(dp, idesc)
if (idesc->id_fix != IGNORE)
idesc->id_fix = DONTKNOW;
idesc->id_lbn = -1;
idesc->id_entryno = 0;
idesc->id_filesize = dp->di_size;
mode = dp->di_mode & IFMT;
@ -80,6 +81,7 @@ ckinode(dp, idesc)
dino = *dp;
ndb = howmany(dino.di_size, sblock.fs_bsize);
for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
idesc->id_lbn++;
if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
idesc->id_numfrags =
numfrags(&sblock, fragroundup(&sblock, offset));
@ -106,7 +108,7 @@ ckinode(dp, idesc)
continue;
}
idesc->id_blkno = *ap;
if (idesc->id_type == ADDR)
if (idesc->id_type != DATA)
ret = (*idesc->id_func)(idesc);
else
ret = dirscan(idesc);
@ -117,12 +119,14 @@ ckinode(dp, idesc)
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
sizepb = sblock.fs_bsize;
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
sizepb *= NINDIR(&sblock);
if (*ap) {
idesc->id_blkno = *ap;
ret = iblock(idesc, n, remsize);
if (ret & STOP)
return (ret);
} else {
idesc->id_lbn += sizepb / sblock.fs_bsize;
if (idesc->id_type == DATA && remsize > 0) {
/* An empty block in a directory XXX */
getpathname(pathbuf, idesc->id_number,
@ -141,7 +145,6 @@ ckinode(dp, idesc)
}
}
}
sizepb *= NINDIR(&sblock);
remsize -= sizepb;
}
return (KEEPON);
@ -162,7 +165,7 @@ iblock(idesc, ilevel, isize)
char pathbuf[MAXPATHLEN + 1];
struct dinode *dp;
if (idesc->id_type == ADDR) {
if (idesc->id_type != DATA) {
func = idesc->id_func;
if (((n = (*func)(idesc)) & KEEPON) == 0)
return (n);
@ -193,6 +196,8 @@ iblock(idesc, ilevel, isize)
}
aplim = &bp->b_un.b_indir[nif];
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
if (ilevel == 0)
idesc->id_lbn++;
if (*ap) {
idesc->id_blkno = *ap;
if (ilevel == 0)

View File

@ -40,6 +40,7 @@ static const char rcsid[] =
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@ -82,7 +83,6 @@ pass1()
* Find all allocated blocks.
*/
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass1check;
n_files = n_blks = 0;
for (c = 0; c < sblock.fs_ncg; c++) {
@ -306,6 +306,10 @@ checkinode(inumber, idesc)
}
badblk = dupblk = 0;
idesc->id_number = inumber;
if (dp->di_flags & SF_SNAPSHOT)
idesc->id_type = SNAP;
else
idesc->id_type = ADDR;
(void)ckinode(dp, idesc);
idesc->id_entryno *= btodb(sblock.fs_fsize);
if (dp->di_blocks != idesc->id_entryno) {
@ -341,6 +345,21 @@ pass1check(idesc)
register struct dups *dlp;
struct dups *new;
if (idesc->id_type == SNAP) {
if (blkno == BLK_NOCOPY)
return (KEEPON);
if (idesc->id_number == cursnapshot) {
if (blkno == blkstofrags(&sblock, idesc->id_lbn))
return (KEEPON);
if (blkno == BLK_SNAP) {
blkno = blkstofrags(&sblock, idesc->id_lbn);
idesc->id_entryno -= idesc->id_numfrags;
}
} else {
if (blkno == BLK_SNAP)
return (KEEPON);
}
}
if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
blkerror(idesc->id_number, "BAD", blkno);
if (badblk++ >= MAXBAD) {

View File

@ -53,12 +53,12 @@ void
pass5()
{
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
int inomapsize, blkmapsize;
int inomapsize, blkmapsize, astart, aend, ustart, uend;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
ufs_daddr_t dbase, dmax;
ufs_daddr_t d;
long i, j, k;
long i, j, k, l, m, n;
struct csum *cs;
struct csum cstotal;
struct inodesc idesc[3];
@ -314,6 +314,72 @@ pass5()
&cg_blktot(newcg)[0], (size_t)sumsize);
cgdirty();
}
if (debug) {
for (i = 0; i < inomapsize; i++) {
j = cg_inosused(newcg)[i];
k = cg_inosused(cg)[i];
if (j == k)
continue;
for (m = 0, l = 1; m < NBBY; m++, l <<= 1) {
if ((j & l) == (k & l))
continue;
n = c * fs->fs_ipg + i * NBBY + m;
if ((j & l) != 0)
pwarn("%s INODE %d MARKED %s\n",
"ALLOCATED", n, "FREE");
else
pwarn("%s INODE %d MARKED %s\n",
"UNALLOCATED", n, "USED");
}
}
astart = ustart = -1;
for (i = 0; i < blkmapsize; i++) {
j = cg_blksfree(cg)[i];
k = cg_blksfree(newcg)[i];
if (j == k)
continue;
for (m = 0, l = 1; m < NBBY; m++, l <<= 1) {
if ((j & l) == (k & l))
continue;
n = c * fs->fs_fpg + i * NBBY + m;
if ((j & l) != 0) {
if (astart == -1) {
astart = aend = n;
continue;
}
if (aend + 1 == n) {
aend = n;
continue;
}
pwarn("%s FRAGS %d-%d %s\n",
"ALLOCATED", astart, aend,
"MARKED FREE");
astart = aend = n;
} else {
if (ustart == -1) {
ustart = uend = n;
continue;
}
if (uend + 1 == n) {
uend = n;
continue;
}
pwarn("%s FRAGS %d-%d %s\n",
"UNALLOCATED", ustart, uend,
"MARKED USED");
ustart = uend = n;
}
}
}
if (astart != -1)
pwarn("%s FRAGS %d-%d %s\n",
"ALLOCATED", astart, aend,
"MARKED FREE");
if (ustart != -1)
pwarn("%s FRAGS %d-%d %s\n",
"UNALLOCATED", ustart, uend,
"MARKED USED");
}
if (usedsoftdep) {
for (i = 0; i < inomapsize; i++) {
j = cg_inosused(newcg)[i];

View File

@ -82,6 +82,7 @@ setup(dev)
havesb = 0;
fswritefd = -1;
cursnapshot = 0;
skipclean = fflag ? 0 : preen;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
@ -89,9 +90,13 @@ setup(dev)
}
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
(statb.st_mode & S_IFMT) != S_IFBLK) {
pfatal("%s is not a disk device", dev);
if (reply("CONTINUE") == 0)
return (0);
if ((statb.st_flags & SF_SNAPSHOT) != 0) {
cursnapshot = statb.st_ino;
} else {
pfatal("%s is not a disk device", dev);
if (reply("CONTINUE") == 0)
return (0);
}
}
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
printf("Can't open %s: %s\n", dev, strerror(errno));
@ -378,6 +383,8 @@ readsb(listerr)
memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp);
altsblock.fs_maxcluster = sblock.fs_maxcluster;
memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt);
memmove(altsblock.fs_snapinum, sblock.fs_snapinum,
sizeof sblock.fs_snapinum);
memmove(altsblock.fs_sparecon,
sblock.fs_sparecon, sizeof sblock.fs_sparecon);
/*

View File

@ -241,7 +241,7 @@ dircheck(idesc, dp)
if (dp->d_reclen == 0 ||
dp->d_reclen > spaceleft ||
(dp->d_reclen & 0x3) != 0)
return (0);
goto bad;
if (dp->d_ino == 0)
return (1);
size = DIRSIZ(!newinofmt, dp);
@ -261,13 +261,19 @@ dircheck(idesc, dp)
idesc->id_filesize < size ||
namlen > MAXNAMLEN ||
type > 15)
return (0);
goto bad;
for (cp = dp->d_name, size = 0; size < namlen; size++)
if (*cp == '\0' || (*cp++ == '/'))
return (0);
goto bad;
if (*cp != '\0')
return (0);
goto bad;
return (1);
bad:
if (debug)
printf("Bad dir: ino %d reclen %d namlen %d type %d name %s\n",
dp->d_ino, dp->d_reclen, dp->d_namlen, dp->d_type,
dp->d_name);
return (0);
}
void

View File

@ -114,12 +114,14 @@ struct bufarea *pbp; /* current inode block */
#define cgrp (*cgblk.b_un.b_cg)
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
ino_t cursnapshot;
struct inodesc {
enum fixstate id_fix; /* policy on fixing errors */
int (*id_func)(); /* function to be applied to blocks of inode */
ino_t id_number; /* inode number described */
ino_t id_parent; /* for DATA nodes, their parent */
int id_lbn; /* logical block number of current block */
ufs_daddr_t id_blkno; /* current block number being examined */
int id_numfrags; /* number of frags contained in block */
quad_t id_filesize; /* for DATA nodes, the size of the directory */
@ -130,8 +132,9 @@ struct inodesc {
char id_type; /* type of descriptor, DATA or ADDR */
};
/* file types */
#define DATA 1
#define ADDR 2
#define DATA 1 /* a directory */
#define SNAP 2 /* a snapshot */
#define ADDR 3 /* anything but a directory or a snapshot */
/*
* Linked list of duplicate blocks.

View File

@ -71,6 +71,7 @@ ckinode(dp, idesc)
if (idesc->id_fix != IGNORE)
idesc->id_fix = DONTKNOW;
idesc->id_lbn = -1;
idesc->id_entryno = 0;
idesc->id_filesize = dp->di_size;
mode = dp->di_mode & IFMT;
@ -80,6 +81,7 @@ ckinode(dp, idesc)
dino = *dp;
ndb = howmany(dino.di_size, sblock.fs_bsize);
for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
idesc->id_lbn++;
if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
idesc->id_numfrags =
numfrags(&sblock, fragroundup(&sblock, offset));
@ -106,7 +108,7 @@ ckinode(dp, idesc)
continue;
}
idesc->id_blkno = *ap;
if (idesc->id_type == ADDR)
if (idesc->id_type != DATA)
ret = (*idesc->id_func)(idesc);
else
ret = dirscan(idesc);
@ -117,12 +119,14 @@ ckinode(dp, idesc)
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
sizepb = sblock.fs_bsize;
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
sizepb *= NINDIR(&sblock);
if (*ap) {
idesc->id_blkno = *ap;
ret = iblock(idesc, n, remsize);
if (ret & STOP)
return (ret);
} else {
idesc->id_lbn += sizepb / sblock.fs_bsize;
if (idesc->id_type == DATA && remsize > 0) {
/* An empty block in a directory XXX */
getpathname(pathbuf, idesc->id_number,
@ -141,7 +145,6 @@ ckinode(dp, idesc)
}
}
}
sizepb *= NINDIR(&sblock);
remsize -= sizepb;
}
return (KEEPON);
@ -162,7 +165,7 @@ iblock(idesc, ilevel, isize)
char pathbuf[MAXPATHLEN + 1];
struct dinode *dp;
if (idesc->id_type == ADDR) {
if (idesc->id_type != DATA) {
func = idesc->id_func;
if (((n = (*func)(idesc)) & KEEPON) == 0)
return (n);
@ -193,6 +196,8 @@ iblock(idesc, ilevel, isize)
}
aplim = &bp->b_un.b_indir[nif];
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
if (ilevel == 0)
idesc->id_lbn++;
if (*ap) {
idesc->id_blkno = *ap;
if (ilevel == 0)

View File

@ -40,6 +40,7 @@ static const char rcsid[] =
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@ -82,7 +83,6 @@ pass1()
* Find all allocated blocks.
*/
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass1check;
n_files = n_blks = 0;
for (c = 0; c < sblock.fs_ncg; c++) {
@ -306,6 +306,10 @@ checkinode(inumber, idesc)
}
badblk = dupblk = 0;
idesc->id_number = inumber;
if (dp->di_flags & SF_SNAPSHOT)
idesc->id_type = SNAP;
else
idesc->id_type = ADDR;
(void)ckinode(dp, idesc);
idesc->id_entryno *= btodb(sblock.fs_fsize);
if (dp->di_blocks != idesc->id_entryno) {
@ -341,6 +345,21 @@ pass1check(idesc)
register struct dups *dlp;
struct dups *new;
if (idesc->id_type == SNAP) {
if (blkno == BLK_NOCOPY)
return (KEEPON);
if (idesc->id_number == cursnapshot) {
if (blkno == blkstofrags(&sblock, idesc->id_lbn))
return (KEEPON);
if (blkno == BLK_SNAP) {
blkno = blkstofrags(&sblock, idesc->id_lbn);
idesc->id_entryno -= idesc->id_numfrags;
}
} else {
if (blkno == BLK_SNAP)
return (KEEPON);
}
}
if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
blkerror(idesc->id_number, "BAD", blkno);
if (badblk++ >= MAXBAD) {

View File

@ -53,12 +53,12 @@ void
pass5()
{
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
int inomapsize, blkmapsize;
int inomapsize, blkmapsize, astart, aend, ustart, uend;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
ufs_daddr_t dbase, dmax;
ufs_daddr_t d;
long i, j, k;
long i, j, k, l, m, n;
struct csum *cs;
struct csum cstotal;
struct inodesc idesc[3];
@ -314,6 +314,72 @@ pass5()
&cg_blktot(newcg)[0], (size_t)sumsize);
cgdirty();
}
if (debug) {
for (i = 0; i < inomapsize; i++) {
j = cg_inosused(newcg)[i];
k = cg_inosused(cg)[i];
if (j == k)
continue;
for (m = 0, l = 1; m < NBBY; m++, l <<= 1) {
if ((j & l) == (k & l))
continue;
n = c * fs->fs_ipg + i * NBBY + m;
if ((j & l) != 0)
pwarn("%s INODE %d MARKED %s\n",
"ALLOCATED", n, "FREE");
else
pwarn("%s INODE %d MARKED %s\n",
"UNALLOCATED", n, "USED");
}
}
astart = ustart = -1;
for (i = 0; i < blkmapsize; i++) {
j = cg_blksfree(cg)[i];
k = cg_blksfree(newcg)[i];
if (j == k)
continue;
for (m = 0, l = 1; m < NBBY; m++, l <<= 1) {
if ((j & l) == (k & l))
continue;
n = c * fs->fs_fpg + i * NBBY + m;
if ((j & l) != 0) {
if (astart == -1) {
astart = aend = n;
continue;
}
if (aend + 1 == n) {
aend = n;
continue;
}
pwarn("%s FRAGS %d-%d %s\n",
"ALLOCATED", astart, aend,
"MARKED FREE");
astart = aend = n;
} else {
if (ustart == -1) {
ustart = uend = n;
continue;
}
if (uend + 1 == n) {
uend = n;
continue;
}
pwarn("%s FRAGS %d-%d %s\n",
"UNALLOCATED", ustart, uend,
"MARKED USED");
ustart = uend = n;
}
}
}
if (astart != -1)
pwarn("%s FRAGS %d-%d %s\n",
"ALLOCATED", astart, aend,
"MARKED FREE");
if (ustart != -1)
pwarn("%s FRAGS %d-%d %s\n",
"UNALLOCATED", ustart, uend,
"MARKED USED");
}
if (usedsoftdep) {
for (i = 0; i < inomapsize; i++) {
j = cg_inosused(newcg)[i];

View File

@ -82,6 +82,7 @@ setup(dev)
havesb = 0;
fswritefd = -1;
cursnapshot = 0;
skipclean = fflag ? 0 : preen;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
@ -89,9 +90,13 @@ setup(dev)
}
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
(statb.st_mode & S_IFMT) != S_IFBLK) {
pfatal("%s is not a disk device", dev);
if (reply("CONTINUE") == 0)
return (0);
if ((statb.st_flags & SF_SNAPSHOT) != 0) {
cursnapshot = statb.st_ino;
} else {
pfatal("%s is not a disk device", dev);
if (reply("CONTINUE") == 0)
return (0);
}
}
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
printf("Can't open %s: %s\n", dev, strerror(errno));
@ -378,6 +383,8 @@ readsb(listerr)
memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp);
altsblock.fs_maxcluster = sblock.fs_maxcluster;
memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt);
memmove(altsblock.fs_snapinum, sblock.fs_snapinum,
sizeof sblock.fs_snapinum);
memmove(altsblock.fs_sparecon,
sblock.fs_sparecon, sizeof sblock.fs_sparecon);
/*