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:
+10
-4
@@ -241,7 +241,7 @@ dircheck(idesc, dp)
|
|||||||
if (dp->d_reclen == 0 ||
|
if (dp->d_reclen == 0 ||
|
||||||
dp->d_reclen > spaceleft ||
|
dp->d_reclen > spaceleft ||
|
||||||
(dp->d_reclen & 0x3) != 0)
|
(dp->d_reclen & 0x3) != 0)
|
||||||
return (0);
|
goto bad;
|
||||||
if (dp->d_ino == 0)
|
if (dp->d_ino == 0)
|
||||||
return (1);
|
return (1);
|
||||||
size = DIRSIZ(!newinofmt, dp);
|
size = DIRSIZ(!newinofmt, dp);
|
||||||
@@ -261,13 +261,19 @@ dircheck(idesc, dp)
|
|||||||
idesc->id_filesize < size ||
|
idesc->id_filesize < size ||
|
||||||
namlen > MAXNAMLEN ||
|
namlen > MAXNAMLEN ||
|
||||||
type > 15)
|
type > 15)
|
||||||
return (0);
|
goto bad;
|
||||||
for (cp = dp->d_name, size = 0; size < namlen; size++)
|
for (cp = dp->d_name, size = 0; size < namlen; size++)
|
||||||
if (*cp == '\0' || (*cp++ == '/'))
|
if (*cp == '\0' || (*cp++ == '/'))
|
||||||
return (0);
|
goto bad;
|
||||||
if (*cp != '\0')
|
if (*cp != '\0')
|
||||||
return (0);
|
goto bad;
|
||||||
return (1);
|
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
|
void
|
||||||
|
|||||||
+5
-2
@@ -114,12 +114,14 @@ struct bufarea *pbp; /* current inode block */
|
|||||||
#define cgrp (*cgblk.b_un.b_cg)
|
#define cgrp (*cgblk.b_un.b_cg)
|
||||||
|
|
||||||
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
|
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
|
||||||
|
ino_t cursnapshot;
|
||||||
|
|
||||||
struct inodesc {
|
struct inodesc {
|
||||||
enum fixstate id_fix; /* policy on fixing errors */
|
enum fixstate id_fix; /* policy on fixing errors */
|
||||||
int (*id_func)(); /* function to be applied to blocks of inode */
|
int (*id_func)(); /* function to be applied to blocks of inode */
|
||||||
ino_t id_number; /* inode number described */
|
ino_t id_number; /* inode number described */
|
||||||
ino_t id_parent; /* for DATA nodes, their parent */
|
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 */
|
ufs_daddr_t id_blkno; /* current block number being examined */
|
||||||
int id_numfrags; /* number of frags contained in block */
|
int id_numfrags; /* number of frags contained in block */
|
||||||
quad_t id_filesize; /* for DATA nodes, the size of the directory */
|
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 */
|
char id_type; /* type of descriptor, DATA or ADDR */
|
||||||
};
|
};
|
||||||
/* file types */
|
/* file types */
|
||||||
#define DATA 1
|
#define DATA 1 /* a directory */
|
||||||
#define ADDR 2
|
#define SNAP 2 /* a snapshot */
|
||||||
|
#define ADDR 3 /* anything but a directory or a snapshot */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Linked list of duplicate blocks.
|
* Linked list of duplicate blocks.
|
||||||
|
|||||||
+8
-3
@@ -71,6 +71,7 @@ ckinode(dp, idesc)
|
|||||||
|
|
||||||
if (idesc->id_fix != IGNORE)
|
if (idesc->id_fix != IGNORE)
|
||||||
idesc->id_fix = DONTKNOW;
|
idesc->id_fix = DONTKNOW;
|
||||||
|
idesc->id_lbn = -1;
|
||||||
idesc->id_entryno = 0;
|
idesc->id_entryno = 0;
|
||||||
idesc->id_filesize = dp->di_size;
|
idesc->id_filesize = dp->di_size;
|
||||||
mode = dp->di_mode & IFMT;
|
mode = dp->di_mode & IFMT;
|
||||||
@@ -80,6 +81,7 @@ ckinode(dp, idesc)
|
|||||||
dino = *dp;
|
dino = *dp;
|
||||||
ndb = howmany(dino.di_size, sblock.fs_bsize);
|
ndb = howmany(dino.di_size, sblock.fs_bsize);
|
||||||
for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
|
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)
|
if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
|
||||||
idesc->id_numfrags =
|
idesc->id_numfrags =
|
||||||
numfrags(&sblock, fragroundup(&sblock, offset));
|
numfrags(&sblock, fragroundup(&sblock, offset));
|
||||||
@@ -106,7 +108,7 @@ ckinode(dp, idesc)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
idesc->id_blkno = *ap;
|
idesc->id_blkno = *ap;
|
||||||
if (idesc->id_type == ADDR)
|
if (idesc->id_type != DATA)
|
||||||
ret = (*idesc->id_func)(idesc);
|
ret = (*idesc->id_func)(idesc);
|
||||||
else
|
else
|
||||||
ret = dirscan(idesc);
|
ret = dirscan(idesc);
|
||||||
@@ -117,12 +119,14 @@ ckinode(dp, idesc)
|
|||||||
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
|
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
|
||||||
sizepb = sblock.fs_bsize;
|
sizepb = sblock.fs_bsize;
|
||||||
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
|
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
|
||||||
|
sizepb *= NINDIR(&sblock);
|
||||||
if (*ap) {
|
if (*ap) {
|
||||||
idesc->id_blkno = *ap;
|
idesc->id_blkno = *ap;
|
||||||
ret = iblock(idesc, n, remsize);
|
ret = iblock(idesc, n, remsize);
|
||||||
if (ret & STOP)
|
if (ret & STOP)
|
||||||
return (ret);
|
return (ret);
|
||||||
} else {
|
} else {
|
||||||
|
idesc->id_lbn += sizepb / sblock.fs_bsize;
|
||||||
if (idesc->id_type == DATA && remsize > 0) {
|
if (idesc->id_type == DATA && remsize > 0) {
|
||||||
/* An empty block in a directory XXX */
|
/* An empty block in a directory XXX */
|
||||||
getpathname(pathbuf, idesc->id_number,
|
getpathname(pathbuf, idesc->id_number,
|
||||||
@@ -141,7 +145,6 @@ ckinode(dp, idesc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sizepb *= NINDIR(&sblock);
|
|
||||||
remsize -= sizepb;
|
remsize -= sizepb;
|
||||||
}
|
}
|
||||||
return (KEEPON);
|
return (KEEPON);
|
||||||
@@ -162,7 +165,7 @@ iblock(idesc, ilevel, isize)
|
|||||||
char pathbuf[MAXPATHLEN + 1];
|
char pathbuf[MAXPATHLEN + 1];
|
||||||
struct dinode *dp;
|
struct dinode *dp;
|
||||||
|
|
||||||
if (idesc->id_type == ADDR) {
|
if (idesc->id_type != DATA) {
|
||||||
func = idesc->id_func;
|
func = idesc->id_func;
|
||||||
if (((n = (*func)(idesc)) & KEEPON) == 0)
|
if (((n = (*func)(idesc)) & KEEPON) == 0)
|
||||||
return (n);
|
return (n);
|
||||||
@@ -193,6 +196,8 @@ iblock(idesc, ilevel, isize)
|
|||||||
}
|
}
|
||||||
aplim = &bp->b_un.b_indir[nif];
|
aplim = &bp->b_un.b_indir[nif];
|
||||||
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
|
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
|
||||||
|
if (ilevel == 0)
|
||||||
|
idesc->id_lbn++;
|
||||||
if (*ap) {
|
if (*ap) {
|
||||||
idesc->id_blkno = *ap;
|
idesc->id_blkno = *ap;
|
||||||
if (ilevel == 0)
|
if (ilevel == 0)
|
||||||
|
|||||||
+20
-1
@@ -40,6 +40,7 @@ static const char rcsid[] =
|
|||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <ufs/ufs/dinode.h>
|
#include <ufs/ufs/dinode.h>
|
||||||
#include <ufs/ufs/dir.h>
|
#include <ufs/ufs/dir.h>
|
||||||
@@ -82,7 +83,6 @@ pass1()
|
|||||||
* Find all allocated blocks.
|
* Find all allocated blocks.
|
||||||
*/
|
*/
|
||||||
memset(&idesc, 0, sizeof(struct inodesc));
|
memset(&idesc, 0, sizeof(struct inodesc));
|
||||||
idesc.id_type = ADDR;
|
|
||||||
idesc.id_func = pass1check;
|
idesc.id_func = pass1check;
|
||||||
n_files = n_blks = 0;
|
n_files = n_blks = 0;
|
||||||
for (c = 0; c < sblock.fs_ncg; c++) {
|
for (c = 0; c < sblock.fs_ncg; c++) {
|
||||||
@@ -306,6 +306,10 @@ checkinode(inumber, idesc)
|
|||||||
}
|
}
|
||||||
badblk = dupblk = 0;
|
badblk = dupblk = 0;
|
||||||
idesc->id_number = inumber;
|
idesc->id_number = inumber;
|
||||||
|
if (dp->di_flags & SF_SNAPSHOT)
|
||||||
|
idesc->id_type = SNAP;
|
||||||
|
else
|
||||||
|
idesc->id_type = ADDR;
|
||||||
(void)ckinode(dp, idesc);
|
(void)ckinode(dp, idesc);
|
||||||
idesc->id_entryno *= btodb(sblock.fs_fsize);
|
idesc->id_entryno *= btodb(sblock.fs_fsize);
|
||||||
if (dp->di_blocks != idesc->id_entryno) {
|
if (dp->di_blocks != idesc->id_entryno) {
|
||||||
@@ -341,6 +345,21 @@ pass1check(idesc)
|
|||||||
register struct dups *dlp;
|
register struct dups *dlp;
|
||||||
struct dups *new;
|
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) {
|
if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
|
||||||
blkerror(idesc->id_number, "BAD", blkno);
|
blkerror(idesc->id_number, "BAD", blkno);
|
||||||
if (badblk++ >= MAXBAD) {
|
if (badblk++ >= MAXBAD) {
|
||||||
|
|||||||
+68
-2
@@ -53,12 +53,12 @@ void
|
|||||||
pass5()
|
pass5()
|
||||||
{
|
{
|
||||||
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
|
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
|
||||||
int inomapsize, blkmapsize;
|
int inomapsize, blkmapsize, astart, aend, ustart, uend;
|
||||||
struct fs *fs = &sblock;
|
struct fs *fs = &sblock;
|
||||||
struct cg *cg = &cgrp;
|
struct cg *cg = &cgrp;
|
||||||
ufs_daddr_t dbase, dmax;
|
ufs_daddr_t dbase, dmax;
|
||||||
ufs_daddr_t d;
|
ufs_daddr_t d;
|
||||||
long i, j, k;
|
long i, j, k, l, m, n;
|
||||||
struct csum *cs;
|
struct csum *cs;
|
||||||
struct csum cstotal;
|
struct csum cstotal;
|
||||||
struct inodesc idesc[3];
|
struct inodesc idesc[3];
|
||||||
@@ -314,6 +314,72 @@ pass5()
|
|||||||
&cg_blktot(newcg)[0], (size_t)sumsize);
|
&cg_blktot(newcg)[0], (size_t)sumsize);
|
||||||
cgdirty();
|
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) {
|
if (usedsoftdep) {
|
||||||
for (i = 0; i < inomapsize; i++) {
|
for (i = 0; i < inomapsize; i++) {
|
||||||
j = cg_inosused(newcg)[i];
|
j = cg_inosused(newcg)[i];
|
||||||
|
|||||||
+10
-3
@@ -82,6 +82,7 @@ setup(dev)
|
|||||||
|
|
||||||
havesb = 0;
|
havesb = 0;
|
||||||
fswritefd = -1;
|
fswritefd = -1;
|
||||||
|
cursnapshot = 0;
|
||||||
skipclean = fflag ? 0 : preen;
|
skipclean = fflag ? 0 : preen;
|
||||||
if (stat(dev, &statb) < 0) {
|
if (stat(dev, &statb) < 0) {
|
||||||
printf("Can't stat %s: %s\n", dev, strerror(errno));
|
printf("Can't stat %s: %s\n", dev, strerror(errno));
|
||||||
@@ -89,9 +90,13 @@ setup(dev)
|
|||||||
}
|
}
|
||||||
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
|
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
|
||||||
(statb.st_mode & S_IFMT) != S_IFBLK) {
|
(statb.st_mode & S_IFMT) != S_IFBLK) {
|
||||||
pfatal("%s is not a disk device", dev);
|
if ((statb.st_flags & SF_SNAPSHOT) != 0) {
|
||||||
if (reply("CONTINUE") == 0)
|
cursnapshot = statb.st_ino;
|
||||||
return (0);
|
} else {
|
||||||
|
pfatal("%s is not a disk device", dev);
|
||||||
|
if (reply("CONTINUE") == 0)
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
|
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
|
||||||
printf("Can't open %s: %s\n", dev, strerror(errno));
|
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);
|
memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp);
|
||||||
altsblock.fs_maxcluster = sblock.fs_maxcluster;
|
altsblock.fs_maxcluster = sblock.fs_maxcluster;
|
||||||
memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt);
|
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,
|
memmove(altsblock.fs_sparecon,
|
||||||
sblock.fs_sparecon, sizeof sblock.fs_sparecon);
|
sblock.fs_sparecon, sizeof sblock.fs_sparecon);
|
||||||
/*
|
/*
|
||||||
|
|||||||
+10
-4
@@ -241,7 +241,7 @@ dircheck(idesc, dp)
|
|||||||
if (dp->d_reclen == 0 ||
|
if (dp->d_reclen == 0 ||
|
||||||
dp->d_reclen > spaceleft ||
|
dp->d_reclen > spaceleft ||
|
||||||
(dp->d_reclen & 0x3) != 0)
|
(dp->d_reclen & 0x3) != 0)
|
||||||
return (0);
|
goto bad;
|
||||||
if (dp->d_ino == 0)
|
if (dp->d_ino == 0)
|
||||||
return (1);
|
return (1);
|
||||||
size = DIRSIZ(!newinofmt, dp);
|
size = DIRSIZ(!newinofmt, dp);
|
||||||
@@ -261,13 +261,19 @@ dircheck(idesc, dp)
|
|||||||
idesc->id_filesize < size ||
|
idesc->id_filesize < size ||
|
||||||
namlen > MAXNAMLEN ||
|
namlen > MAXNAMLEN ||
|
||||||
type > 15)
|
type > 15)
|
||||||
return (0);
|
goto bad;
|
||||||
for (cp = dp->d_name, size = 0; size < namlen; size++)
|
for (cp = dp->d_name, size = 0; size < namlen; size++)
|
||||||
if (*cp == '\0' || (*cp++ == '/'))
|
if (*cp == '\0' || (*cp++ == '/'))
|
||||||
return (0);
|
goto bad;
|
||||||
if (*cp != '\0')
|
if (*cp != '\0')
|
||||||
return (0);
|
goto bad;
|
||||||
return (1);
|
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
|
void
|
||||||
|
|||||||
@@ -114,12 +114,14 @@ struct bufarea *pbp; /* current inode block */
|
|||||||
#define cgrp (*cgblk.b_un.b_cg)
|
#define cgrp (*cgblk.b_un.b_cg)
|
||||||
|
|
||||||
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
|
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
|
||||||
|
ino_t cursnapshot;
|
||||||
|
|
||||||
struct inodesc {
|
struct inodesc {
|
||||||
enum fixstate id_fix; /* policy on fixing errors */
|
enum fixstate id_fix; /* policy on fixing errors */
|
||||||
int (*id_func)(); /* function to be applied to blocks of inode */
|
int (*id_func)(); /* function to be applied to blocks of inode */
|
||||||
ino_t id_number; /* inode number described */
|
ino_t id_number; /* inode number described */
|
||||||
ino_t id_parent; /* for DATA nodes, their parent */
|
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 */
|
ufs_daddr_t id_blkno; /* current block number being examined */
|
||||||
int id_numfrags; /* number of frags contained in block */
|
int id_numfrags; /* number of frags contained in block */
|
||||||
quad_t id_filesize; /* for DATA nodes, the size of the directory */
|
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 */
|
char id_type; /* type of descriptor, DATA or ADDR */
|
||||||
};
|
};
|
||||||
/* file types */
|
/* file types */
|
||||||
#define DATA 1
|
#define DATA 1 /* a directory */
|
||||||
#define ADDR 2
|
#define SNAP 2 /* a snapshot */
|
||||||
|
#define ADDR 3 /* anything but a directory or a snapshot */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Linked list of duplicate blocks.
|
* Linked list of duplicate blocks.
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ ckinode(dp, idesc)
|
|||||||
|
|
||||||
if (idesc->id_fix != IGNORE)
|
if (idesc->id_fix != IGNORE)
|
||||||
idesc->id_fix = DONTKNOW;
|
idesc->id_fix = DONTKNOW;
|
||||||
|
idesc->id_lbn = -1;
|
||||||
idesc->id_entryno = 0;
|
idesc->id_entryno = 0;
|
||||||
idesc->id_filesize = dp->di_size;
|
idesc->id_filesize = dp->di_size;
|
||||||
mode = dp->di_mode & IFMT;
|
mode = dp->di_mode & IFMT;
|
||||||
@@ -80,6 +81,7 @@ ckinode(dp, idesc)
|
|||||||
dino = *dp;
|
dino = *dp;
|
||||||
ndb = howmany(dino.di_size, sblock.fs_bsize);
|
ndb = howmany(dino.di_size, sblock.fs_bsize);
|
||||||
for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
|
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)
|
if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
|
||||||
idesc->id_numfrags =
|
idesc->id_numfrags =
|
||||||
numfrags(&sblock, fragroundup(&sblock, offset));
|
numfrags(&sblock, fragroundup(&sblock, offset));
|
||||||
@@ -106,7 +108,7 @@ ckinode(dp, idesc)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
idesc->id_blkno = *ap;
|
idesc->id_blkno = *ap;
|
||||||
if (idesc->id_type == ADDR)
|
if (idesc->id_type != DATA)
|
||||||
ret = (*idesc->id_func)(idesc);
|
ret = (*idesc->id_func)(idesc);
|
||||||
else
|
else
|
||||||
ret = dirscan(idesc);
|
ret = dirscan(idesc);
|
||||||
@@ -117,12 +119,14 @@ ckinode(dp, idesc)
|
|||||||
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
|
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
|
||||||
sizepb = sblock.fs_bsize;
|
sizepb = sblock.fs_bsize;
|
||||||
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
|
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
|
||||||
|
sizepb *= NINDIR(&sblock);
|
||||||
if (*ap) {
|
if (*ap) {
|
||||||
idesc->id_blkno = *ap;
|
idesc->id_blkno = *ap;
|
||||||
ret = iblock(idesc, n, remsize);
|
ret = iblock(idesc, n, remsize);
|
||||||
if (ret & STOP)
|
if (ret & STOP)
|
||||||
return (ret);
|
return (ret);
|
||||||
} else {
|
} else {
|
||||||
|
idesc->id_lbn += sizepb / sblock.fs_bsize;
|
||||||
if (idesc->id_type == DATA && remsize > 0) {
|
if (idesc->id_type == DATA && remsize > 0) {
|
||||||
/* An empty block in a directory XXX */
|
/* An empty block in a directory XXX */
|
||||||
getpathname(pathbuf, idesc->id_number,
|
getpathname(pathbuf, idesc->id_number,
|
||||||
@@ -141,7 +145,6 @@ ckinode(dp, idesc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sizepb *= NINDIR(&sblock);
|
|
||||||
remsize -= sizepb;
|
remsize -= sizepb;
|
||||||
}
|
}
|
||||||
return (KEEPON);
|
return (KEEPON);
|
||||||
@@ -162,7 +165,7 @@ iblock(idesc, ilevel, isize)
|
|||||||
char pathbuf[MAXPATHLEN + 1];
|
char pathbuf[MAXPATHLEN + 1];
|
||||||
struct dinode *dp;
|
struct dinode *dp;
|
||||||
|
|
||||||
if (idesc->id_type == ADDR) {
|
if (idesc->id_type != DATA) {
|
||||||
func = idesc->id_func;
|
func = idesc->id_func;
|
||||||
if (((n = (*func)(idesc)) & KEEPON) == 0)
|
if (((n = (*func)(idesc)) & KEEPON) == 0)
|
||||||
return (n);
|
return (n);
|
||||||
@@ -193,6 +196,8 @@ iblock(idesc, ilevel, isize)
|
|||||||
}
|
}
|
||||||
aplim = &bp->b_un.b_indir[nif];
|
aplim = &bp->b_un.b_indir[nif];
|
||||||
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
|
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
|
||||||
|
if (ilevel == 0)
|
||||||
|
idesc->id_lbn++;
|
||||||
if (*ap) {
|
if (*ap) {
|
||||||
idesc->id_blkno = *ap;
|
idesc->id_blkno = *ap;
|
||||||
if (ilevel == 0)
|
if (ilevel == 0)
|
||||||
|
|||||||
+20
-1
@@ -40,6 +40,7 @@ static const char rcsid[] =
|
|||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <ufs/ufs/dinode.h>
|
#include <ufs/ufs/dinode.h>
|
||||||
#include <ufs/ufs/dir.h>
|
#include <ufs/ufs/dir.h>
|
||||||
@@ -82,7 +83,6 @@ pass1()
|
|||||||
* Find all allocated blocks.
|
* Find all allocated blocks.
|
||||||
*/
|
*/
|
||||||
memset(&idesc, 0, sizeof(struct inodesc));
|
memset(&idesc, 0, sizeof(struct inodesc));
|
||||||
idesc.id_type = ADDR;
|
|
||||||
idesc.id_func = pass1check;
|
idesc.id_func = pass1check;
|
||||||
n_files = n_blks = 0;
|
n_files = n_blks = 0;
|
||||||
for (c = 0; c < sblock.fs_ncg; c++) {
|
for (c = 0; c < sblock.fs_ncg; c++) {
|
||||||
@@ -306,6 +306,10 @@ checkinode(inumber, idesc)
|
|||||||
}
|
}
|
||||||
badblk = dupblk = 0;
|
badblk = dupblk = 0;
|
||||||
idesc->id_number = inumber;
|
idesc->id_number = inumber;
|
||||||
|
if (dp->di_flags & SF_SNAPSHOT)
|
||||||
|
idesc->id_type = SNAP;
|
||||||
|
else
|
||||||
|
idesc->id_type = ADDR;
|
||||||
(void)ckinode(dp, idesc);
|
(void)ckinode(dp, idesc);
|
||||||
idesc->id_entryno *= btodb(sblock.fs_fsize);
|
idesc->id_entryno *= btodb(sblock.fs_fsize);
|
||||||
if (dp->di_blocks != idesc->id_entryno) {
|
if (dp->di_blocks != idesc->id_entryno) {
|
||||||
@@ -341,6 +345,21 @@ pass1check(idesc)
|
|||||||
register struct dups *dlp;
|
register struct dups *dlp;
|
||||||
struct dups *new;
|
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) {
|
if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
|
||||||
blkerror(idesc->id_number, "BAD", blkno);
|
blkerror(idesc->id_number, "BAD", blkno);
|
||||||
if (badblk++ >= MAXBAD) {
|
if (badblk++ >= MAXBAD) {
|
||||||
|
|||||||
+68
-2
@@ -53,12 +53,12 @@ void
|
|||||||
pass5()
|
pass5()
|
||||||
{
|
{
|
||||||
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
|
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
|
||||||
int inomapsize, blkmapsize;
|
int inomapsize, blkmapsize, astart, aend, ustart, uend;
|
||||||
struct fs *fs = &sblock;
|
struct fs *fs = &sblock;
|
||||||
struct cg *cg = &cgrp;
|
struct cg *cg = &cgrp;
|
||||||
ufs_daddr_t dbase, dmax;
|
ufs_daddr_t dbase, dmax;
|
||||||
ufs_daddr_t d;
|
ufs_daddr_t d;
|
||||||
long i, j, k;
|
long i, j, k, l, m, n;
|
||||||
struct csum *cs;
|
struct csum *cs;
|
||||||
struct csum cstotal;
|
struct csum cstotal;
|
||||||
struct inodesc idesc[3];
|
struct inodesc idesc[3];
|
||||||
@@ -314,6 +314,72 @@ pass5()
|
|||||||
&cg_blktot(newcg)[0], (size_t)sumsize);
|
&cg_blktot(newcg)[0], (size_t)sumsize);
|
||||||
cgdirty();
|
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) {
|
if (usedsoftdep) {
|
||||||
for (i = 0; i < inomapsize; i++) {
|
for (i = 0; i < inomapsize; i++) {
|
||||||
j = cg_inosused(newcg)[i];
|
j = cg_inosused(newcg)[i];
|
||||||
|
|||||||
+10
-3
@@ -82,6 +82,7 @@ setup(dev)
|
|||||||
|
|
||||||
havesb = 0;
|
havesb = 0;
|
||||||
fswritefd = -1;
|
fswritefd = -1;
|
||||||
|
cursnapshot = 0;
|
||||||
skipclean = fflag ? 0 : preen;
|
skipclean = fflag ? 0 : preen;
|
||||||
if (stat(dev, &statb) < 0) {
|
if (stat(dev, &statb) < 0) {
|
||||||
printf("Can't stat %s: %s\n", dev, strerror(errno));
|
printf("Can't stat %s: %s\n", dev, strerror(errno));
|
||||||
@@ -89,9 +90,13 @@ setup(dev)
|
|||||||
}
|
}
|
||||||
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
|
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
|
||||||
(statb.st_mode & S_IFMT) != S_IFBLK) {
|
(statb.st_mode & S_IFMT) != S_IFBLK) {
|
||||||
pfatal("%s is not a disk device", dev);
|
if ((statb.st_flags & SF_SNAPSHOT) != 0) {
|
||||||
if (reply("CONTINUE") == 0)
|
cursnapshot = statb.st_ino;
|
||||||
return (0);
|
} else {
|
||||||
|
pfatal("%s is not a disk device", dev);
|
||||||
|
if (reply("CONTINUE") == 0)
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
|
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
|
||||||
printf("Can't open %s: %s\n", dev, strerror(errno));
|
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);
|
memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp);
|
||||||
altsblock.fs_maxcluster = sblock.fs_maxcluster;
|
altsblock.fs_maxcluster = sblock.fs_maxcluster;
|
||||||
memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt);
|
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,
|
memmove(altsblock.fs_sparecon,
|
||||||
sblock.fs_sparecon, sizeof sblock.fs_sparecon);
|
sblock.fs_sparecon, sizeof sblock.fs_sparecon);
|
||||||
/*
|
/*
|
||||||
|
|||||||
+10
-4
@@ -241,7 +241,7 @@ dircheck(idesc, dp)
|
|||||||
if (dp->d_reclen == 0 ||
|
if (dp->d_reclen == 0 ||
|
||||||
dp->d_reclen > spaceleft ||
|
dp->d_reclen > spaceleft ||
|
||||||
(dp->d_reclen & 0x3) != 0)
|
(dp->d_reclen & 0x3) != 0)
|
||||||
return (0);
|
goto bad;
|
||||||
if (dp->d_ino == 0)
|
if (dp->d_ino == 0)
|
||||||
return (1);
|
return (1);
|
||||||
size = DIRSIZ(!newinofmt, dp);
|
size = DIRSIZ(!newinofmt, dp);
|
||||||
@@ -261,13 +261,19 @@ dircheck(idesc, dp)
|
|||||||
idesc->id_filesize < size ||
|
idesc->id_filesize < size ||
|
||||||
namlen > MAXNAMLEN ||
|
namlen > MAXNAMLEN ||
|
||||||
type > 15)
|
type > 15)
|
||||||
return (0);
|
goto bad;
|
||||||
for (cp = dp->d_name, size = 0; size < namlen; size++)
|
for (cp = dp->d_name, size = 0; size < namlen; size++)
|
||||||
if (*cp == '\0' || (*cp++ == '/'))
|
if (*cp == '\0' || (*cp++ == '/'))
|
||||||
return (0);
|
goto bad;
|
||||||
if (*cp != '\0')
|
if (*cp != '\0')
|
||||||
return (0);
|
goto bad;
|
||||||
return (1);
|
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
|
void
|
||||||
|
|||||||
@@ -114,12 +114,14 @@ struct bufarea *pbp; /* current inode block */
|
|||||||
#define cgrp (*cgblk.b_un.b_cg)
|
#define cgrp (*cgblk.b_un.b_cg)
|
||||||
|
|
||||||
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
|
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
|
||||||
|
ino_t cursnapshot;
|
||||||
|
|
||||||
struct inodesc {
|
struct inodesc {
|
||||||
enum fixstate id_fix; /* policy on fixing errors */
|
enum fixstate id_fix; /* policy on fixing errors */
|
||||||
int (*id_func)(); /* function to be applied to blocks of inode */
|
int (*id_func)(); /* function to be applied to blocks of inode */
|
||||||
ino_t id_number; /* inode number described */
|
ino_t id_number; /* inode number described */
|
||||||
ino_t id_parent; /* for DATA nodes, their parent */
|
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 */
|
ufs_daddr_t id_blkno; /* current block number being examined */
|
||||||
int id_numfrags; /* number of frags contained in block */
|
int id_numfrags; /* number of frags contained in block */
|
||||||
quad_t id_filesize; /* for DATA nodes, the size of the directory */
|
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 */
|
char id_type; /* type of descriptor, DATA or ADDR */
|
||||||
};
|
};
|
||||||
/* file types */
|
/* file types */
|
||||||
#define DATA 1
|
#define DATA 1 /* a directory */
|
||||||
#define ADDR 2
|
#define SNAP 2 /* a snapshot */
|
||||||
|
#define ADDR 3 /* anything but a directory or a snapshot */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Linked list of duplicate blocks.
|
* Linked list of duplicate blocks.
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ ckinode(dp, idesc)
|
|||||||
|
|
||||||
if (idesc->id_fix != IGNORE)
|
if (idesc->id_fix != IGNORE)
|
||||||
idesc->id_fix = DONTKNOW;
|
idesc->id_fix = DONTKNOW;
|
||||||
|
idesc->id_lbn = -1;
|
||||||
idesc->id_entryno = 0;
|
idesc->id_entryno = 0;
|
||||||
idesc->id_filesize = dp->di_size;
|
idesc->id_filesize = dp->di_size;
|
||||||
mode = dp->di_mode & IFMT;
|
mode = dp->di_mode & IFMT;
|
||||||
@@ -80,6 +81,7 @@ ckinode(dp, idesc)
|
|||||||
dino = *dp;
|
dino = *dp;
|
||||||
ndb = howmany(dino.di_size, sblock.fs_bsize);
|
ndb = howmany(dino.di_size, sblock.fs_bsize);
|
||||||
for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
|
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)
|
if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
|
||||||
idesc->id_numfrags =
|
idesc->id_numfrags =
|
||||||
numfrags(&sblock, fragroundup(&sblock, offset));
|
numfrags(&sblock, fragroundup(&sblock, offset));
|
||||||
@@ -106,7 +108,7 @@ ckinode(dp, idesc)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
idesc->id_blkno = *ap;
|
idesc->id_blkno = *ap;
|
||||||
if (idesc->id_type == ADDR)
|
if (idesc->id_type != DATA)
|
||||||
ret = (*idesc->id_func)(idesc);
|
ret = (*idesc->id_func)(idesc);
|
||||||
else
|
else
|
||||||
ret = dirscan(idesc);
|
ret = dirscan(idesc);
|
||||||
@@ -117,12 +119,14 @@ ckinode(dp, idesc)
|
|||||||
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
|
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
|
||||||
sizepb = sblock.fs_bsize;
|
sizepb = sblock.fs_bsize;
|
||||||
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
|
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
|
||||||
|
sizepb *= NINDIR(&sblock);
|
||||||
if (*ap) {
|
if (*ap) {
|
||||||
idesc->id_blkno = *ap;
|
idesc->id_blkno = *ap;
|
||||||
ret = iblock(idesc, n, remsize);
|
ret = iblock(idesc, n, remsize);
|
||||||
if (ret & STOP)
|
if (ret & STOP)
|
||||||
return (ret);
|
return (ret);
|
||||||
} else {
|
} else {
|
||||||
|
idesc->id_lbn += sizepb / sblock.fs_bsize;
|
||||||
if (idesc->id_type == DATA && remsize > 0) {
|
if (idesc->id_type == DATA && remsize > 0) {
|
||||||
/* An empty block in a directory XXX */
|
/* An empty block in a directory XXX */
|
||||||
getpathname(pathbuf, idesc->id_number,
|
getpathname(pathbuf, idesc->id_number,
|
||||||
@@ -141,7 +145,6 @@ ckinode(dp, idesc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sizepb *= NINDIR(&sblock);
|
|
||||||
remsize -= sizepb;
|
remsize -= sizepb;
|
||||||
}
|
}
|
||||||
return (KEEPON);
|
return (KEEPON);
|
||||||
@@ -162,7 +165,7 @@ iblock(idesc, ilevel, isize)
|
|||||||
char pathbuf[MAXPATHLEN + 1];
|
char pathbuf[MAXPATHLEN + 1];
|
||||||
struct dinode *dp;
|
struct dinode *dp;
|
||||||
|
|
||||||
if (idesc->id_type == ADDR) {
|
if (idesc->id_type != DATA) {
|
||||||
func = idesc->id_func;
|
func = idesc->id_func;
|
||||||
if (((n = (*func)(idesc)) & KEEPON) == 0)
|
if (((n = (*func)(idesc)) & KEEPON) == 0)
|
||||||
return (n);
|
return (n);
|
||||||
@@ -193,6 +196,8 @@ iblock(idesc, ilevel, isize)
|
|||||||
}
|
}
|
||||||
aplim = &bp->b_un.b_indir[nif];
|
aplim = &bp->b_un.b_indir[nif];
|
||||||
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
|
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
|
||||||
|
if (ilevel == 0)
|
||||||
|
idesc->id_lbn++;
|
||||||
if (*ap) {
|
if (*ap) {
|
||||||
idesc->id_blkno = *ap;
|
idesc->id_blkno = *ap;
|
||||||
if (ilevel == 0)
|
if (ilevel == 0)
|
||||||
|
|||||||
+20
-1
@@ -40,6 +40,7 @@ static const char rcsid[] =
|
|||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <ufs/ufs/dinode.h>
|
#include <ufs/ufs/dinode.h>
|
||||||
#include <ufs/ufs/dir.h>
|
#include <ufs/ufs/dir.h>
|
||||||
@@ -82,7 +83,6 @@ pass1()
|
|||||||
* Find all allocated blocks.
|
* Find all allocated blocks.
|
||||||
*/
|
*/
|
||||||
memset(&idesc, 0, sizeof(struct inodesc));
|
memset(&idesc, 0, sizeof(struct inodesc));
|
||||||
idesc.id_type = ADDR;
|
|
||||||
idesc.id_func = pass1check;
|
idesc.id_func = pass1check;
|
||||||
n_files = n_blks = 0;
|
n_files = n_blks = 0;
|
||||||
for (c = 0; c < sblock.fs_ncg; c++) {
|
for (c = 0; c < sblock.fs_ncg; c++) {
|
||||||
@@ -306,6 +306,10 @@ checkinode(inumber, idesc)
|
|||||||
}
|
}
|
||||||
badblk = dupblk = 0;
|
badblk = dupblk = 0;
|
||||||
idesc->id_number = inumber;
|
idesc->id_number = inumber;
|
||||||
|
if (dp->di_flags & SF_SNAPSHOT)
|
||||||
|
idesc->id_type = SNAP;
|
||||||
|
else
|
||||||
|
idesc->id_type = ADDR;
|
||||||
(void)ckinode(dp, idesc);
|
(void)ckinode(dp, idesc);
|
||||||
idesc->id_entryno *= btodb(sblock.fs_fsize);
|
idesc->id_entryno *= btodb(sblock.fs_fsize);
|
||||||
if (dp->di_blocks != idesc->id_entryno) {
|
if (dp->di_blocks != idesc->id_entryno) {
|
||||||
@@ -341,6 +345,21 @@ pass1check(idesc)
|
|||||||
register struct dups *dlp;
|
register struct dups *dlp;
|
||||||
struct dups *new;
|
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) {
|
if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
|
||||||
blkerror(idesc->id_number, "BAD", blkno);
|
blkerror(idesc->id_number, "BAD", blkno);
|
||||||
if (badblk++ >= MAXBAD) {
|
if (badblk++ >= MAXBAD) {
|
||||||
|
|||||||
+68
-2
@@ -53,12 +53,12 @@ void
|
|||||||
pass5()
|
pass5()
|
||||||
{
|
{
|
||||||
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
|
int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
|
||||||
int inomapsize, blkmapsize;
|
int inomapsize, blkmapsize, astart, aend, ustart, uend;
|
||||||
struct fs *fs = &sblock;
|
struct fs *fs = &sblock;
|
||||||
struct cg *cg = &cgrp;
|
struct cg *cg = &cgrp;
|
||||||
ufs_daddr_t dbase, dmax;
|
ufs_daddr_t dbase, dmax;
|
||||||
ufs_daddr_t d;
|
ufs_daddr_t d;
|
||||||
long i, j, k;
|
long i, j, k, l, m, n;
|
||||||
struct csum *cs;
|
struct csum *cs;
|
||||||
struct csum cstotal;
|
struct csum cstotal;
|
||||||
struct inodesc idesc[3];
|
struct inodesc idesc[3];
|
||||||
@@ -314,6 +314,72 @@ pass5()
|
|||||||
&cg_blktot(newcg)[0], (size_t)sumsize);
|
&cg_blktot(newcg)[0], (size_t)sumsize);
|
||||||
cgdirty();
|
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) {
|
if (usedsoftdep) {
|
||||||
for (i = 0; i < inomapsize; i++) {
|
for (i = 0; i < inomapsize; i++) {
|
||||||
j = cg_inosused(newcg)[i];
|
j = cg_inosused(newcg)[i];
|
||||||
|
|||||||
+10
-3
@@ -82,6 +82,7 @@ setup(dev)
|
|||||||
|
|
||||||
havesb = 0;
|
havesb = 0;
|
||||||
fswritefd = -1;
|
fswritefd = -1;
|
||||||
|
cursnapshot = 0;
|
||||||
skipclean = fflag ? 0 : preen;
|
skipclean = fflag ? 0 : preen;
|
||||||
if (stat(dev, &statb) < 0) {
|
if (stat(dev, &statb) < 0) {
|
||||||
printf("Can't stat %s: %s\n", dev, strerror(errno));
|
printf("Can't stat %s: %s\n", dev, strerror(errno));
|
||||||
@@ -89,9 +90,13 @@ setup(dev)
|
|||||||
}
|
}
|
||||||
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
|
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
|
||||||
(statb.st_mode & S_IFMT) != S_IFBLK) {
|
(statb.st_mode & S_IFMT) != S_IFBLK) {
|
||||||
pfatal("%s is not a disk device", dev);
|
if ((statb.st_flags & SF_SNAPSHOT) != 0) {
|
||||||
if (reply("CONTINUE") == 0)
|
cursnapshot = statb.st_ino;
|
||||||
return (0);
|
} else {
|
||||||
|
pfatal("%s is not a disk device", dev);
|
||||||
|
if (reply("CONTINUE") == 0)
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
|
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
|
||||||
printf("Can't open %s: %s\n", dev, strerror(errno));
|
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);
|
memmove(altsblock.fs_csp, sblock.fs_csp, sizeof sblock.fs_csp);
|
||||||
altsblock.fs_maxcluster = sblock.fs_maxcluster;
|
altsblock.fs_maxcluster = sblock.fs_maxcluster;
|
||||||
memmove(altsblock.fs_fsmnt, sblock.fs_fsmnt, sizeof sblock.fs_fsmnt);
|
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,
|
memmove(altsblock.fs_sparecon,
|
||||||
sblock.fs_sparecon, sizeof sblock.fs_sparecon);
|
sblock.fs_sparecon, sizeof sblock.fs_sparecon);
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user