version 1.17.2.6, 2007/12/07 17:35:19 |
version 1.17.2.7, 2008/01/21 09:48:07 |
Line 78 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 78 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#define ufs2_daddr_t int64_t |
#define ufs2_daddr_t int64_t |
#define ufs_lbn_t daddr_t |
#define ufs_lbn_t daddr_t |
#define VI_MTX(v) (&(v)->v_interlock) |
#define VI_MTX(v) (&(v)->v_interlock) |
#define VI_LOCK(v) simple_lock(&(v)->v_interlock) |
#define VI_LOCK(v) mutex_enter(&(v)->v_interlock) |
#define VI_UNLOCK(v) simple_unlock(&(v)->v_interlock) |
#define VI_UNLOCK(v) mutex_exit(&(v)->v_interlock) |
#define MNT_ILOCK(v) simple_lock(&mntvnode_slock) |
#define MNT_ILOCK(v) mutex_enter(&mntvnode_lock) |
#define MNT_IUNLOCK(v) simple_unlock(&mntvnode_slock) |
#define MNT_IUNLOCK(v) mutex_exit(&mntvnode_lock) |
|
|
#if !defined(FFS_NO_SNAPSHOT) |
#if !defined(FFS_NO_SNAPSHOT) |
static int cgaccount(int, struct vnode *, void *, int); |
static int cgaccount(int, struct vnode *, void *, int); |
Line 204 ffs_snapshot(struct mount *mp, struct vn |
|
Line 204 ffs_snapshot(struct mount *mp, struct vn |
|
#else /* defined(FFS_NO_SNAPSHOT) */ |
#else /* defined(FFS_NO_SNAPSHOT) */ |
ufs2_daddr_t numblks, blkno, *blkp, snaplistsize = 0, *snapblklist; |
ufs2_daddr_t numblks, blkno, *blkp, snaplistsize = 0, *snapblklist; |
int error, ns, cg, snaploc; |
int error, ns, cg, snaploc; |
int i, s, size, len, loc; |
int i, size, len, loc; |
int flag = mp->mnt_flag; |
int flag = mp->mnt_flag; |
struct timeval starttime; |
struct timeval starttime; |
#ifdef DEBUG |
#ifdef DEBUG |
Line 220 ffs_snapshot(struct mount *mp, struct vn |
|
Line 220 ffs_snapshot(struct mount *mp, struct vn |
|
struct inode *ip, *xp; |
struct inode *ip, *xp; |
struct buf *bp, *ibp, *nbp; |
struct buf *bp, *ibp, *nbp; |
struct vattr vat; |
struct vattr vat; |
struct vnode *xvp, *nvp, *devvp; |
struct vnode *xvp, *mvp, *devvp; |
struct snap_info *si; |
struct snap_info *si; |
|
|
ns = UFS_FSNEEDSWAP(fs); |
ns = UFS_FSNEEDSWAP(fs); |
Line 252 ffs_snapshot(struct mount *mp, struct vn |
|
Line 252 ffs_snapshot(struct mount *mp, struct vn |
|
return EACCES; |
return EACCES; |
|
|
if (vp->v_size != 0) { |
if (vp->v_size != 0) { |
error = ffs_truncate(vp, 0, 0, NOCRED, l); |
error = ffs_truncate(vp, 0, 0, NOCRED); |
if (error) |
if (error) |
return error; |
return error; |
} |
} |
Line 426 ffs_snapshot(struct mount *mp, struct vn |
|
Line 426 ffs_snapshot(struct mount *mp, struct vn |
|
*/ |
*/ |
snaplistsize = fs->fs_ncg + howmany(fs->fs_cssize, fs->fs_bsize) + |
snaplistsize = fs->fs_ncg + howmany(fs->fs_cssize, fs->fs_bsize) + |
FSMAXSNAP + 1 /* superblock */ + 1 /* last block */ + 1 /* size */; |
FSMAXSNAP + 1 /* superblock */ + 1 /* last block */ + 1 /* size */; |
|
/* Allocate a marker vnode */ |
|
if ((mvp = vnalloc(mp)) == NULL) { |
|
error = ENOMEM; |
|
goto out1; |
|
} |
MNT_ILOCK(mp); |
MNT_ILOCK(mp); |
loop: |
|
/* |
/* |
* NOTE: not using the TAILQ_FOREACH here since in this loop vgone() |
* NOTE: not using the TAILQ_FOREACH here since in this loop vgone() |
* and vclean() can be called indirectly |
* and vclean() can be called indirectly |
*/ |
*/ |
for (xvp = TAILQ_FIRST(&mp->mnt_vnodelist); xvp; xvp = nvp) { |
for (xvp = TAILQ_FIRST(&mp->mnt_vnodelist); xvp; xvp = vunmark(mvp)) { |
|
vmark(mvp, vp); |
/* |
/* |
* Make sure this vnode wasn't reclaimed in getnewvnode(). |
* Make sure this vnode wasn't reclaimed in getnewvnode(). |
* Start over if it has (it won't be on the list anymore). |
* Start over if it has (it won't be on the list anymore). |
*/ |
*/ |
if (xvp->v_mount != mp) |
if (xvp->v_mount != mp || vismarker(xvp)) |
goto loop; |
continue; |
VI_LOCK(xvp); |
VI_LOCK(xvp); |
nvp = TAILQ_NEXT(xvp, v_mntvnodes); |
|
MNT_IUNLOCK(mp); |
|
if ((xvp->v_iflag & VI_XLOCK) || |
if ((xvp->v_iflag & VI_XLOCK) || |
xvp->v_usecount == 0 || xvp->v_type == VNON || |
xvp->v_usecount == 0 || xvp->v_type == VNON || |
(VTOI(xvp)->i_flags & SF_SNAPSHOT)) { |
(VTOI(xvp)->i_flags & SF_SNAPSHOT)) { |
VI_UNLOCK(xvp); |
VI_UNLOCK(xvp); |
MNT_ILOCK(mp); |
|
continue; |
continue; |
} |
} |
|
MNT_IUNLOCK(mp); |
|
/* |
|
* XXXAD should increase vnode ref count to prevent it |
|
* disappearing or being recycled. |
|
*/ |
VI_UNLOCK(xvp); |
VI_UNLOCK(xvp); |
#ifdef DEBUG |
#ifdef DEBUG |
if (snapdebug) |
if (snapdebug) |
|
|
xp->i_mode); |
xp->i_mode); |
if (error) { |
if (error) { |
free(copy_fs->fs_csp, M_UFSMNT); |
free(copy_fs->fs_csp, M_UFSMNT); |
|
(void)vunmark(mvp); |
goto out1; |
goto out1; |
} |
} |
MNT_ILOCK(mp); |
MNT_ILOCK(mp); |
} |
} |
MNT_IUNLOCK(mp); |
MNT_IUNLOCK(mp); |
|
vnfree(mvp); |
/* |
/* |
* If there already exist snapshots on this filesystem, grab a |
* If there already exist snapshots on this filesystem, grab a |
* reference to their shared lock. If this is the first snapshot |
* reference to their shared lock. If this is the first snapshot |
|
|
* Clean all dirty buffers now to avoid UBC inconsistencies. |
* Clean all dirty buffers now to avoid UBC inconsistencies. |
*/ |
*/ |
if (!error) { |
if (!error) { |
simple_lock(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
error = VOP_PUTPAGES(vp, 0, 0, |
error = VOP_PUTPAGES(vp, 0, 0, |
PGO_ALLPAGES|PGO_CLEANIT|PGO_SYNCIO|PGO_FREE); |
PGO_ALLPAGES|PGO_CLEANIT|PGO_SYNCIO|PGO_FREE); |
} |
} |
if (!error) { |
if (!error) { |
s = splbio(); |
mutex_enter(&bufcache_lock); |
for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { |
for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { |
nbp = LIST_NEXT(bp, b_vnbufs); |
nbp = LIST_NEXT(bp, b_vnbufs); |
simple_lock(&bp->b_interlock); |
bp->b_cflags |= BC_BUSY|BC_VFLUSH; |
splx(s); |
|
if ((bp->b_flags & (B_DELWRI|B_BUSY)) != B_DELWRI) |
|
panic("ffs_snapshot: not dirty or busy, bp %p", |
|
bp); |
|
bp->b_flags |= B_BUSY|B_VFLUSH; |
|
if (LIST_FIRST(&bp->b_dep) == NULL) |
if (LIST_FIRST(&bp->b_dep) == NULL) |
bp->b_flags |= B_NOCACHE; |
bp->b_cflags |= BC_NOCACHE; |
simple_unlock(&bp->b_interlock); |
mutex_exit(&bufcache_lock); |
bwrite(bp); |
bwrite(bp); |
s = splbio(); |
mutex_enter(&bufcache_lock); |
} |
} |
simple_lock(&global_v_numoutput_slock); |
mutex_exit(&bufcache_lock); |
while (vp->v_numoutput) { |
|
vp->v_iflag |= VI_BWAIT; |
mutex_enter(&vp->v_interlock); |
ltsleep((void *)&vp->v_numoutput, PRIBIO+1, |
while (vp->v_numoutput > 0) |
"snapflushbuf", 0, &global_v_numoutput_slock); |
cv_wait(&vp->v_cv, &vp->v_interlock); |
} |
mutex_exit(&vp->v_interlock); |
simple_unlock(&global_v_numoutput_slock); |
|
splx(s); |
|
} |
} |
if (sbbuf) |
if (sbbuf) |
free(sbbuf, M_UFSMNT); |
free(sbbuf, M_UFSMNT); |
|
|
} |
} |
mp->mnt_flag = flag; |
mp->mnt_flag = flag; |
if (error) |
if (error) |
(void) ffs_truncate(vp, (off_t)0, 0, NOCRED, l); |
(void) ffs_truncate(vp, (off_t)0, 0, NOCRED); |
else |
else |
vref(vp); |
vref(vp); |
return (error); |
return (error); |
Line 958 indiracct_ufs1(struct vnode *snapvp, str |
|
Line 960 indiracct_ufs1(struct vnode *snapvp, str |
|
*/ |
*/ |
bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0); |
bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0); |
bp->b_blkno = fsbtodb(fs, blkno); |
bp->b_blkno = fsbtodb(fs, blkno); |
if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0 && |
if ((bp->b_oflags & (BO_DONE | BO_DELWRI)) == 0 && |
(error = readfsblk(bp->b_vp, bp->b_data, fragstoblks(fs, blkno)))) { |
(error = readfsblk(bp->b_vp, bp->b_data, fragstoblks(fs, blkno)))) { |
brelse(bp, 0); |
brelse(bp, 0); |
return (error); |
return (error); |
Line 1226 indiracct_ufs2(struct vnode *snapvp, str |
|
Line 1228 indiracct_ufs2(struct vnode *snapvp, str |
|
*/ |
*/ |
bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0); |
bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0); |
bp->b_blkno = fsbtodb(fs, blkno); |
bp->b_blkno = fsbtodb(fs, blkno); |
if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0 && |
if ((bp->b_oflags & (BO_DONE | BO_DELWRI)) == 0 && |
(error = readfsblk(bp->b_vp, bp->b_data, fragstoblks(fs, blkno)))) { |
(error = readfsblk(bp->b_vp, bp->b_data, fragstoblks(fs, blkno)))) { |
brelse(bp, 0); |
brelse(bp, 0); |
return (error); |
return (error); |
Line 2063 readfsblk(struct vnode *vp, void *data, |
|
Line 2065 readfsblk(struct vnode *vp, void *data, |
|
struct fs *fs = ip->i_fs; |
struct fs *fs = ip->i_fs; |
struct buf *nbp; |
struct buf *nbp; |
|
|
nbp = getiobuf(); |
nbp = getiobuf(NULL, true); |
nbp->b_flags = B_READ; |
nbp->b_flags = B_READ; |
nbp->b_bcount = nbp->b_bufsize = fs->fs_bsize; |
nbp->b_bcount = nbp->b_bufsize = fs->fs_bsize; |
nbp->b_error = 0; |
nbp->b_error = 0; |
Line 2071 readfsblk(struct vnode *vp, void *data, |
|
Line 2073 readfsblk(struct vnode *vp, void *data, |
|
nbp->b_blkno = nbp->b_rawblkno = fsbtodb(fs, blkstofrags(fs, lbn)); |
nbp->b_blkno = nbp->b_rawblkno = fsbtodb(fs, blkstofrags(fs, lbn)); |
nbp->b_proc = NULL; |
nbp->b_proc = NULL; |
nbp->b_dev = ip->i_devvp->v_rdev; |
nbp->b_dev = ip->i_devvp->v_rdev; |
nbp->b_vp = NULLVP; |
|
|
|
bdev_strategy(nbp); |
bdev_strategy(nbp); |
|
|
Line 2101 readvnblk(struct vnode *vp, void *data, |
|
Line 2102 readvnblk(struct vnode *vp, void *data, |
|
|
|
if (bn != (daddr_t)-1) { |
if (bn != (daddr_t)-1) { |
offset = dbtob(bn); |
offset = dbtob(bn); |
simple_lock(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
error = VOP_PUTPAGES(vp, trunc_page(offset), |
error = VOP_PUTPAGES(vp, trunc_page(offset), |
round_page(offset+fs->fs_bsize), |
round_page(offset+fs->fs_bsize), |
PGO_CLEANIT|PGO_SYNCIO|PGO_FREE); |
PGO_CLEANIT|PGO_SYNCIO|PGO_FREE); |
Line 2131 writevnblk(struct vnode *vp, void *data, |
|
Line 2132 writevnblk(struct vnode *vp, void *data, |
|
|
|
offset = lblktosize(fs, (off_t)lbn); |
offset = lblktosize(fs, (off_t)lbn); |
s = cow_enter(); |
s = cow_enter(); |
simple_lock(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
error = VOP_PUTPAGES(vp, trunc_page(offset), |
error = VOP_PUTPAGES(vp, trunc_page(offset), |
round_page(offset+fs->fs_bsize), PGO_CLEANIT|PGO_SYNCIO|PGO_FREE); |
round_page(offset+fs->fs_bsize), PGO_CLEANIT|PGO_SYNCIO|PGO_FREE); |
if (error == 0) |
if (error == 0) |
Line 2142 writevnblk(struct vnode *vp, void *data, |
|
Line 2143 writevnblk(struct vnode *vp, void *data, |
|
return error; |
return error; |
|
|
bcopy(data, bp->b_data, fs->fs_bsize); |
bcopy(data, bp->b_data, fs->fs_bsize); |
bp->b_flags |= B_NOCACHE; |
mutex_enter(&bufcache_lock); |
|
/* XXX Shouldn't need to lock for this, NOCACHE is only read later. */ |
|
bp->b_cflags |= BC_NOCACHE; |
|
mutex_exit(&bufcache_lock); |
|
|
return bwrite(bp); |
return bwrite(bp); |
} |
} |