Properly handle UFS2 sparsely allocated inodes. The UFS2 filesystem
only preallocates a small number of inodes. The dump program tries to scan through all the allocated inodes on a filesystem which causes bad behavior if they have never been allocated. Thus dump must calculate the set of inodes that have actually been allocated and scan only those inodes. Sponsored by: DARPA & NAI Labs.
This commit is contained in:
parent
7ec589a9b7
commit
69becf4a5e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=107541
@ -139,36 +139,77 @@ blockest(union dinode *dp)
|
|||||||
int
|
int
|
||||||
mapfiles(ino_t maxino, long *tapesize)
|
mapfiles(ino_t maxino, long *tapesize)
|
||||||
{
|
{
|
||||||
int mode;
|
int i, cg, mode, inosused;
|
||||||
ino_t ino;
|
|
||||||
union dinode *dp;
|
|
||||||
int anydirskipped = 0;
|
int anydirskipped = 0;
|
||||||
|
union dinode *dp;
|
||||||
|
struct cg *cgp;
|
||||||
|
ino_t ino;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
for (ino = ROOTINO; ino < maxino; ino++) {
|
if ((cgp = malloc(sblock->fs_cgsize)) == NULL)
|
||||||
dp = getino(ino, &mode);
|
quit("mapfiles: cannot allocate memory.\n");
|
||||||
if (mode == 0)
|
for (cg = 0; cg < sblock->fs_ncg; cg++) {
|
||||||
continue;
|
ino = cg * sblock->fs_ipg;
|
||||||
|
bread(fsbtodb(sblock, cgtod(sblock, cg)), (char *)cgp,
|
||||||
|
sblock->fs_cgsize);
|
||||||
|
if (sblock->fs_magic == FS_UFS2_MAGIC)
|
||||||
|
inosused = cgp->cg_initediblk;
|
||||||
|
else
|
||||||
|
inosused = sblock->fs_ipg;
|
||||||
/*
|
/*
|
||||||
* Everything must go in usedinomap so that a check
|
* If we are using soft updates, then we can trust the
|
||||||
* for "in dumpdirmap but not in usedinomap" to detect
|
* cylinder group inode allocation maps to tell us which
|
||||||
* dirs with nodump set has a chance of succeeding
|
* inodes are allocated. We will scan the used inode map
|
||||||
* (this is used in mapdirs()).
|
* to find the inodes that are really in use, and then
|
||||||
|
* read only those inodes in from disk.
|
||||||
*/
|
*/
|
||||||
SETINO(ino, usedinomap);
|
if (sblock->fs_flags & FS_DOSOFTDEP) {
|
||||||
if (mode == IFDIR)
|
if (!cg_chkmagic(cgp))
|
||||||
SETINO(ino, dumpdirmap);
|
quit("mapfiles: cg %d: bad magic number\n", cg);
|
||||||
if (WANTTODUMP(dp)) {
|
cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
|
||||||
SETINO(ino, dumpinomap);
|
for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
|
||||||
if (mode != IFREG && mode != IFDIR && mode != IFLNK)
|
if (*cp == 0)
|
||||||
*tapesize += 1;
|
continue;
|
||||||
else
|
for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
|
||||||
*tapesize += blockest(dp);
|
if (*cp & i)
|
||||||
continue;
|
break;
|
||||||
|
inosused--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (inosused <= 0)
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (mode == IFDIR) {
|
for (i = 0; i < inosused; i++, ino++) {
|
||||||
if (!nonodump && (DIP(dp, di_flags) & UF_NODUMP))
|
if (ino < ROOTINO ||
|
||||||
CLRINO(ino, usedinomap);
|
(dp = getino(ino, &mode)) == NULL ||
|
||||||
anydirskipped = 1;
|
(mode & IFMT) == 0)
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
* Everything must go in usedinomap so that a check
|
||||||
|
* for "in dumpdirmap but not in usedinomap" to detect
|
||||||
|
* dirs with nodump set has a chance of succeeding
|
||||||
|
* (this is used in mapdirs()).
|
||||||
|
*/
|
||||||
|
SETINO(ino, usedinomap);
|
||||||
|
if (mode == IFDIR)
|
||||||
|
SETINO(ino, dumpdirmap);
|
||||||
|
if (WANTTODUMP(dp)) {
|
||||||
|
SETINO(ino, dumpinomap);
|
||||||
|
if (mode != IFREG &&
|
||||||
|
mode != IFDIR &&
|
||||||
|
mode != IFLNK)
|
||||||
|
*tapesize += 1;
|
||||||
|
else
|
||||||
|
*tapesize += blockest(dp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mode == IFDIR) {
|
||||||
|
if (!nonodump &&
|
||||||
|
(DIP(dp, di_flags) & UF_NODUMP))
|
||||||
|
CLRINO(ino, usedinomap);
|
||||||
|
anydirskipped = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user