summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2002-02-02 01:42:44 +0000
committermckusick <mckusick@FreeBSD.org>2002-02-02 01:42:44 +0000
commitc142ab455cd4b7427fe561e5cd19e3d40a54835b (patch)
treef05537f6403fa281b365382d8c7b69842cdf2af5
parent664993c2615f86de7949f69ae74763c7562ae922 (diff)
downloadFreeBSD-src-c142ab455cd4b7427fe561e5cd19e3d40a54835b.zip
FreeBSD-src-c142ab455cd4b7427fe561e5cd19e3d40a54835b.tar.gz
When taking a snapshot, we must check for active files that have
been unlinked (e.g., with a zero link count). We have to expunge all trace of these files from the snapshot so that they are neither reclaimed prematurely by fsck nor saved unnecessarily by dump.
-rw-r--r--sys/ufs/ffs/ffs_alloc.c139
-rw-r--r--sys/ufs/ffs/ffs_balloc.c2
-rw-r--r--sys/ufs/ffs/ffs_extern.h8
-rw-r--r--sys/ufs/ffs/ffs_inode.c10
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c376
-rw-r--r--sys/ufs/ffs/ffs_softdep.c73
6 files changed, 336 insertions, 272 deletions
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index aa6f31c..79fcb91 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -71,7 +71,7 @@ static ufs_daddr_t ffs_clusteralloc __P((struct inode *, int, ufs_daddr_t,
int));
static ino_t ffs_dirpref __P((struct inode *));
static ufs_daddr_t ffs_fragextend __P((struct inode *, int, long, int, int));
-static void ffs_fserr __P((struct fs *, u_int, char *));
+static void ffs_fserr __P((struct fs *, ino_t, char *));
static u_long ffs_hashalloc
__P((struct inode *, int, long, int, allocfcn_t *));
static ino_t ffs_nodealloccg __P((struct inode *, int, ufs_daddr_t, int));
@@ -162,7 +162,7 @@ nospace:
softdep_request_cleanup(fs, ITOV(ip));
goto retry;
}
- ffs_fserr(fs, cred->cr_uid, "file system full");
+ ffs_fserr(fs, ip->i_number, "file system full");
uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
return (ENOSPC);
}
@@ -309,10 +309,11 @@ retry:
if (bno > 0) {
bp->b_blkno = fsbtodb(fs, bno);
if (!DOINGSOFTDEP(vp))
- ffs_blkfree(ip, bprev, (long)osize);
+ ffs_blkfree(fs, ip->i_devvp, bprev, (long)osize,
+ ip->i_number);
if (nsize < request)
- ffs_blkfree(ip, bno + numfrags(fs, nsize),
- (long)(request - nsize));
+ ffs_blkfree(fs, ip->i_devvp, bno + numfrags(fs, nsize),
+ (long)(request - nsize), ip->i_number);
ip->i_blocks += btodb(nsize - osize);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
allocbuf(bp, nsize);
@@ -337,7 +338,7 @@ nospace:
softdep_request_cleanup(fs, vp);
goto retry;
}
- ffs_fserr(fs, cred->cr_uid, "file system full");
+ ffs_fserr(fs, ip->i_number, "file system full");
uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
return (ENOSPC);
}
@@ -542,9 +543,9 @@ ffs_reallocblks(ap)
#endif
for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) {
if (!DOINGSOFTDEP(vp))
- ffs_blkfree(ip,
+ ffs_blkfree(fs, ip->i_devvp,
dbtofsb(fs, buflist->bs_children[i]->b_blkno),
- fs->fs_bsize);
+ fs->fs_bsize, ip->i_number);
buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
#ifdef DIAGNOSTIC
if (!ffs_checkblk(ip,
@@ -652,7 +653,7 @@ ffs_valloc(pvp, mode, cred, vpp)
ip->i_gen = random() / 2 + 1;
return (0);
noinodes:
- ffs_fserr(fs, cred->cr_uid, "out of inodes");
+ ffs_fserr(fs, pip->i_number, "out of inodes");
uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);
return (ENOSPC);
}
@@ -1427,48 +1428,52 @@ gotit:
* block reassembly is checked.
*/
void
-ffs_blkfree(ip, bno, size)
- register struct inode *ip;
+ffs_blkfree(fs, devvp, bno, size, inum)
+ struct fs *fs;
+ struct vnode *devvp;
ufs_daddr_t bno;
long size;
+ ino_t inum;
{
- register struct fs *fs;
- register struct cg *cgp;
+ struct cg *cgp;
struct buf *bp;
ufs_daddr_t fragno, cgbno;
int i, error, cg, blk, frags, bbase;
u_int8_t *blksfree;
-#ifdef DIAGNOSTIC
- struct vnode *vp;
-#endif
+ dev_t dev;
- fs = ip->i_fs;
+ cg = dtog(fs, bno);
+ if (devvp->v_type != VCHR) {
+ /* devvp is a snapshot */
+ dev = VTOI(devvp)->i_devvp->v_rdev;
+ cgbno = fragstoblks(fs, cgtod(fs, cg));
+ } else {
+ /* devvp is a normal disk device */
+ dev = devvp->v_rdev;
+ cgbno = fsbtodb(fs, cgtod(fs, cg));
+ if ((devvp->v_flag & VCOPYONWRITE) &&
+ ffs_snapblkfree(fs, devvp, bno, size, inum))
+ return;
+ VOP_FREEBLKS(devvp, fsbtodb(fs, bno), size);
+ }
#ifdef DIAGNOSTIC
- if ((vp = ITOV(ip)) != NULL && vp->v_mount != NULL &&
- (vp->v_mount->mnt_kern_flag & MNTK_SUSPENDED))
+ if (dev->si_mountpoint &&
+ (dev->si_mountpoint->mnt_kern_flag & MNTK_SUSPENDED))
panic("ffs_blkfree: deallocation on suspended filesystem");
if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 ||
fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
printf("dev=%s, bno = %ld, bsize = %ld, size = %ld, fs = %s\n",
- devtoname(ip->i_dev), (long)bno, (long)fs->fs_bsize, size,
- fs->fs_fsmnt);
+ devtoname(dev), (long)bno, (long)fs->fs_bsize,
+ size, fs->fs_fsmnt);
panic("ffs_blkfree: bad size");
}
#endif
- if ((ip->i_devvp->v_flag & VCOPYONWRITE) &&
- ffs_snapblkfree(ip, bno, size))
- return;
- VOP_FREEBLKS(ip->i_devvp, fsbtodb(fs, bno), size);
- cg = dtog(fs, bno);
if ((u_int)bno >= fs->fs_size) {
- printf("bad block %ld, ino %lu\n",
- (long)bno, (u_long)ip->i_number);
- ffs_fserr(fs, ip->i_uid, "bad block");
+ printf("bad block %ld, ino %lu\n", (long)bno, (u_long)inum);
+ ffs_fserr(fs, inum, "bad block");
return;
}
- error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
- (int)fs->fs_cgsize, NOCRED, &bp);
- if (error) {
+ if ((error = bread(devvp, cgbno, (int)fs->fs_cgsize, NOCRED, &bp))) {
brelse(bp);
return;
}
@@ -1484,8 +1489,13 @@ ffs_blkfree(ip, bno, size)
if (size == fs->fs_bsize) {
fragno = fragstoblks(fs, cgbno);
if (!ffs_isfreeblock(fs, blksfree, fragno)) {
+ if (devvp->v_type != VCHR) {
+ /* devvp is a snapshot */
+ brelse(bp);
+ return;
+ }
printf("dev = %s, block = %ld, fs = %s\n",
- devtoname(ip->i_dev), (long)bno, fs->fs_fsmnt);
+ devtoname(dev), (long)bno, fs->fs_fsmnt);
panic("ffs_blkfree: freeing free block");
}
ffs_setblock(fs, blksfree, fragno);
@@ -1510,7 +1520,7 @@ ffs_blkfree(ip, bno, size)
for (i = 0; i < frags; i++) {
if (isset(blksfree, cgbno + i)) {
printf("dev = %s, block = %ld, fs = %s\n",
- devtoname(ip->i_dev), (long)(bno + i),
+ devtoname(dev), (long)(bno + i),
fs->fs_fsmnt);
panic("ffs_blkfree: freeing free frag");
}
@@ -1610,7 +1620,7 @@ ffs_vfree(pvp, ino, mode)
softdep_freefile(pvp, ino, mode);
return (0);
}
- return (ffs_freefile(VTOI(pvp), ino, mode));
+ return (ffs_freefile(VTOI(pvp)->i_fs, VTOI(pvp)->i_devvp, ino, mode));
}
/*
@@ -1618,25 +1628,32 @@ ffs_vfree(pvp, ino, mode)
* The specified inode is placed back in the free map.
*/
int
-ffs_freefile(pip, ino, mode)
- struct inode *pip;
+ffs_freefile(fs, devvp, ino, mode)
+ struct fs *fs;
+ struct vnode *devvp;
ino_t ino;
int mode;
{
- register struct fs *fs;
- register struct cg *cgp;
+ struct cg *cgp;
struct buf *bp;
- int error, cg;
+ int error, cgbno, cg;
u_int8_t *inosused;
+ dev_t dev;
- fs = pip->i_fs;
- if ((u_int)ino >= fs->fs_ipg * fs->fs_ncg)
- panic("ffs_vfree: range: dev = (%d,%d), ino = %d, fs = %s",
- major(pip->i_dev), minor(pip->i_dev), ino, fs->fs_fsmnt);
cg = ino_to_cg(fs, ino);
- error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
- (int)fs->fs_cgsize, NOCRED, &bp);
- if (error) {
+ if (devvp->v_type != VCHR) {
+ /* devvp is a snapshot */
+ dev = VTOI(devvp)->i_devvp->v_rdev;
+ cgbno = fragstoblks(fs, cgtod(fs, cg));
+ } else {
+ /* devvp is a normal disk device */
+ dev = devvp->v_rdev;
+ cgbno = fsbtodb(fs, cgtod(fs, cg));
+ }
+ if ((u_int)ino >= fs->fs_ipg * fs->fs_ncg)
+ panic("ffs_vfree: range: dev = %s, ino = %d, fs = %s",
+ devtoname(dev), ino, fs->fs_fsmnt);
+ if ((error = bread(devvp, cgbno, (int)fs->fs_cgsize, NOCRED, &bp))) {
brelse(bp);
return (error);
}
@@ -1650,7 +1667,7 @@ ffs_freefile(pip, ino, mode)
inosused = cg_inosused(cgp);
ino %= fs->fs_ipg;
if (isclr(inosused, ino)) {
- printf("dev = %s, ino = %lu, fs = %s\n", devtoname(pip->i_dev),
+ printf("dev = %s, ino = %lu, fs = %s\n", devtoname(dev),
(u_long)ino + cg * fs->fs_ipg, fs->fs_fsmnt);
if (fs->fs_ronly == 0)
panic("ffs_vfree: freeing free inode");
@@ -1837,15 +1854,16 @@ ffs_clusteracct(fs, cgp, blkno, cnt)
* fs: error message
*/
static void
-ffs_fserr(fs, uid, cp)
+ffs_fserr(fs, inum, cp)
struct fs *fs;
- u_int uid;
+ ino_t inum;
char *cp;
{
struct proc *p = curproc; /* XXX */
- log(LOG_ERR, "pid %d (%s), uid %d on %s: %s\n", p ? p->p_pid : -1,
- p ? p->p_comm : "-", uid, fs->fs_fsmnt, cp);
+ log(LOG_ERR, "pid %d (%s), uid %d inumber %d on %s: %s\n",
+ p ? p->p_pid : -1, p ? p->p_comm : "-",
+ p ? p->p_ucred->cr_uid : 0, inum, fs->fs_fsmnt, cp);
}
/*
@@ -1900,7 +1918,6 @@ static int
sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
{
struct fsck_cmd cmd;
- struct inode tip;
struct ufsmount *ump;
struct vnode *vp;
struct inode *ip;
@@ -2003,11 +2020,9 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
(ino_t)(cmd.value + cmd.size - 1));
}
#endif /* DEBUG */
- tip.i_devvp = ump->um_devvp;
- tip.i_dev = ump->um_dev;
- tip.i_fs = fs;
while (cmd.size > 0) {
- if ((error = ffs_freefile(&tip, cmd.value, filetype)))
+ if ((error = ffs_freefile(fs, ump->um_devvp, cmd.value,
+ filetype)))
break;
cmd.size -= 1;
cmd.value += 1;
@@ -2028,20 +2043,14 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
(ufs_daddr_t)cmd.value + cmd.size - 1);
}
#endif /* DEBUG */
- tip.i_number = ROOTINO;
- tip.i_devvp = ump->um_devvp;
- tip.i_dev = ump->um_dev;
- tip.i_fs = fs;
- tip.i_size = cmd.size * fs->fs_fsize;
- tip.i_uid = 0;
- tip.i_vnode = NULL;
blkno = (ufs_daddr_t)cmd.value;
blkcnt = cmd.size;
blksize = fs->fs_frag - (blkno % fs->fs_frag);
while (blkcnt > 0) {
if (blksize > blkcnt)
blksize = blkcnt;
- ffs_blkfree(&tip, blkno, blksize * fs->fs_fsize);
+ ffs_blkfree(fs, ump->um_devvp, blkno,
+ blksize * fs->fs_fsize, ROOTINO);
blkno += blksize;
blkcnt -= blksize;
blksize = fs->fs_frag;
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
index 26747fc..dbfe075 100644
--- a/sys/ufs/ffs/ffs_balloc.c
+++ b/sys/ufs/ffs/ffs_balloc.c
@@ -352,7 +352,7 @@ fail:
*/
(void) VOP_FSYNC(vp, cred, MNT_WAIT, td);
for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
- ffs_blkfree(ip, *blkp, fs->fs_bsize);
+ ffs_blkfree(fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number);
deallocated += fs->fs_bsize;
}
if (allocib != NULL) {
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index b70f7f7..cfcdcbd 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -59,14 +59,15 @@ int ffs_alloc __P((struct inode *,
int ffs_balloc __P((struct vnode *a_vp, off_t a_startoffset, int a_size,
struct ucred *a_cred, int a_flags, struct buf **a_bpp));
int ffs_blkatoff __P((struct vnode *, off_t, char **, struct buf **));
-void ffs_blkfree __P((struct inode *, ufs_daddr_t, long));
+void ffs_blkfree __P((struct fs *, struct vnode *, ufs_daddr_t, long,
+ ino_t));
ufs_daddr_t ffs_blkpref __P((struct inode *, ufs_daddr_t, int, ufs_daddr_t *));
void ffs_clrblock __P((struct fs *, u_char *, ufs_daddr_t));
void ffs_clusteracct __P((struct fs *, struct cg *, ufs_daddr_t, int));
int ffs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
int ffs_flushfiles __P((struct mount *, int, struct thread *));
void ffs_fragacct __P((struct fs *, int, int32_t [], int));
-int ffs_freefile __P((struct inode *, ino_t, int ));
+int ffs_freefile __P((struct fs *, struct vnode *, ino_t, int ));
int ffs_isblock __P((struct fs *, u_char *, ufs_daddr_t));
int ffs_isfreeblock __P((struct fs *, unsigned char *, ufs_daddr_t));
int ffs_mountfs __P((struct vnode *, struct mount *, struct thread *,
@@ -78,7 +79,8 @@ int ffs_reallocblks __P((struct vop_reallocblks_args *));
int ffs_realloccg __P((struct inode *,
ufs_daddr_t, ufs_daddr_t, int, int, struct ucred *, struct buf **));
void ffs_setblock __P((struct fs *, u_char *, ufs_daddr_t));
-int ffs_snapblkfree __P((struct inode *freeip, ufs_daddr_t bno, long size));
+int ffs_snapblkfree __P((struct fs *, struct vnode *, ufs_daddr_t,
+ long, ino_t));
void ffs_snapremove __P((struct vnode *vp));
int ffs_snapshot __P((struct mount *mp, char *snapfile));
void ffs_snapshot_mount __P((struct mount *mp));
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index 43dfec6..301cb49 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -336,7 +336,8 @@ ffs_truncate(vp, length, flags, cred, td)
blocksreleased += count;
if (lastiblock[level] < 0) {
oip->i_ib[level] = 0;
- ffs_blkfree(oip, bn, fs->fs_bsize);
+ ffs_blkfree(fs, oip->i_devvp, bn, fs->fs_bsize,
+ oip->i_number);
blocksreleased += nblocks;
}
}
@@ -355,7 +356,7 @@ ffs_truncate(vp, length, flags, cred, td)
continue;
oip->i_db[i] = 0;
bsize = blksize(fs, oip, i);
- ffs_blkfree(oip, bn, bsize);
+ ffs_blkfree(fs, oip->i_devvp, bn, bsize, oip->i_number);
blocksreleased += btodb(bsize);
}
if (lastblock < 0)
@@ -385,7 +386,8 @@ ffs_truncate(vp, length, flags, cred, td)
* required for the storage we're keeping.
*/
bn += numfrags(fs, newspace);
- ffs_blkfree(oip, bn, oldspace - newspace);
+ ffs_blkfree(fs, oip->i_devvp, bn, oldspace - newspace,
+ oip->i_number);
blocksreleased += btodb(oldspace - newspace);
}
}
@@ -514,7 +516,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
allerror = error;
blocksreleased += blkcount;
}
- ffs_blkfree(ip, nb, fs->fs_bsize);
+ ffs_blkfree(fs, ip->i_devvp, nb, fs->fs_bsize, ip->i_number);
blocksreleased += nblocks;
}
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 1d0a372..1140973 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -63,14 +63,16 @@
static int cgaccount __P((int, struct vnode *, struct buf *, int));
static int expunge __P((struct vnode *, struct inode *, struct fs *,
int (*) __P((struct vnode *, ufs_daddr_t *, ufs_daddr_t *, struct fs *,
- ufs_daddr_t))));
+ ufs_daddr_t, int)), int));
static int indiracct __P((struct vnode *, struct vnode *, int, ufs_daddr_t,
int, int, int, int, struct fs *, int (*) __P((struct vnode *,
- ufs_daddr_t *, ufs_daddr_t *, struct fs *, ufs_daddr_t))));
+ ufs_daddr_t *, ufs_daddr_t *, struct fs *, ufs_daddr_t, int)), int));
+static int fullacct __P((struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
+ struct fs *, ufs_daddr_t, int));
static int snapacct __P((struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
- struct fs *, ufs_daddr_t));
+ struct fs *, ufs_daddr_t, int));
static int mapacct __P((struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
- struct fs *, ufs_daddr_t));
+ struct fs *, ufs_daddr_t, int));
static int ffs_copyonwrite __P((struct vnode *, struct buf *));
static int readblock __P((struct buf *, daddr_t));
@@ -101,9 +103,9 @@ ffs_snapshot(mp, snapfile)
struct mount *mp;
char *snapfile;
{
- ufs_daddr_t blkno, inoblks[FSMAXSNAP];
+ ufs_daddr_t blkno;
int error, cg, snaploc, numblks;
- int i, size, len, loc, inoblkcnt;
+ int i, size, len, loc;
int flag = mp->mnt_flag;
struct timespec starttime = {0, 0}, endtime;
char saved_nice = 0;
@@ -118,7 +120,7 @@ ffs_snapshot(mp, snapfile)
struct nameidata nd;
struct mount *wrtmp;
struct vattr vat;
- struct vnode *vp;
+ struct vnode *vp, *xvp, *nvp;
/*
* Need to serialize access to snapshot code per filesystem.
@@ -211,28 +213,6 @@ restart:
bdwrite(ibp);
}
/*
- * Allocate shadow blocks to copy all of the other snapshot inodes
- * so that we will be able to expunge them from this snapshot. Also
- * include a copy of ourselves so that we do not deadlock trying
- * to copyonwrite ourselves when VOP_FSYNC'ing below.
- */
- fs->fs_snapinum[snaploc] = ip->i_number;
- for (loc = snaploc, inoblkcnt = 0; loc >= 0; loc--) {
- blkno = fragstoblks(fs, ino_to_fsba(fs, fs->fs_snapinum[loc]));
- fs->fs_snapinum[snaploc] = 0;
- for (i = 0; i < inoblkcnt; i++)
- if (inoblks[i] == blkno)
- break;
- if (i == inoblkcnt) {
- inoblks[inoblkcnt++] = blkno;
- error = UFS_BALLOC(vp, lblktosize(fs, (off_t)blkno),
- fs->fs_bsize, KERNCRED, 0, &nbp);
- if (error)
- goto out;
- bawrite(nbp);
- }
- }
- /*
* Allocate copies for the superblock and its summary information.
*/
error = UFS_BALLOC(vp, (off_t)(SBOFF), SBSIZE, KERNCRED, 0, &nbp);
@@ -272,8 +252,10 @@ restart:
for (cg = 0; cg < fs->fs_ncg; cg++) {
error = bread(vp, fragstoblks(fs, cgtod(fs, cg)), fs->fs_bsize,
KERNCRED, &nbp);
- if (error)
+ if (error) {
+ brelse(nbp);
goto out;
+ }
error = cgaccount(cg, vp, nbp, 1);
bawrite(nbp);
if (error)
@@ -308,43 +290,36 @@ restart:
break;
vn_start_write(NULL, &wrtmp, V_WAIT);
}
+ if (collectsnapstats)
+ nanotime(&starttime);
/*
* First, copy all the cylinder group maps that have changed.
*/
- if (collectsnapstats)
- nanotime(&starttime);
for (cg = 0; cg < fs->fs_ncg; cg++) {
if ((ACTIVECGNUM(fs, cg) & ACTIVECGOFF(cg)) != 0)
continue;
redo++;
error = bread(vp, fragstoblks(fs, cgtod(fs, cg)), fs->fs_bsize,
KERNCRED, &nbp);
- if (error)
+ if (error) {
+ brelse(nbp);
goto out1;
+ }
error = cgaccount(cg, vp, nbp, 2);
bawrite(nbp);
if (error)
goto out1;
}
/*
- * Copy the shadow blocks for the snapshot inodes so that
- * the copies can can be expunged.
- */
- for (loc = 0; loc < inoblkcnt; loc++) {
- error = bread(vp, inoblks[loc], fs->fs_bsize, KERNCRED, &nbp);
- if (error)
- goto out1;
- readblock(nbp, inoblks[loc]);
- nbp->b_flags |= B_VALIDSUSPWRT;
- bdwrite(nbp);
- }
- /*
* Grab a copy of the superblock and its summary information.
* We delay writing it until the suspension is released below.
*/
error = bread(vp, lblkno(fs, SBOFF), fs->fs_bsize, KERNCRED, &sbp);
- if (error)
+ if (error) {
+ brelse(sbp);
+ sbp = NULL;
goto out1;
+ }
copy_fs = (struct fs *)(sbp->b_data + blkoff(fs, SBOFF));
bcopy(fs, copy_fs, fs->fs_sbsize);
if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0)
@@ -366,7 +341,10 @@ restart:
if ((error = bread(ip->i_devvp,
fsbtodb(fs, fs->fs_csaddr + loc),
len, KERNCRED, &bp)) != 0) {
+ brelse(bp);
free(copy_fs->fs_csp, M_UFSMNT);
+ bawrite(sbp);
+ sbp = NULL;
goto out1;
}
bcopy(bp->b_data, space, (u_int)len);
@@ -380,6 +358,69 @@ restart:
*lp++ = fs->fs_contigsumsize;
}
/*
+ * We must check for active files that have been unlinked
+ * (e.g., with a zero link count). We have to expunge all
+ * trace of these files from the snapshot so that they are
+ * not reclaimed prematurely by fsck or unnecessarily dumped.
+ * We turn off the MNTK_SUSPENDED flag to avoid a panic from
+ * spec_strategy about writing on a suspended filesystem.
+ */
+ mp->mnt_kern_flag &= ~MNTK_SUSPENDED;
+ mtx_lock(&mntvnode_mtx);
+loop:
+ for (xvp = TAILQ_FIRST(&mp->mnt_nvnodelist); xvp; xvp = nvp) {
+ /*
+ * Make sure this vnode wasn't reclaimed in getnewvnode().
+ * Start over if it has (it won't be on the list anymore).
+ */
+ if (xvp->v_mount != mp)
+ goto loop;
+ nvp = TAILQ_NEXT(xvp, v_nmntvnodes);
+ mtx_unlock(&mntvnode_mtx);
+ mtx_lock(&xvp->v_interlock);
+ if (xvp->v_usecount == 0 || xvp->v_type == VNON ||
+ (VOP_GETATTR(xvp, &vat, td->td_proc->p_ucred, td) == 0 &&
+ vat.va_nlink > 0)) {
+ mtx_unlock(&xvp->v_interlock);
+ mtx_lock(&mntvnode_mtx);
+ continue;
+ }
+ if (snapdebug)
+ vprint("ffs_snapshot: busy vnode", xvp);
+ if (vn_lock(xvp, LK_EXCLUSIVE | LK_INTERLOCK, td) != 0)
+ goto loop;
+ xp = VTOI(xvp);
+ /*
+ * If there is a fragment, clear it here.
+ */
+ blkno = 0;
+ loc = howmany(xp->i_size, fs->fs_bsize) - 1;
+ if (loc < NDADDR) {
+ len = fragroundup(fs, blkoff(fs, xp->i_size));
+ if (len < fs->fs_bsize) {
+ ffs_blkfree(copy_fs, vp, xp->i_db[loc], len,
+ xp->i_number);
+ blkno = xp->i_db[loc];
+ xp->i_db[loc] = 0;
+ }
+ }
+ error = expunge(vp, xp, copy_fs, fullacct, BLK_NOCOPY);
+ if (blkno)
+ xp->i_db[loc] = blkno;
+ if (!error)
+ error = ffs_freefile(copy_fs, vp, xp->i_number,
+ xp->i_mode);
+ VOP_UNLOCK(xvp, 0, td);
+ if (error) {
+ free(copy_fs->fs_csp, M_UFSMNT);
+ bawrite(sbp);
+ sbp = NULL;
+ goto out1;
+ }
+ mtx_lock(&mntvnode_mtx);
+ }
+ mtx_unlock(&mntvnode_mtx);
+ /*
* Record snapshot inode. Since this is the newest snapshot,
* it must be placed at the end of the list.
*/
@@ -406,53 +447,50 @@ out1:
vp->v_mount->mnt_stat.f_mntonname, endtime.tv_sec,
endtime.tv_nsec / 1000000, redo, fs->fs_ncg);
}
- if (sbp != NULL) {
- /*
- * Copy allocation information from all the snapshots in
- * this snapshot and then expunge them from its view.
- */
- snaphead = &ip->i_devvp->v_rdev->si_snapshots;
- TAILQ_FOREACH(xp, snaphead, i_nextsnap) {
- if (xp == VTOI(vp))
- break;
- if ((error = expunge(vp, xp, fs, snapacct)) != 0)
- goto out1;
- }
- /*
- * Expunge the blocks used by the snapshots from the set of
- * blocks marked as used in the snapshot bitmaps.
- */
- if ((error = expunge(vp, VTOI(vp), copy_fs, mapacct)) != 0) {
- vref(vp);
- ffs_snapgone(VTOI(vp));
- free(copy_fs->fs_csp, M_UFSMNT);
- bawrite(sbp);
- goto out;
+ if (sbp == NULL)
+ goto out;
+ /*
+ * Copy allocation information from all the snapshots in
+ * this snapshot and then expunge them from its view.
+ */
+ snaphead = &ip->i_devvp->v_rdev->si_snapshots;
+ TAILQ_FOREACH(xp, snaphead, i_nextsnap) {
+ if (xp == ip)
+ break;
+ if ((error = expunge(vp, xp, fs, snapacct, BLK_SNAP)) != 0) {
+ fs->fs_snapinum[snaploc] = 0;
+ goto done;
}
- /*
- * Write the superblock and its summary information
- * to the snapshot.
- */
- blkno = fragstoblks(fs, fs->fs_csaddr);
- len = howmany(fs->fs_cssize, fs->fs_bsize);
- space = copy_fs->fs_csp;
- for (loc = 0; loc < len; loc++) {
- error = bread(vp, blkno + loc, fs->fs_bsize,
- KERNCRED, &nbp);
- if (error) {
- vref(vp);
- ffs_snapgone(VTOI(vp));
- free(copy_fs->fs_csp, M_UFSMNT);
- bawrite(sbp);
- goto out;
- }
- bcopy(space, nbp->b_data, fs->fs_bsize);
- space = (char *)space + fs->fs_bsize;
- bawrite(nbp);
+ }
+ /*
+ * Expunge the blocks used by the snapshots from the set of
+ * blocks marked as used in the snapshot bitmaps.
+ */
+ if ((error = expunge(vp, ip, copy_fs, mapacct, BLK_SNAP)) != 0) {
+ fs->fs_snapinum[snaploc] = 0;
+ goto done;
+ }
+ /*
+ * Write the superblock and its summary information
+ * to the snapshot.
+ */
+ blkno = fragstoblks(fs, fs->fs_csaddr);
+ len = howmany(fs->fs_cssize, fs->fs_bsize);
+ space = copy_fs->fs_csp;
+ for (loc = 0; loc < len; loc++) {
+ error = bread(vp, blkno + loc, fs->fs_bsize, KERNCRED, &nbp);
+ if (error) {
+ brelse(nbp);
+ fs->fs_snapinum[snaploc] = 0;
+ goto done;
}
- free(copy_fs->fs_csp, M_UFSMNT);
- bawrite(sbp);
+ bcopy(space, nbp->b_data, fs->fs_bsize);
+ space = (char *)space + fs->fs_bsize;
+ bawrite(nbp);
}
+done:
+ free(copy_fs->fs_csp, M_UFSMNT);
+ bawrite(sbp);
out:
if (fs->fs_active != 0) {
FREE(fs->fs_active, M_DEVBUF);
@@ -572,28 +610,31 @@ cgaccount(cg, vp, nbp, passno)
* if the other snapshot holding them is freed.
*/
static int
-expunge(vp, xp, fs, acctfunc)
- struct vnode *vp;
- struct inode *xp;
+expunge(snapvp, cancelip, fs, acctfunc, expungetype)
+ struct vnode *snapvp;
+ struct inode *cancelip;
struct fs *fs;
int (*acctfunc) __P((struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
- struct fs *, ufs_daddr_t));
+ struct fs *, ufs_daddr_t, int));
+ int expungetype;
{
int i, len, error, numblks, blksperindir;
- ufs_daddr_t lbn, rlbn, blkno;
+ ufs_daddr_t lbn, rlbn, blkno, indiroff;
+ struct thread *td = curthread;
struct dinode *dip;
struct buf *bp;
- if ((error = (*acctfunc)(vp, &xp->i_db[0], &xp->i_ib[NIADDR], fs, 0)))
+ numblks = howmany(cancelip->i_size, fs->fs_bsize);
+ if ((error = (*acctfunc)(snapvp, &cancelip->i_db[0],
+ &cancelip->i_ib[NIADDR], fs, 0, expungetype)))
return (error);
- numblks = howmany(fs->fs_size, fs->fs_frag);
blksperindir = 1;
lbn = -NDADDR;
len = numblks - NDADDR;
rlbn = NDADDR;
for (i = 0; len > 0 && i < NIADDR; i++) {
- error = indiracct(vp, ITOV(xp), i, xp->i_ib[i], lbn,
- rlbn, len, blksperindir, fs, acctfunc);
+ error = indiracct(snapvp, ITOV(cancelip), i, cancelip->i_ib[i],
+ lbn, rlbn, len, blksperindir, fs, acctfunc, expungetype);
if (error)
return (error);
blksperindir *= NINDIR(fs);
@@ -602,13 +643,37 @@ expunge(vp, xp, fs, acctfunc)
rlbn += blksperindir;
}
/*
- * Set copied snapshot inode to be a zero length file.
+ * Prepare to expunge the inode. If its inode block has not
+ * yet been copied, then allocate and fill the copy.
*/
- blkno = fragstoblks(fs, ino_to_fsba(fs, xp->i_number));
- if ((error = bread(vp, blkno, fs->fs_bsize, KERNCRED, &bp)) != 0)
+ lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number));
+ blkno = 0;
+ if (lbn < NDADDR) {
+ blkno = cancelip->i_db[lbn];
+ } else {
+ td->td_proc->p_flag |= P_COWINPROGRESS;
+ error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
+ fs->fs_bsize, KERNCRED, B_METAONLY, &bp);
+ td->td_proc->p_flag &= ~P_COWINPROGRESS;
+ if (error)
+ return (error);
+ indiroff = (lbn - NDADDR) % NINDIR(fs);
+ blkno = ((ufs_daddr_t *)(bp->b_data))[indiroff];
+ bqrelse(bp);
+ }
+ error = UFS_BALLOC(snapvp, lblktosize(fs, (off_t)lbn),
+ fs->fs_bsize, KERNCRED, 0, &bp);
+ if (error)
return (error);
- dip = (struct dinode *)bp->b_data +
- ino_to_fsbo(fs, xp->i_number);
+ if (blkno == 0 && (error = readblock(bp, lbn)))
+ return (error);
+ /*
+ * Set a snapshot inode to be a zero length file, regular files
+ * to be completely unallocated.
+ */
+ dip = (struct dinode *)bp->b_data + ino_to_fsbo(fs, cancelip->i_number);
+ if (expungetype == BLK_NOCOPY)
+ dip->di_mode = 0;
dip->di_size = 0;
dip->di_blocks = 0;
dip->di_flags &= ~SF_SNAPSHOT;
@@ -623,7 +688,7 @@ expunge(vp, xp, fs, acctfunc)
*/
static int
indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
- acctfunc)
+ acctfunc, expungetype)
struct vnode *snapvp;
struct vnode *cancelvp;
int level;
@@ -634,7 +699,8 @@ indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
int blksperindir;
struct fs *fs;
int (*acctfunc) __P((struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
- struct fs *, ufs_daddr_t));
+ struct fs *, ufs_daddr_t, int));
+ int expungetype;
{
int subblksperindir, error, last, num, i;
struct indir indirs[NIADDR + 2];
@@ -665,7 +731,7 @@ indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
MALLOC(bap, ufs_daddr_t *, fs->fs_bsize, M_DEVBUF, M_WAITOK);
bcopy(bp->b_data, (caddr_t)bap, fs->fs_bsize);
bqrelse(bp);
- error = (*acctfunc)(snapvp, &bap[0], &bap[last], fs, rlbn);
+ error = (*acctfunc)(snapvp, &bap[0], &bap[last], fs, rlbn, expungetype);
if (error || level == 0)
goto out;
/*
@@ -675,7 +741,7 @@ indiracct(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks, blksperindir, fs,
subblksperindir = blksperindir / NINDIR(fs);
for (lbn++, level--, i = 0; i < last; i++) {
error = indiracct(snapvp, cancelvp, level, bap[i], lbn,
- rlbn, remblks, subblksperindir, fs, acctfunc);
+ rlbn, remblks, subblksperindir, fs, acctfunc, expungetype);
if (error)
goto out;
rlbn += blksperindir;
@@ -688,14 +754,33 @@ out:
}
/*
+ * Do both snap accounting and map accounting.
+ */
+static int
+fullacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
+ struct vnode *vp;
+ ufs_daddr_t *oldblkp, *lastblkp;
+ struct fs *fs;
+ ufs_daddr_t lblkno;
+ int expungetype; /* BLK_SNAP or BLK_NOCOPY */
+{
+ int error;
+
+ if ((error = snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)))
+ return (error);
+ return (mapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype));
+}
+
+/*
* Identify a set of blocks allocated in a snapshot inode.
*/
static int
-snapacct(vp, oldblkp, lastblkp, fs, lblkno)
+snapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
struct vnode *vp;
ufs_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
ufs_daddr_t lblkno;
+ int expungetype; /* BLK_SNAP or BLK_NOCOPY */
{
struct inode *ip = VTOI(vp);
ufs_daddr_t lbn, blkno, *blkp;
@@ -719,17 +804,18 @@ snapacct(vp, oldblkp, lastblkp, fs, lblkno)
[(lbn - NDADDR) % NINDIR(fs)];
}
/*
- * If we find a block marked BLK_NOCOPY, then it is
+ * If we are expunging a snapshot vnode and we
+ * find a block marked BLK_NOCOPY, then it is
* one that has been allocated to this snapshot after
* we took our current snapshot and can be ignored.
*/
- if (*blkp == BLK_NOCOPY) {
+ if (expungetype == BLK_SNAP && *blkp == BLK_NOCOPY) {
if (lbn >= NDADDR)
brelse(ibp);
} else {
if (*blkp != 0)
panic("snapacct: bad block");
- *blkp = BLK_SNAP;
+ *blkp = expungetype;
if (lbn >= NDADDR)
bdwrite(ibp);
}
@@ -741,59 +827,24 @@ snapacct(vp, oldblkp, lastblkp, fs, lblkno)
* Account for a set of blocks allocated in a snapshot inode.
*/
static int
-mapacct(vp, oldblkp, lastblkp, fs, lblkno)
+mapacct(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
struct vnode *vp;
ufs_daddr_t *oldblkp, *lastblkp;
struct fs *fs;
ufs_daddr_t lblkno;
+ int expungetype;
{
- struct inode *ip = VTOI(vp);
- ufs_daddr_t blkno, cgblkno, fragno;
- struct buf *bp;
- struct cg *cgp;
- char *blksfree;
- int i, cg, error;
+ ufs_daddr_t blkno;
+ ino_t inum;
+ inum = VTOI(vp)->i_number;
for ( ; oldblkp < lastblkp; oldblkp++, lblkno++) {
blkno = *oldblkp;
if (blkno == 0 || blkno == BLK_NOCOPY)
continue;
if (blkno == BLK_SNAP)
blkno = blkstofrags(fs, lblkno);
- cg = dtog(fs, blkno);
- cgblkno = fragstoblks(fs, cgtod(fs, cg));
- if ((error = bread(vp, cgblkno, fs->fs_bsize, KERNCRED, &bp)))
- return (error);
- cgp = (struct cg *)bp->b_data;
- if (!cg_chkmagic(cgp) || cgp->cg_cgx != cg) {
- if (!cg_chkmagic(cgp))
- printf("mapacct: bad magic 0x%x\n",
- cgp->cg_magic);
- else
- printf("%s: mismatched cg %d != cg_cgx %d\n",
- "mapacct", cg, cgp->cg_cgx);
- brelse(bp);
- return (EIO);
- }
- cgp->cg_time = time_second;
- cgblkno = dtogd(fs, blkno);
- blksfree = cg_blksfree(cgp);
- fragno = fragstoblks(fs, cgblkno);
- if (!ffs_isfreeblock(fs, blksfree, fragno)) {
- printf("dev = %s, block = %ld, fs = %s\n",
- devtoname(ip->i_dev), (long)blkno, fs->fs_fsmnt);
- panic("mapacct: freeing free block");
- }
- ffs_setblock(fs, blksfree, fragno);
- ffs_clusteracct(fs, cgp, fragno, 1);
- cgp->cg_cs.cs_nbfree++;
- fs->fs_cstotal.cs_nbfree++;
- fs->fs_cs(fs, cg).cs_nbfree++;
- i = cbtocylno(fs, cgblkno);
- cg_blks(fs, cgp, i)[cbtorpos(fs, cgblkno)]++;
- cg_blktot(cgp)[i]++;
- fs->fs_fmod = 1;
- bdwrite(bp);
+ ffs_blkfree(fs, vp, blkno, fs->fs_bsize, inum);
}
return (0);
}
@@ -879,7 +930,8 @@ ffs_snapremove(vp)
if (dblk == BLK_NOCOPY || dblk == BLK_SNAP)
ip->i_db[blkno] = 0;
else if ((dblk == blkstofrags(fs, blkno) &&
- ffs_snapblkfree(ip, dblk, fs->fs_bsize))) {
+ ffs_snapblkfree(fs, ip->i_devvp, dblk, fs->fs_bsize,
+ ip->i_number))) {
ip->i_blocks -= btodb(fs->fs_bsize);
ip->i_db[blkno] = 0;
}
@@ -897,7 +949,8 @@ ffs_snapremove(vp)
if (dblk == BLK_NOCOPY || dblk == BLK_SNAP)
((ufs_daddr_t *)(ibp->b_data))[loc] = 0;
else if ((dblk == blkstofrags(fs, blkno) &&
- ffs_snapblkfree(ip, dblk, fs->fs_bsize))) {
+ ffs_snapblkfree(fs, ip->i_devvp, dblk,
+ fs->fs_bsize, ip->i_number))) {
ip->i_blocks -= btodb(fs->fs_bsize);
((ufs_daddr_t *)(ibp->b_data))[loc] = 0;
}
@@ -930,13 +983,14 @@ ffs_snapremove(vp)
* must always have been allocated from a BLK_NOCOPY location.
*/
int
-ffs_snapblkfree(freeip, bno, size)
- struct inode *freeip;
+ffs_snapblkfree(fs, devvp, bno, size, inum)
+ struct fs *fs;
+ struct vnode *devvp;
ufs_daddr_t bno;
long size;
+ ino_t inum;
{
struct buf *ibp, *cbp, *savedcbp = 0;
- struct fs *fs = freeip->i_fs;
struct thread *td = curthread;
struct inode *ip;
struct vnode *vp;
@@ -945,7 +999,7 @@ ffs_snapblkfree(freeip, bno, size)
struct snaphead *snaphead;
lbn = fragstoblks(fs, bno);
- snaphead = &freeip->i_devvp->v_rdev->si_snapshots;
+ snaphead = &devvp->v_rdev->si_snapshots;
TAILQ_FOREACH(ip, snaphead, i_nextsnap) {
vp = ITOV(ip);
/*
@@ -1016,7 +1070,7 @@ ffs_snapblkfree(freeip, bno, size)
if (snapdebug)
printf("%s %d lbn %d from inum %d\n",
"Grabonremove: snapino", ip->i_number, lbn,
- freeip->i_number);
+ inum);
#endif
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (lbn < NDADDR) {
@@ -1050,7 +1104,7 @@ ffs_snapblkfree(freeip, bno, size)
if (snapdebug)
printf("%s%d lbn %d for inum %d size %ld to blkno %d\n",
"Copyonremove: snapino ", ip->i_number, lbn,
- freeip->i_number, size, cbp->b_blkno);
+ inum, size, cbp->b_blkno);
#endif
/*
* If we have already read the old block contents, then
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 913d5a1..a7c12d4 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -169,7 +169,7 @@ static struct dirrem *newdirrem __P((struct buf *, struct inode *,
static void free_diradd __P((struct diradd *));
static void free_allocindir __P((struct allocindir *, struct inodedep *));
static void free_newdirblk __P((struct newdirblk *));
-static int indir_trunc __P((struct inode *, ufs_daddr_t, int, ufs_lbn_t,
+static int indir_trunc __P((struct freeblks *, ufs_daddr_t, int, ufs_lbn_t,
long *));
static void deallocate_dependencies __P((struct buf *, struct inodedep *));
static void free_allocdirect __P((struct allocdirectlst *,
@@ -1506,7 +1506,7 @@ newfreefrag(ip, blkno, size)
MALLOC(freefrag, struct freefrag *, sizeof(struct freefrag),
M_FREEFRAG, M_SOFTDEP_FLAGS);
freefrag->ff_list.wk_type = D_FREEFRAG;
- freefrag->ff_state = ip->i_uid & ~ONWORKLIST; /* XXX - used below */
+ freefrag->ff_state = 0;
freefrag->ff_inum = ip->i_number;
freefrag->ff_mnt = ITOV(ip)->v_mount;
freefrag->ff_devvp = ip->i_devvp;
@@ -1523,15 +1523,9 @@ static void
handle_workitem_freefrag(freefrag)
struct freefrag *freefrag;
{
- struct inode tip;
-
- tip.i_vnode = NULL;
- tip.i_fs = VFSTOUFS(freefrag->ff_mnt)->um_fs;
- tip.i_devvp = freefrag->ff_devvp;
- tip.i_dev = freefrag->ff_devvp->v_rdev;
- tip.i_number = freefrag->ff_inum;
- tip.i_uid = freefrag->ff_state & ~ONWORKLIST; /* XXX - set above */
- ffs_blkfree(&tip, freefrag->ff_blkno, freefrag->ff_fragsize);
+
+ ffs_blkfree(VFSTOUFS(freefrag->ff_mnt)->um_fs, freefrag->ff_devvp,
+ freefrag->ff_blkno, freefrag->ff_fragsize, freefrag->ff_inum);
FREE(freefrag, M_FREEFRAG);
}
@@ -1819,8 +1813,10 @@ softdep_setup_freeblocks(ip, length)
*/
if ((error = bread(ip->i_devvp,
fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
- (int)fs->fs_bsize, NOCRED, &bp)) != 0)
+ (int)fs->fs_bsize, NOCRED, &bp)) != 0) {
+ brelse(bp);
softdep_error("softdep_setup_freeblocks", error);
+ }
*((struct dinode *)bp->b_data + ino_to_fsbo(fs, ip->i_number)) =
ip->i_din;
/*
@@ -2224,7 +2220,7 @@ handle_workitem_freeblocks(freeblks, flags)
struct freeblks *freeblks;
int flags;
{
- struct inode tip, *ip;
+ struct inode *ip;
struct vnode *vp;
ufs_daddr_t bn;
struct fs *fs;
@@ -2233,13 +2229,7 @@ handle_workitem_freeblocks(freeblks, flags)
int error, allerror = 0;
ufs_lbn_t baselbns[NIADDR], tmpval;
- tip.i_fs = fs = VFSTOUFS(freeblks->fb_mnt)->um_fs;
- tip.i_number = freeblks->fb_previousinum;
- tip.i_devvp = freeblks->fb_devvp;
- tip.i_dev = freeblks->fb_devvp->v_rdev;
- tip.i_size = freeblks->fb_oldsize;
- tip.i_uid = freeblks->fb_uid;
- tip.i_vnode = NULL;
+ fs = VFSTOUFS(freeblks->fb_mnt)->um_fs;
tmpval = 1;
baselbns[0] = NDADDR;
for (i = 1; i < NIADDR; i++) {
@@ -2254,10 +2244,11 @@ handle_workitem_freeblocks(freeblks, flags)
for (level = (NIADDR - 1); level >= 0; level--) {
if ((bn = freeblks->fb_iblks[level]) == 0)
continue;
- if ((error = indir_trunc(&tip, fsbtodb(fs, bn), level,
+ if ((error = indir_trunc(freeblks, fsbtodb(fs, bn), level,
baselbns[level], &blocksreleased)) == 0)
allerror = error;
- ffs_blkfree(&tip, bn, fs->fs_bsize);
+ ffs_blkfree(fs, freeblks->fb_devvp, bn, fs->fs_bsize,
+ freeblks->fb_previousinum);
fs->fs_pendingblocks -= nblocks;
blocksreleased += nblocks;
}
@@ -2267,8 +2258,9 @@ handle_workitem_freeblocks(freeblks, flags)
for (i = (NDADDR - 1); i >= 0; i--) {
if ((bn = freeblks->fb_dblks[i]) == 0)
continue;
- bsize = blksize(fs, &tip, i);
- ffs_blkfree(&tip, bn, bsize);
+ bsize = sblksize(fs, freeblks->fb_oldsize, i);
+ ffs_blkfree(fs, freeblks->fb_devvp, bn, bsize,
+ freeblks->fb_previousinum);
fs->fs_pendingblocks -= btodb(bsize);
blocksreleased += btodb(bsize);
}
@@ -2303,8 +2295,8 @@ handle_workitem_freeblocks(freeblks, flags)
* blocks.
*/
static int
-indir_trunc(ip, dbn, level, lbn, countp)
- struct inode *ip;
+indir_trunc(freeblks, dbn, level, lbn, countp)
+ struct freeblks *freeblks;
ufs_daddr_t dbn;
int level;
ufs_lbn_t lbn;
@@ -2319,7 +2311,7 @@ indir_trunc(ip, dbn, level, lbn, countp)
int i, lbnadd, nblocks;
int error, allerror = 0;
- fs = ip->i_fs;
+ fs = VFSTOUFS(freeblks->fb_mnt)->um_fs;
lbnadd = 1;
for (i = level; i > 0; i--)
lbnadd *= NINDIR(fs);
@@ -2336,7 +2328,7 @@ indir_trunc(ip, dbn, level, lbn, countp)
* Otherwise we have to read the blocks in from the disk.
*/
ACQUIRE_LOCK(&lk);
- if ((bp = incore(ip->i_devvp, dbn)) != NULL &&
+ if ((bp = incore(freeblks->fb_devvp, dbn)) != NULL &&
(wk = LIST_FIRST(&bp->b_dep)) != NULL) {
if (wk->wk_type != D_INDIRDEP ||
(indirdep = WK_INDIRDEP(wk))->ir_savebp != bp ||
@@ -2353,9 +2345,12 @@ indir_trunc(ip, dbn, level, lbn, countp)
FREE_LOCK(&lk);
} else {
FREE_LOCK(&lk);
- error = bread(ip->i_devvp, dbn, (int)fs->fs_bsize, NOCRED, &bp);
- if (error)
+ error = bread(freeblks->fb_devvp, dbn, (int)fs->fs_bsize,
+ NOCRED, &bp);
+ if (error) {
+ brelse(bp);
return (error);
+ }
}
/*
* Recursively free indirect blocks.
@@ -2366,11 +2361,12 @@ indir_trunc(ip, dbn, level, lbn, countp)
if ((nb = bap[i]) == 0)
continue;
if (level != 0) {
- if ((error = indir_trunc(ip, fsbtodb(fs, nb),
+ if ((error = indir_trunc(freeblks, fsbtodb(fs, nb),
level - 1, lbn + (i * lbnadd), countp)) != 0)
allerror = error;
}
- ffs_blkfree(ip, nb, fs->fs_bsize);
+ ffs_blkfree(fs, freeblks->fb_devvp, nb, fs->fs_bsize,
+ freeblks->fb_previousinum);
fs->fs_pendingblocks -= nblocks;
*countp += nblocks;
}
@@ -3132,7 +3128,6 @@ handle_workitem_freefile(freefile)
struct freefile *freefile;
{
struct fs *fs;
- struct inode tip;
struct inodedep *idp;
int error;
@@ -3144,11 +3139,9 @@ handle_workitem_freefile(freefile)
if (error)
panic("handle_workitem_freefile: inodedep survived");
#endif
- tip.i_devvp = freefile->fx_devvp;
- tip.i_dev = freefile->fx_devvp->v_rdev;
- tip.i_fs = fs;
fs->fs_pendinginodes -= 1;
- if ((error = ffs_freefile(&tip, freefile->fx_oldinum, freefile->fx_mode)) != 0)
+ if ((error = ffs_freefile(fs, freefile->fx_devvp, freefile->fx_oldinum,
+ freefile->fx_mode)) != 0)
softdep_error("handle_workitem_freefile", error);
WORKITEM_FREE(freefile, D_FREEFILE);
}
@@ -4261,6 +4254,8 @@ softdep_fsync(vp)
&bp);
if (error == 0)
error = BUF_WRITE(bp);
+ else
+ brelse(bp);
vput(pvp);
if (error != 0)
return (error);
@@ -4785,8 +4780,10 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
FREE_LOCK(&lk);
if ((error = bread(ump->um_devvp,
fsbtodb(ump->um_fs, ino_to_fsba(ump->um_fs, inum)),
- (int)ump->um_fs->fs_bsize, NOCRED, &bp)) != 0)
+ (int)ump->um_fs->fs_bsize, NOCRED, &bp)) != 0) {
+ brelse(bp);
break;
+ }
if ((error = BUF_WRITE(bp)) != 0)
break;
ACQUIRE_LOCK(&lk);
OpenPOWER on IntegriCloud