summaryrefslogtreecommitdiffstats
path: root/sys
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 /sys
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.
Diffstat (limited to 'sys')
-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