version 1.23.6.3, 2014/05/22 11:37:28 |
version 1.24, 2012/01/05 16:18:00 |
|
|
#include <sys/buf.h> |
#include <sys/buf.h> |
#include <sys/mount.h> |
#include <sys/mount.h> |
|
|
#define VU_DIROP 0x01000000 /* XXX XXX from sys/vnode.h */ |
#include <ufs/ufs/ufsmount.h> |
|
#include <ufs/ufs/inode.h> |
|
#include <ufs/ufs/dir.h> |
#define vnode uvnode |
#define vnode uvnode |
#include <ufs/lfs/lfs.h> |
#include <ufs/lfs/lfs.h> |
#include <ufs/lfs/lfs_inode.h> |
|
#undef vnode |
#undef vnode |
|
|
#include <assert.h> |
#include <assert.h> |
|
|
extern u_int32_t cksum(void *, size_t); |
extern u_int32_t cksum(void *, size_t); |
extern u_int32_t lfs_sb_cksum(struct dlfs *); |
extern u_int32_t lfs_sb_cksum(struct dlfs *); |
|
|
extern ulfs_daddr_t badblk; |
extern ufs_daddr_t badblk; |
extern SEGUSE *seg_table; |
extern SEGUSE *seg_table; |
|
|
static int nnewblocks; |
static int nnewblocks; |
Line 72 static int nnewblocks; |
|
Line 73 static int nnewblocks; |
|
* segment. |
* segment. |
* |
* |
* Change the given block's address to ndaddr, finding its previous |
* Change the given block's address to ndaddr, finding its previous |
* location using ulfs_bmaparray(). |
* location using ufs_bmaparray(). |
* |
* |
* Account for this change in the segment table. |
* Account for this change in the segment table. |
*/ |
*/ |
static void |
static void |
rfw_update_single(struct uvnode *vp, daddr_t lbn, ulfs_daddr_t ndaddr, int size) |
rfw_update_single(struct uvnode *vp, daddr_t lbn, ufs_daddr_t ndaddr, int size) |
{ |
{ |
SEGUSE *sup; |
SEGUSE *sup; |
struct ubuf *bp; |
struct ubuf *bp; |
struct indir a[ULFS_NIADDR + 2], *ap; |
struct indir a[NIADDR + 2], *ap; |
struct inode *ip; |
struct inode *ip; |
daddr_t daddr, ooff; |
daddr_t daddr, ooff; |
int num, error; |
int num, error; |
Line 92 rfw_update_single(struct uvnode *vp, dad |
|
Line 93 rfw_update_single(struct uvnode *vp, dad |
|
ip = VTOI(vp); |
ip = VTOI(vp); |
ip->i_flag |= IN_MODIFIED; |
ip->i_flag |= IN_MODIFIED; |
|
|
error = ulfs_bmaparray(fs, vp, lbn, &daddr, a, &num); |
error = ufs_bmaparray(fs, vp, lbn, &daddr, a, &num); |
if (error) |
if (error) |
errx(1, "lfs_updatemeta: ulfs_bmaparray returned %d" |
errx(1, "lfs_updatemeta: ufs_bmaparray returned %d" |
" looking up lbn %" PRId64 "\n", error, lbn); |
" looking up lbn %" PRId64 "\n", error, lbn); |
if (daddr > 0) |
if (daddr > 0) |
daddr = LFS_DBTOFSB(fs, daddr); |
daddr = dbtofsb(fs, daddr); |
|
|
frags = lfs_numfrags(fs, size); |
frags = numfrags(fs, size); |
switch (num) { |
switch (num) { |
case 0: |
case 0: |
ooff = ip->i_ffs1_db[lbn]; |
ooff = ip->i_ffs1_db[lbn]; |
Line 107 rfw_update_single(struct uvnode *vp, dad |
|
Line 108 rfw_update_single(struct uvnode *vp, dad |
|
ip->i_ffs1_blocks += frags; |
ip->i_ffs1_blocks += frags; |
else { |
else { |
/* possible fragment truncation or extension */ |
/* possible fragment truncation or extension */ |
ofrags = lfs_numfrags(fs, ip->i_lfs_fragsize[lbn]); |
ofrags = numfrags(fs, ip->i_lfs_fragsize[lbn]); |
ip->i_ffs1_blocks += (frags - ofrags); |
ip->i_ffs1_blocks += (frags - ofrags); |
} |
} |
ip->i_ffs1_db[lbn] = ndaddr; |
ip->i_ffs1_db[lbn] = ndaddr; |
Line 124 rfw_update_single(struct uvnode *vp, dad |
|
Line 125 rfw_update_single(struct uvnode *vp, dad |
|
errx(1, "lfs_updatemeta: bread bno %" PRId64, |
errx(1, "lfs_updatemeta: bread bno %" PRId64, |
ap->in_lbn); |
ap->in_lbn); |
|
|
ooff = ((ulfs_daddr_t *) bp->b_data)[ap->in_off]; |
ooff = ((ufs_daddr_t *) bp->b_data)[ap->in_off]; |
if (ooff <= 0) |
if (ooff <= 0) |
ip->i_ffs1_blocks += frags; |
ip->i_ffs1_blocks += frags; |
((ulfs_daddr_t *) bp->b_data)[ap->in_off] = ndaddr; |
((ufs_daddr_t *) bp->b_data)[ap->in_off] = ndaddr; |
(void) VOP_BWRITE(bp); |
(void) VOP_BWRITE(bp); |
} |
} |
|
|
Line 136 rfw_update_single(struct uvnode *vp, dad |
|
Line 137 rfw_update_single(struct uvnode *vp, dad |
|
* and location. |
* and location. |
*/ |
*/ |
if (daddr > 0) { |
if (daddr > 0) { |
oldsn = lfs_dtosn(fs, daddr); |
oldsn = dtosn(fs, daddr); |
if (lbn >= 0 && lbn < ULFS_NDADDR) |
if (lbn >= 0 && lbn < NDADDR) |
osize = ip->i_lfs_fragsize[lbn]; |
osize = ip->i_lfs_fragsize[lbn]; |
else |
else |
osize = fs->lfs_bsize; |
osize = fs->lfs_bsize; |
Line 147 rfw_update_single(struct uvnode *vp, dad |
|
Line 148 rfw_update_single(struct uvnode *vp, dad |
|
if (!(bp->b_flags & B_GATHERED)) |
if (!(bp->b_flags & B_GATHERED)) |
fs->lfs_flags |= LFS_IFDIRTY; |
fs->lfs_flags |= LFS_IFDIRTY; |
LFS_WRITESEGENTRY(sup, fs, oldsn, bp); |
LFS_WRITESEGENTRY(sup, fs, oldsn, bp); |
for (i = 0; i < lfs_btofsb(fs, osize); i++) |
for (i = 0; i < btofsb(fs, osize); i++) |
clrbmap(daddr + i); |
clrbmap(daddr + i); |
} |
} |
|
|
Line 157 rfw_update_single(struct uvnode *vp, dad |
|
Line 158 rfw_update_single(struct uvnode *vp, dad |
|
} |
} |
|
|
/* If block frag size is too large for old EOF, update size */ |
/* If block frag size is too large for old EOF, update size */ |
if (lbn < ULFS_NDADDR) { |
if (lbn < NDADDR) { |
off_t minsize; |
off_t minsize; |
|
|
minsize = (lbn << fs->lfs_bshift); |
minsize = (lbn << fs->lfs_bshift); |
Line 170 rfw_update_single(struct uvnode *vp, dad |
|
Line 171 rfw_update_single(struct uvnode *vp, dad |
|
++nnewblocks; |
++nnewblocks; |
|
|
/* Add block to its new segment */ |
/* Add block to its new segment */ |
sn = lfs_dtosn(fs, ndaddr); |
sn = dtosn(fs, ndaddr); |
LFS_SEGENTRY(sup, fs, sn, bp); |
LFS_SEGENTRY(sup, fs, sn, bp); |
seg_table[sn].su_nbytes += size; |
seg_table[sn].su_nbytes += size; |
sup->su_nbytes += size; |
sup->su_nbytes += size; |
if (!(bp->b_flags & B_GATHERED)) |
if (!(bp->b_flags & B_GATHERED)) |
fs->lfs_flags |= LFS_IFDIRTY; |
fs->lfs_flags |= LFS_IFDIRTY; |
LFS_WRITESEGENTRY(sup, fs, sn, bp); |
LFS_WRITESEGENTRY(sup, fs, sn, bp); |
for (i = 0; i < lfs_btofsb(fs, size); i++) |
for (i = 0; i < btofsb(fs, size); i++) |
#ifndef VERBOSE_BLOCKMAP |
#ifndef VERBOSE_BLOCKMAP |
setbmap(daddr + i); |
setbmap(daddr + i); |
#else |
#else |
Line 186 rfw_update_single(struct uvnode *vp, dad |
|
Line 187 rfw_update_single(struct uvnode *vp, dad |
|
|
|
/* Check bfree accounting as well */ |
/* Check bfree accounting as well */ |
if (daddr <= 0) { |
if (daddr <= 0) { |
fs->lfs_bfree -= lfs_btofsb(fs, size); |
fs->lfs_bfree -= btofsb(fs, size); |
} else if (size != osize) { |
} else if (size != osize) { |
fs->lfs_bfree -= (frags - ofrags); |
fs->lfs_bfree -= (frags - ofrags); |
} |
} |
Line 196 rfw_update_single(struct uvnode *vp, dad |
|
Line 197 rfw_update_single(struct uvnode *vp, dad |
|
* segment no longer owns it, we can forget about its |
* segment no longer owns it, we can forget about its |
* old size. |
* old size. |
*/ |
*/ |
if (lbn >= 0 && lbn < ULFS_NDADDR) |
if (lbn >= 0 && lbn < NDADDR) |
ip->i_lfs_fragsize[lbn] = size; |
ip->i_lfs_fragsize[lbn] = size; |
} |
} |
|
|
Line 213 remove_ino(struct uvnode *vp, ino_t ino) |
|
Line 214 remove_ino(struct uvnode *vp, ino_t ino) |
|
CLEANERINFO *cip; |
CLEANERINFO *cip; |
struct ubuf *bp, *sbp, *cbp; |
struct ubuf *bp, *sbp, *cbp; |
struct inodesc idesc; |
struct inodesc idesc; |
ulfs_daddr_t daddr; |
ufs_daddr_t daddr; |
|
int obfree; |
|
|
if (debug) |
if (debug) |
pwarn("remove ino %d\n", (int)ino); |
pwarn("remove ino %d\n", (int)ino); |
|
|
|
obfree = fs->lfs_bfree; |
LFS_IENTRY(ifp, fs, ino, bp); |
LFS_IENTRY(ifp, fs, ino, bp); |
daddr = ifp->if_daddr; |
daddr = ifp->if_daddr; |
if (daddr > 0) { |
if (daddr > 0) { |
Line 231 remove_ino(struct uvnode *vp, ino_t ino) |
|
Line 234 remove_ino(struct uvnode *vp, ino_t ino) |
|
if (vp == NULL) |
if (vp == NULL) |
vp = lfs_raw_vget(fs, ino, fs->lfs_ivnode->v_fd, daddr); |
vp = lfs_raw_vget(fs, ino, fs->lfs_ivnode->v_fd, daddr); |
|
|
LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); |
LFS_SEGENTRY(sup, fs, dtosn(fs, daddr), sbp); |
sup->su_nbytes -= LFS_DINODE1_SIZE; |
sup->su_nbytes -= DINODE1_SIZE; |
VOP_BWRITE(sbp); |
VOP_BWRITE(sbp); |
seg_table[lfs_dtosn(fs, daddr)].su_nbytes -= LFS_DINODE1_SIZE; |
seg_table[dtosn(fs, daddr)].su_nbytes -= DINODE1_SIZE; |
} else |
} else |
brelse(bp, 0); |
brelse(bp, 0); |
|
|
Line 253 remove_ino(struct uvnode *vp, ino_t ino) |
|
Line 256 remove_ino(struct uvnode *vp, ino_t ino) |
|
* Use FIP records to update blocks, if the generation number matches. |
* Use FIP records to update blocks, if the generation number matches. |
*/ |
*/ |
static void |
static void |
pass6harvest(ulfs_daddr_t daddr, FINFO *fip) |
pass6harvest(ufs_daddr_t daddr, FINFO *fip) |
{ |
{ |
struct uvnode *vp; |
struct uvnode *vp; |
int i; |
int i; |
Line 271 pass6harvest(ulfs_daddr_t daddr, FINFO * |
|
Line 274 pass6harvest(ulfs_daddr_t daddr, FINFO * |
|
(long long)fip->fi_blocks[i], |
(long long)fip->fi_blocks[i], |
(long)daddr); |
(long)daddr); |
rfw_update_single(vp, fip->fi_blocks[i], daddr, size); |
rfw_update_single(vp, fip->fi_blocks[i], daddr, size); |
daddr += lfs_btofsb(fs, size); |
daddr += btofsb(fs, size); |
} |
} |
} |
} |
} |
} |
Line 291 pass6check(struct inodesc * idesc) |
|
Line 294 pass6check(struct inodesc * idesc) |
|
/* Check that the blocks do not lie within clean segments. */ |
/* Check that the blocks do not lie within clean segments. */ |
anyout = anynew = 0; |
anyout = anynew = 0; |
for (i = 0; i < idesc->id_numfrags; i++) { |
for (i = 0; i < idesc->id_numfrags; i++) { |
sn = lfs_dtosn(fs, idesc->id_blkno + i); |
sn = dtosn(fs, idesc->id_blkno + i); |
if (sn < 0 || sn >= fs->lfs_nseg || |
if (sn < 0 || sn >= fs->lfs_nseg || |
(seg_table[sn].su_flags & SEGUSE_DIRTY) == 0) { |
(seg_table[sn].su_flags & SEGUSE_DIRTY) == 0) { |
anyout = 1; |
anyout = 1; |
break; |
break; |
} |
} |
if (seg_table[sn].su_flags & SEGUSE_ACTIVE) { |
if (seg_table[sn].su_flags & SEGUSE_ACTIVE) { |
if (sn != lfs_dtosn(fs, fs->lfs_offset) || |
if (sn != dtosn(fs, fs->lfs_offset) || |
idesc->id_blkno > fs->lfs_offset) { |
idesc->id_blkno > fs->lfs_offset) { |
++anynew; |
++anynew; |
} |
} |
Line 306 pass6check(struct inodesc * idesc) |
|
Line 309 pass6check(struct inodesc * idesc) |
|
if (!anynew) { |
if (!anynew) { |
/* Clear so pass1check won't be surprised */ |
/* Clear so pass1check won't be surprised */ |
clrbmap(idesc->id_blkno + i); |
clrbmap(idesc->id_blkno + i); |
seg_table[sn].su_nbytes -= lfs_fsbtob(fs, 1); |
seg_table[sn].su_nbytes -= fsbtob(fs, 1); |
} |
} |
} |
} |
if (anyout) { |
if (anyout) { |
Line 326 pass6check(struct inodesc * idesc) |
|
Line 329 pass6check(struct inodesc * idesc) |
|
} |
} |
|
|
static void |
static void |
account_indir(struct uvnode *vp, struct ulfs1_dinode *dp, daddr_t ilbn, daddr_t daddr, int lvl) |
account_indir(struct uvnode *vp, struct ufs1_dinode *dp, daddr_t ilbn, daddr_t daddr, int lvl) |
{ |
{ |
struct ubuf *bp; |
struct ubuf *bp; |
int32_t *dap, *odap, *buf, *obuf; |
int32_t *dap, *odap, *buf, *obuf; |
Line 336 account_indir(struct uvnode *vp, struct |
|
Line 339 account_indir(struct uvnode *vp, struct |
|
lbn = -ilbn; |
lbn = -ilbn; |
else |
else |
lbn = ilbn + 1; |
lbn = ilbn + 1; |
bread(fs->lfs_devvp, LFS_FSBTODB(fs, daddr), fs->lfs_bsize, NULL, 0, &bp); |
bread(fs->lfs_devvp, fsbtodb(fs, daddr), fs->lfs_bsize, NULL, 0, &bp); |
buf = emalloc(fs->lfs_bsize); |
buf = emalloc(fs->lfs_bsize); |
memcpy(buf, bp->b_data, fs->lfs_bsize); |
memcpy(buf, bp->b_data, fs->lfs_bsize); |
brelse(bp, 0); |
brelse(bp, 0); |
Line 353 account_indir(struct uvnode *vp, struct |
|
Line 356 account_indir(struct uvnode *vp, struct |
|
dap < (int32_t *)((char *)buf + fs->lfs_bsize); |
dap < (int32_t *)((char *)buf + fs->lfs_bsize); |
++dap, ++odap) { |
++dap, ++odap) { |
if (*dap > 0 && *dap != *odap) { |
if (*dap > 0 && *dap != *odap) { |
rfw_update_single(vp, lbn, *dap, lfs_dblksize(fs, dp, lbn)); |
rfw_update_single(vp, lbn, *dap, dblksize(fs, dp, lbn)); |
if (lvl > 0) |
if (lvl > 0) |
account_indir(vp, dp, lbn, *dap, lvl - 1); |
account_indir(vp, dp, lbn, *dap, lvl - 1); |
} |
} |
if (lvl == 0) |
if (lvl == 0) |
++lbn; |
++lbn; |
else if (lvl == 1) |
else if (lvl == 1) |
lbn -= LFS_NINDIR(fs); |
lbn -= NINDIR(fs); |
else if (lvl == 2) |
else if (lvl == 2) |
lbn -= LFS_NINDIR(fs) * LFS_NINDIR(fs); |
lbn -= NINDIR(fs) * NINDIR(fs); |
} |
} |
|
|
free(obuf); |
free(obuf); |
Line 373 account_indir(struct uvnode *vp, struct |
|
Line 376 account_indir(struct uvnode *vp, struct |
|
* Account block changes between new found inode and existing inode. |
* Account block changes between new found inode and existing inode. |
*/ |
*/ |
static void |
static void |
account_block_changes(struct ulfs1_dinode *dp) |
account_block_changes(struct ufs1_dinode *dp) |
{ |
{ |
int i; |
int i; |
daddr_t lbn, off, odaddr; |
daddr_t lbn, off, odaddr; |
Line 384 account_block_changes(struct ulfs1_dinod |
|
Line 387 account_block_changes(struct ulfs1_dinod |
|
ip = (vp ? VTOI(vp) : NULL); |
ip = (vp ? VTOI(vp) : NULL); |
|
|
/* Check direct block holdings between existing and new */ |
/* Check direct block holdings between existing and new */ |
for (i = 0; i < ULFS_NDADDR; i++) { |
for (i = 0; i < NDADDR; i++) { |
odaddr = (ip ? ip->i_ffs1_db[i] : 0x0); |
odaddr = (ip ? ip->i_ffs1_db[i] : 0x0); |
if (dp->di_db[i] > 0 && dp->di_db[i] != odaddr) |
if (dp->di_db[i] > 0 && dp->di_db[i] != odaddr) |
rfw_update_single(vp, i, dp->di_db[i], |
rfw_update_single(vp, i, dp->di_db[i], |
lfs_dblksize(fs, dp, i)); |
dblksize(fs, dp, i)); |
} |
} |
|
|
/* Check indirect block holdings between existing and new */ |
/* Check indirect block holdings between existing and new */ |
off = 0; |
off = 0; |
for (i = 0; i < ULFS_NIADDR; i++) { |
for (i = 0; i < NIADDR; i++) { |
odaddr = (ip ? ip->i_ffs1_ib[i] : 0x0); |
odaddr = (ip ? ip->i_ffs1_ib[i] : 0x0); |
if (dp->di_ib[i] > 0 && dp->di_ib[i] != odaddr) { |
if (dp->di_ib[i] > 0 && dp->di_ib[i] != odaddr) { |
lbn = -(ULFS_NDADDR + off + i); |
lbn = -(NDADDR + off + i); |
rfw_update_single(vp, i, dp->di_ib[i], fs->lfs_bsize); |
rfw_update_single(vp, i, dp->di_ib[i], fs->lfs_bsize); |
account_indir(vp, dp, lbn, dp->di_ib[i], i); |
account_indir(vp, dp, lbn, dp->di_ib[i], i); |
} |
} |
if (off == 0) |
if (off == 0) |
off = LFS_NINDIR(fs); |
off = NINDIR(fs); |
else |
else |
off *= LFS_NINDIR(fs); |
off *= NINDIR(fs); |
} |
} |
} |
} |
|
|
Line 415 account_block_changes(struct ulfs1_dinod |
|
Line 418 account_block_changes(struct ulfs1_dinod |
|
* free list accounting is done. |
* free list accounting is done. |
*/ |
*/ |
static void |
static void |
readdress_inode(struct ulfs1_dinode *dp, ulfs_daddr_t daddr) |
readdress_inode(struct ufs1_dinode *dp, ufs_daddr_t daddr) |
{ |
{ |
IFILE *ifp; |
IFILE *ifp; |
SEGUSE *sup; |
SEGUSE *sup; |
struct ubuf *bp; |
struct ubuf *bp; |
int sn; |
int sn; |
ulfs_daddr_t odaddr; |
ufs_daddr_t odaddr; |
ino_t thisino = dp->di_inumber; |
ino_t thisino = dp->di_inumber; |
struct uvnode *vp; |
struct uvnode *vp; |
|
|
Line 447 readdress_inode(struct ulfs1_dinode *dp, |
|
Line 450 readdress_inode(struct ulfs1_dinode *dp, |
|
memcpy(VTOI(vp)->i_din.ffs1_din, dp, sizeof(*dp)); |
memcpy(VTOI(vp)->i_din.ffs1_din, dp, sizeof(*dp)); |
|
|
/* Finally account the inode itself */ |
/* Finally account the inode itself */ |
sn = lfs_dtosn(fs, odaddr); |
sn = dtosn(fs, odaddr); |
LFS_SEGENTRY(sup, fs, sn, bp); |
LFS_SEGENTRY(sup, fs, sn, bp); |
sup->su_nbytes -= LFS_DINODE1_SIZE; |
sup->su_nbytes -= DINODE1_SIZE; |
VOP_BWRITE(bp); |
VOP_BWRITE(bp); |
seg_table[sn].su_nbytes -= LFS_DINODE1_SIZE; |
seg_table[sn].su_nbytes -= DINODE1_SIZE; |
|
|
sn = lfs_dtosn(fs, daddr); |
sn = dtosn(fs, daddr); |
LFS_SEGENTRY(sup, fs, sn, bp); |
LFS_SEGENTRY(sup, fs, sn, bp); |
sup->su_nbytes += LFS_DINODE1_SIZE; |
sup->su_nbytes += DINODE1_SIZE; |
VOP_BWRITE(bp); |
VOP_BWRITE(bp); |
seg_table[sn].su_nbytes += LFS_DINODE1_SIZE; |
seg_table[sn].su_nbytes += DINODE1_SIZE; |
} |
} |
|
|
/* |
/* |
* Allocate the given inode from the free list. |
* Allocate the given inode from the free list. |
*/ |
*/ |
static void |
static void |
alloc_inode(ino_t thisino, ulfs_daddr_t daddr) |
alloc_inode(ino_t thisino, ufs_daddr_t daddr) |
{ |
{ |
ino_t ino, nextfree, oldhead; |
ino_t ino, nextfree, oldhead; |
IFILE *ifp; |
IFILE *ifp; |
Line 515 alloc_inode(ino_t thisino, ulfs_daddr_t |
|
Line 518 alloc_inode(ino_t thisino, ulfs_daddr_t |
|
} |
} |
|
|
/* Account for new location */ |
/* Account for new location */ |
LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), bp); |
LFS_SEGENTRY(sup, fs, dtosn(fs, daddr), bp); |
sup->su_nbytes += LFS_DINODE1_SIZE; |
sup->su_nbytes += DINODE1_SIZE; |
VOP_BWRITE(bp); |
VOP_BWRITE(bp); |
seg_table[lfs_dtosn(fs, daddr)].su_nbytes += LFS_DINODE1_SIZE; |
seg_table[dtosn(fs, daddr)].su_nbytes += DINODE1_SIZE; |
} |
} |
|
|
/* |
/* |
Line 541 alloc_inode(ino_t thisino, ulfs_daddr_t |
|
Line 544 alloc_inode(ino_t thisino, ulfs_daddr_t |
|
void |
void |
pass6(void) |
pass6(void) |
{ |
{ |
ulfs_daddr_t daddr, ibdaddr, odaddr, lastgood, *idaddrp; |
ufs_daddr_t daddr, ibdaddr, odaddr, lastgood, nextseg, *idaddrp; |
struct uvnode *vp, *devvp; |
struct uvnode *vp, *devvp; |
CLEANERINFO *cip; |
CLEANERINFO *cip; |
SEGUSE *sup; |
SEGUSE *sup; |
SEGSUM *sp; |
SEGSUM *sp; |
struct ubuf *bp, *ibp, *sbp, *cbp; |
struct ubuf *bp, *ibp, *sbp, *cbp; |
struct ulfs1_dinode *dp; |
struct ufs1_dinode *dp; |
struct inodesc idesc; |
struct inodesc idesc; |
int i, j, bc, hassuper; |
int i, j, bc, hassuper; |
int nnewfiles, ndelfiles, nmvfiles; |
int nnewfiles, ndelfiles, nmvfiles; |
|
|
ibbuf = emalloc(fs->lfs_ibsize); |
ibbuf = emalloc(fs->lfs_ibsize); |
nnewfiles = ndelfiles = nmvfiles = nnewblocks = 0; |
nnewfiles = ndelfiles = nmvfiles = nnewblocks = 0; |
daddr = fs->lfs_offset; |
daddr = fs->lfs_offset; |
|
nextseg = fs->lfs_nextseg; |
hassuper = 0; |
hassuper = 0; |
lastserial = 0; |
lastserial = 0; |
while (daddr != lastgood) { |
while (daddr != lastgood) { |
seg_table[lfs_dtosn(fs, daddr)].su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE; |
seg_table[dtosn(fs, daddr)].su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE; |
LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); |
LFS_SEGENTRY(sup, fs, dtosn(fs, daddr), sbp); |
sup->su_flags |= SEGUSE_DIRTY; |
sup->su_flags |= SEGUSE_DIRTY; |
VOP_BWRITE(sbp); |
VOP_BWRITE(sbp); |
|
|
/* Could be a superblock */ |
/* Could be a superblock */ |
if (lfs_sntod(fs, lfs_dtosn(fs, daddr)) == daddr) { |
if (sntod(fs, dtosn(fs, daddr)) == daddr) { |
if (daddr == fs->lfs_start) { |
if (daddr == fs->lfs_start) { |
++hassuper; |
++hassuper; |
daddr += lfs_btofsb(fs, LFS_LABELPAD); |
daddr += btofsb(fs, LFS_LABELPAD); |
} |
} |
for (i = 0; i < LFS_MAXNUMSB; i++) { |
for (i = 0; i < LFS_MAXNUMSB; i++) { |
if (daddr == fs->lfs_sboffs[i]) { |
if (daddr == fs->lfs_sboffs[i]) { |
++hassuper; |
++hassuper; |
daddr += lfs_btofsb(fs, LFS_SBPAD); |
daddr += btofsb(fs, LFS_SBPAD); |
} |
} |
if (daddr < fs->lfs_sboffs[i]) |
if (daddr < fs->lfs_sboffs[i]) |
break; |
break; |
|
|
} |
} |
|
|
/* Read in summary block */ |
/* Read in summary block */ |
bread(devvp, LFS_FSBTODB(fs, daddr), fs->lfs_sumsize, NULL, 0, &bp); |
bread(devvp, fsbtodb(fs, daddr), fs->lfs_sumsize, NULL, 0, &bp); |
sp = (SEGSUM *)bp->b_data; |
sp = (SEGSUM *)bp->b_data; |
if (debug) |
if (debug) |
pwarn("sum at 0x%x: ninos=%d nfinfo=%d\n", |
pwarn("sum at 0x%x: ninos=%d nfinfo=%d\n", |
|
|
(int)sp->ss_nfinfo); |
(int)sp->ss_nfinfo); |
|
|
/* We have verified that this is a good summary. */ |
/* We have verified that this is a good summary. */ |
LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); |
LFS_SEGENTRY(sup, fs, dtosn(fs, daddr), sbp); |
++sup->su_nsums; |
++sup->su_nsums; |
VOP_BWRITE(sbp); |
VOP_BWRITE(sbp); |
fs->lfs_bfree -= lfs_btofsb(fs, fs->lfs_sumsize); |
fs->lfs_bfree -= btofsb(fs, fs->lfs_sumsize); |
fs->lfs_dmeta += lfs_btofsb(fs, fs->lfs_sumsize); |
fs->lfs_dmeta += btofsb(fs, fs->lfs_sumsize); |
sbdirty(); |
sbdirty(); |
if (lfs_sntod(fs, lfs_dtosn(fs, daddr)) == daddr + |
nextseg = sp->ss_next; |
hassuper * lfs_btofsb(fs, LFS_SBPAD) && |
if (sntod(fs, dtosn(fs, daddr)) == daddr + |
lfs_dtosn(fs, daddr) != lfs_dtosn(fs, fs->lfs_offset)) { |
hassuper * btofsb(fs, LFS_SBPAD) && |
|
dtosn(fs, daddr) != dtosn(fs, fs->lfs_offset)) { |
--fs->lfs_nclean; |
--fs->lfs_nclean; |
sbdirty(); |
sbdirty(); |
} |
} |
|
|
/* Find inodes, look at generation number. */ |
/* Find inodes, look at generation number. */ |
if (sp->ss_ninos) { |
if (sp->ss_ninos) { |
LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); |
LFS_SEGENTRY(sup, fs, dtosn(fs, daddr), sbp); |
sup->su_ninos += howmany(sp->ss_ninos, LFS_INOPB(fs)); |
sup->su_ninos += howmany(sp->ss_ninos, INOPB(fs)); |
VOP_BWRITE(sbp); |
VOP_BWRITE(sbp); |
fs->lfs_dmeta += lfs_btofsb(fs, howmany(sp->ss_ninos, |
fs->lfs_dmeta += btofsb(fs, howmany(sp->ss_ninos, |
LFS_INOPB(fs)) * |
INOPB(fs)) * |
fs->lfs_ibsize); |
fs->lfs_ibsize); |
} |
} |
idaddrp = ((ulfs_daddr_t *)((char *)bp->b_data + fs->lfs_sumsize)); |
idaddrp = ((ufs_daddr_t *)((char *)bp->b_data + fs->lfs_sumsize)); |
for (i = 0; i < howmany(sp->ss_ninos, LFS_INOPB(fs)); i++) { |
for (i = 0; i < howmany(sp->ss_ninos, INOPB(fs)); i++) { |
ino_t *inums; |
ino_t *inums; |
|
|
inums = ecalloc(LFS_INOPB(fs) + 1, sizeof(*inums)); |
inums = ecalloc(INOPB(fs) + 1, sizeof(*inums)); |
ibdaddr = *--idaddrp; |
ibdaddr = *--idaddrp; |
fs->lfs_bfree -= lfs_btofsb(fs, fs->lfs_ibsize); |
fs->lfs_bfree -= btofsb(fs, fs->lfs_ibsize); |
sbdirty(); |
sbdirty(); |
bread(devvp, LFS_FSBTODB(fs, ibdaddr), fs->lfs_ibsize, |
bread(devvp, fsbtodb(fs, ibdaddr), fs->lfs_ibsize, |
NOCRED, 0, &ibp); |
NOCRED, 0, &ibp); |
memcpy(ibbuf, ibp->b_data, fs->lfs_ibsize); |
memcpy(ibbuf, ibp->b_data, fs->lfs_ibsize); |
brelse(ibp, 0); |
brelse(ibp, 0); |
|
|
j = 0; |
j = 0; |
for (dp = (struct ulfs1_dinode *)ibbuf; |
for (dp = (struct ufs1_dinode *)ibbuf; |
dp < (struct ulfs1_dinode *)ibbuf + LFS_INOPB(fs); |
dp < (struct ufs1_dinode *)ibbuf + INOPB(fs); |
++dp) { |
++dp) { |
if (dp->di_inumber == 0 || |
if (dp->di_u.inumber == 0 || |
dp->di_inumber == fs->lfs_ifile) |
dp->di_u.inumber == fs->lfs_ifile) |
continue; |
continue; |
/* Basic sanity checks */ |
/* Basic sanity checks */ |
if (dp->di_nlink < 0 |
if (dp->di_nlink < 0 |
|
|
goto out; |
goto out; |
} |
} |
|
|
vp = vget(fs, dp->di_inumber); |
vp = vget(fs, dp->di_u.inumber); |
|
|
/* |
/* |
* Four cases: |
* Four cases: |
|
|
* If currently allocated, remove. |
* If currently allocated, remove. |
*/ |
*/ |
if (dp->di_nlink == 0) { |
if (dp->di_nlink == 0) { |
remove_ino(vp, dp->di_inumber); |
remove_ino(vp, dp->di_u.inumber); |
++ndelfiles; |
++ndelfiles; |
continue; |
continue; |
} |
} |
|
|
if (!(sp->ss_flags & SS_DIROP)) |
if (!(sp->ss_flags & SS_DIROP)) |
pfatal("NEW FILE IN NON-DIROP PARTIAL SEGMENT"); |
pfatal("NEW FILE IN NON-DIROP PARTIAL SEGMENT"); |
else { |
else { |
inums[j++] = dp->di_inumber; |
inums[j++] = dp->di_u.inumber; |
nnewfiles++; |
nnewfiles++; |
} |
} |
continue; |
continue; |
|
|
* and proceed as in (2). |
* and proceed as in (2). |
*/ |
*/ |
if (vp && VTOI(vp)->i_ffs1_gen < dp->di_gen) { |
if (vp && VTOI(vp)->i_ffs1_gen < dp->di_gen) { |
remove_ino(vp, dp->di_inumber); |
remove_ino(vp, dp->di_u.inumber); |
if (!(sp->ss_flags & SS_DIROP)) |
if (!(sp->ss_flags & SS_DIROP)) |
pfatal("NEW FILE VERSION IN NON-DIROP PARTIAL SEGMENT"); |
pfatal("NEW FILE VERSION IN NON-DIROP PARTIAL SEGMENT"); |
else { |
else { |
inums[j++] = dp->di_inumber; |
inums[j++] = dp->di_u.inumber; |
ndelfiles++; |
ndelfiles++; |
nnewfiles++; |
nnewfiles++; |
} |
} |
|
|
if (debug) |
if (debug) |
pwarn("alloc ino %d nlink %d\n", |
pwarn("alloc ino %d nlink %d\n", |
(int)inums[j], VTOD(vp)->di_nlink); |
(int)inums[j], VTOD(vp)->di_nlink); |
memset(VTOD(vp)->di_db, 0, (ULFS_NDADDR + ULFS_NIADDR) * |
memset(VTOD(vp)->di_db, 0, (NDADDR + NIADDR) * |
sizeof(ulfs_daddr_t)); |
sizeof(ufs_daddr_t)); |
VTOD(vp)->di_blocks = 0; |
VTOD(vp)->di_blocks = 0; |
|
|
vp->v_uflag |= VU_DIROP; |
vp->v_uflag |= VU_DIROP; |
|
|
lastserial = sp->ss_serial; |
lastserial = sp->ss_serial; |
} |
} |
odaddr = daddr; |
odaddr = daddr; |
daddr += lfs_btofsb(fs, fs->lfs_sumsize + bc); |
daddr += btofsb(fs, fs->lfs_sumsize + bc); |
if (lfs_dtosn(fs, odaddr) != lfs_dtosn(fs, daddr) || |
if (dtosn(fs, odaddr) != dtosn(fs, daddr) || |
lfs_dtosn(fs, daddr) != lfs_dtosn(fs, daddr + |
dtosn(fs, daddr) != dtosn(fs, daddr + |
lfs_btofsb(fs, fs->lfs_sumsize + fs->lfs_bsize) - 1)) { |
btofsb(fs, fs->lfs_sumsize + fs->lfs_bsize) - 1)) { |
daddr = ((SEGSUM *)bp->b_data)->ss_next; |
daddr = ((SEGSUM *)bp->b_data)->ss_next; |
} |
} |
brelse(bp, 0); |
brelse(bp, 0); |
|
|
*/ |
*/ |
daddr = fs->lfs_offset; |
daddr = fs->lfs_offset; |
while (daddr != lastgood) { |
while (daddr != lastgood) { |
if (!(seg_table[lfs_dtosn(fs, daddr)].su_flags & SEGUSE_DIRTY)) { |
if (!(seg_table[dtosn(fs, daddr)].su_flags & SEGUSE_DIRTY)) { |
seg_table[lfs_dtosn(fs, daddr)].su_flags |= SEGUSE_DIRTY; |
seg_table[dtosn(fs, daddr)].su_flags |= SEGUSE_DIRTY; |
LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); |
LFS_SEGENTRY(sup, fs, dtosn(fs, daddr), sbp); |
sup->su_flags |= SEGUSE_DIRTY; |
sup->su_flags |= SEGUSE_DIRTY; |
VOP_BWRITE(sbp); |
VOP_BWRITE(sbp); |
} |
} |
|
|
/* Could be a superblock */ |
/* Could be a superblock */ |
if (lfs_sntod(fs, lfs_dtosn(fs, daddr)) == daddr) { |
if (sntod(fs, dtosn(fs, daddr)) == daddr) { |
if (daddr == fs->lfs_start) |
if (daddr == fs->lfs_start) |
daddr += lfs_btofsb(fs, LFS_LABELPAD); |
daddr += btofsb(fs, LFS_LABELPAD); |
for (i = 0; i < LFS_MAXNUMSB; i++) { |
for (i = 0; i < LFS_MAXNUMSB; i++) { |
if (daddr == fs->lfs_sboffs[i]) { |
if (daddr == fs->lfs_sboffs[i]) { |
daddr += lfs_btofsb(fs, LFS_SBPAD); |
daddr += btofsb(fs, LFS_SBPAD); |
} |
} |
if (daddr < fs->lfs_sboffs[i]) |
if (daddr < fs->lfs_sboffs[i]) |
break; |
break; |
|
|
} |
} |
|
|
/* Read in summary block */ |
/* Read in summary block */ |
bread(devvp, LFS_FSBTODB(fs, daddr), fs->lfs_sumsize, NULL, 0, &bp); |
bread(devvp, fsbtodb(fs, daddr), fs->lfs_sumsize, NULL, 0, &bp); |
sp = (SEGSUM *)bp->b_data; |
sp = (SEGSUM *)bp->b_data; |
bc = check_summary(fs, sp, daddr, debug, devvp, pass6harvest); |
bc = check_summary(fs, sp, daddr, debug, devvp, pass6harvest); |
if (bc == 0) { |
if (bc == 0) { |
|
|
break; |
break; |
} |
} |
odaddr = daddr; |
odaddr = daddr; |
daddr += lfs_btofsb(fs, fs->lfs_sumsize + bc); |
daddr += btofsb(fs, fs->lfs_sumsize + bc); |
fs->lfs_avail -= lfs_btofsb(fs, fs->lfs_sumsize + bc); |
fs->lfs_avail -= btofsb(fs, fs->lfs_sumsize + bc); |
if (lfs_dtosn(fs, odaddr) != lfs_dtosn(fs, daddr) || |
if (dtosn(fs, odaddr) != dtosn(fs, daddr) || |
lfs_dtosn(fs, daddr) != lfs_dtosn(fs, daddr + |
dtosn(fs, daddr) != dtosn(fs, daddr + |
lfs_btofsb(fs, fs->lfs_sumsize + fs->lfs_bsize) - 1)) { |
btofsb(fs, fs->lfs_sumsize + fs->lfs_bsize) - 1)) { |
fs->lfs_avail -= lfs_sntod(fs, lfs_dtosn(fs, daddr) + 1) - daddr; |
fs->lfs_avail -= sntod(fs, dtosn(fs, daddr) + 1) - daddr; |
daddr = ((SEGSUM *)bp->b_data)->ss_next; |
daddr = ((SEGSUM *)bp->b_data)->ss_next; |
} |
} |
LFS_CLEANERINFO(cip, fs, cbp); |
LFS_CLEANERINFO(cip, fs, cbp); |
|
|
} |
} |
|
|
/* Final address could also be a superblock */ |
/* Final address could also be a superblock */ |
if (lfs_sntod(fs, lfs_dtosn(fs, lastgood)) == lastgood) { |
if (sntod(fs, dtosn(fs, lastgood)) == lastgood) { |
if (lastgood == fs->lfs_start) |
if (lastgood == fs->lfs_start) |
lastgood += lfs_btofsb(fs, LFS_LABELPAD); |
lastgood += btofsb(fs, LFS_LABELPAD); |
for (i = 0; i < LFS_MAXNUMSB; i++) { |
for (i = 0; i < LFS_MAXNUMSB; i++) { |
if (lastgood == fs->lfs_sboffs[i]) |
if (lastgood == fs->lfs_sboffs[i]) |
lastgood += lfs_btofsb(fs, LFS_SBPAD); |
lastgood += btofsb(fs, LFS_SBPAD); |
if (lastgood < fs->lfs_sboffs[i]) |
if (lastgood < fs->lfs_sboffs[i]) |
break; |
break; |
} |
} |
|
|
|
|
/* Update offset to point at correct location */ |
/* Update offset to point at correct location */ |
fs->lfs_offset = lastgood; |
fs->lfs_offset = lastgood; |
fs->lfs_curseg = lfs_sntod(fs, lfs_dtosn(fs, lastgood)); |
fs->lfs_curseg = sntod(fs, dtosn(fs, lastgood)); |
for (sn = curseg = lfs_dtosn(fs, fs->lfs_curseg);;) { |
for (sn = curseg = dtosn(fs, fs->lfs_curseg);;) { |
sn = (sn + 1) % fs->lfs_nseg; |
sn = (sn + 1) % fs->lfs_nseg; |
if (sn == curseg) |
if (sn == curseg) |
errx(1, "no clean segments"); |
errx(1, "no clean segments"); |
|
|
} |
} |
brelse(bp, 0); |
brelse(bp, 0); |
} |
} |
fs->lfs_nextseg = lfs_sntod(fs, sn); |
fs->lfs_nextseg = sntod(fs, sn); |
|
|
if (preen) { |
if (preen) { |
if (ndelfiles) |
if (ndelfiles) |