summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2001-03-07 07:09:55 +0000
committermckusick <mckusick@FreeBSD.org>2001-03-07 07:09:55 +0000
commit61db3f4296e7cbf26765b9523064a58053f033d1 (patch)
treebf90f85e1534824e6dd81dcd98746b86c51cf6c1
parent48c0c7d0fdb3955d984e7d3880153b7b5c711565 (diff)
downloadFreeBSD-src-61db3f4296e7cbf26765b9523064a58053f033d1.zip
FreeBSD-src-61db3f4296e7cbf26765b9523064a58053f033d1.tar.gz
Fixes to track snapshot copy-on-write checking in the specinfo
structure rather than assuming that the device vnode would reside in the FFS filesystem (which is obviously a broken assumption with the device filesystem).
-rw-r--r--sys/fs/specfs/spec_vnops.c4
-rw-r--r--sys/gnu/ext2fs/inode.h2
-rw-r--r--sys/gnu/fs/ext2fs/inode.h2
-rw-r--r--sys/kern/kern_conf.c1
-rw-r--r--sys/kern/vnode_if.src8
-rw-r--r--sys/miscfs/specfs/spec_vnops.c4
-rw-r--r--sys/sys/conf.h4
-rw-r--r--sys/sys/linedisc.h4
-rw-r--r--sys/ufs/ffs/ffs_extern.h1
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c97
-rw-r--r--sys/ufs/ffs/ffs_subr.c2
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c8
-rw-r--r--sys/ufs/ffs/ffs_vnops.c1
-rw-r--r--sys/ufs/ffs/fs.h3
-rw-r--r--sys/ufs/mfs/mfs_vnops.c1
-rw-r--r--sys/ufs/ufs/inode.h2
16 files changed, 72 insertions, 72 deletions
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 35a0a49..2940f40 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -455,8 +455,8 @@ spec_strategy(ap)
bp->b_flags &= ~B_VALIDSUSPWRT;
if (LIST_FIRST(&bp->b_dep) != NULL)
buf_start(bp);
- if ((vp->v_flag & VCOPYONWRITE) &&
- (error = VOP_COPYONWRITE(vp, bp)) != 0 &&
+ if ((vp->v_flag & VCOPYONWRITE) && vp->v_rdev->si_copyonwrite &&
+ (error = (*vp->v_rdev->si_copyonwrite)(vp, bp)) != 0 &&
error != EOPNOTSUPP) {
bp->b_io.bio_error = error;
bp->b_io.bio_flags |= BIO_ERROR;
diff --git a/sys/gnu/ext2fs/inode.h b/sys/gnu/ext2fs/inode.h
index 79e79b1..3e7c67d 100644
--- a/sys/gnu/ext2fs/inode.h
+++ b/sys/gnu/ext2fs/inode.h
@@ -67,6 +67,7 @@ typedef long ufs_lbn_t;
*/
struct inode {
LIST_ENTRY(inode) i_hash;/* Hash chain. */
+ TAILQ_ENTRY(inode) i_nextsnap; /* snapshot file list */
struct vnode *i_vnode;/* Vnode associated with this inode. */
struct vnode *i_devvp;/* Vnode for block I/O. */
u_int32_t i_flag; /* flags, see below */
@@ -83,7 +84,6 @@ struct inode {
struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
u_quad_t i_modrev; /* Revision level for NFS lease. */
struct lockf *i_lockf;/* Head of byte-level lock list. */
- struct inode *i_copyonwrite; /* copy-on-write list */
/*
* Side effects; used during directory lookup.
*/
diff --git a/sys/gnu/fs/ext2fs/inode.h b/sys/gnu/fs/ext2fs/inode.h
index 79e79b1..3e7c67d 100644
--- a/sys/gnu/fs/ext2fs/inode.h
+++ b/sys/gnu/fs/ext2fs/inode.h
@@ -67,6 +67,7 @@ typedef long ufs_lbn_t;
*/
struct inode {
LIST_ENTRY(inode) i_hash;/* Hash chain. */
+ TAILQ_ENTRY(inode) i_nextsnap; /* snapshot file list */
struct vnode *i_vnode;/* Vnode associated with this inode. */
struct vnode *i_devvp;/* Vnode for block I/O. */
u_int32_t i_flag; /* flags, see below */
@@ -83,7 +84,6 @@ struct inode {
struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
u_quad_t i_modrev; /* Revision level for NFS lease. */
struct lockf *i_lockf;/* Head of byte-level lock list. */
- struct inode *i_copyonwrite; /* copy-on-write list */
/*
* Side effects; used during directory lookup.
*/
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index e6a173b..86185f7 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -179,6 +179,7 @@ allocdev(void)
si->si_flags |= SI_STASHED;
}
LIST_INIT(&si->si_names);
+ TAILQ_INIT(&si->si_snapshots);
return (si);
}
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index c8f91f1..87fe31c 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -400,14 +400,6 @@ vop_getwritemount {
};
#
-#% copyonwrite vp L L L
-#
-vop_copyonwrite {
- IN struct vnode *vp;
- IN struct buf *bp;
-};
-
-#
#% print vp = = =
#
vop_print {
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
index 35a0a49..2940f40 100644
--- a/sys/miscfs/specfs/spec_vnops.c
+++ b/sys/miscfs/specfs/spec_vnops.c
@@ -455,8 +455,8 @@ spec_strategy(ap)
bp->b_flags &= ~B_VALIDSUSPWRT;
if (LIST_FIRST(&bp->b_dep) != NULL)
buf_start(bp);
- if ((vp->v_flag & VCOPYONWRITE) &&
- (error = VOP_COPYONWRITE(vp, bp)) != 0 &&
+ if ((vp->v_flag & VCOPYONWRITE) && vp->v_rdev->si_copyonwrite &&
+ (error = (*vp->v_rdev->si_copyonwrite)(vp, bp)) != 0 &&
error != EOPNOTSUPP) {
bp->b_io.bio_error = error;
bp->b_io.bio_flags |= BIO_ERROR;
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index 81b94bc..7f1e85e 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -50,6 +50,8 @@
struct tty;
struct disk;
struct vnode;
+struct buf;
+TAILQ_HEAD(snaphead, inode);
struct specinfo {
u_int si_flags;
@@ -64,6 +66,8 @@ struct specinfo {
LIST_ENTRY(specinfo) si_hash;
SLIST_HEAD(, vnode) si_hlist;
LIST_HEAD(, specinfo) si_names;
+ struct snaphead si_snapshots;
+ int (*si_copyonwrite)(struct vnode *, struct buf *);
u_int si_inode;
char si_name[SPECNAMELEN + 1];
void *si_drv1, *si_drv2;
diff --git a/sys/sys/linedisc.h b/sys/sys/linedisc.h
index 81b94bc..7f1e85e 100644
--- a/sys/sys/linedisc.h
+++ b/sys/sys/linedisc.h
@@ -50,6 +50,8 @@
struct tty;
struct disk;
struct vnode;
+struct buf;
+TAILQ_HEAD(snaphead, inode);
struct specinfo {
u_int si_flags;
@@ -64,6 +66,8 @@ struct specinfo {
LIST_ENTRY(specinfo) si_hash;
SLIST_HEAD(, vnode) si_hlist;
LIST_HEAD(, specinfo) si_names;
+ struct snaphead si_snapshots;
+ int (*si_copyonwrite)(struct vnode *, struct buf *);
u_int si_inode;
char si_name[SPECNAMELEN + 1];
void *si_drv1, *si_drv2;
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index 7801412..a755980 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -77,7 +77,6 @@ void ffs_blkfree __P((struct inode *, ufs_daddr_t, long));
ufs_daddr_t ffs_blkpref __P((struct inode *, ufs_daddr_t, int, ufs_daddr_t *));
int ffs_bmap __P((struct vop_bmap_args *));
void ffs_clrblock __P((struct fs *, u_char *, ufs_daddr_t));
-int ffs_copyonwrite __P((struct vop_copyonwrite_args *ap));
int ffs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
int ffs_flushfiles __P((struct mount *, int, struct proc *));
void ffs_fragacct __P((struct fs *, int, int32_t [], int));
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 029ab35..c8a808f 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -36,6 +36,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/conf.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/proc.h>
@@ -62,6 +63,7 @@
static int indiracct __P((struct vnode *, struct vnode *, int, ufs_daddr_t,
int, int, int, int));
static int snapacct __P((struct vnode *, ufs_daddr_t *, ufs_daddr_t *));
+static int ffs_copyonwrite __P((struct vnode *, struct buf *));
static int readblock __P((struct buf *, daddr_t));
#ifdef DEBUG
@@ -85,14 +87,15 @@ ffs_snapshot(mp, snapfile)
int blksperindir, flag = mp->mnt_flag;
void *space;
struct fs *copy_fs, *fs = VFSTOUFS(mp)->um_fs;
+ struct snaphead *snaphead;
struct proc *p = CURPROC;
- struct inode *devip, *ip, *xp;
+ struct inode *ip, *xp;
struct buf *bp, *nbp, *ibp;
- struct vnode *vp, *devvp;
struct nameidata nd;
struct mount *wrtmp;
struct dinode *dip;
struct vattr vat;
+ struct vnode *vp;
struct cg *cgp;
/*
@@ -153,8 +156,6 @@ restart:
}
vp = nd.ni_vp;
ip = VTOI(vp);
- devvp = ip->i_devvp;
- devip = VTOI(devvp);
/*
* Allocate and copy the last block contents so as to be able
* to set size to that of the filesystem.
@@ -379,7 +380,8 @@ restart:
* Copy allocation information from other snapshots and then
* expunge them from the view of the current snapshot.
*/
- for (xp = devip->i_copyonwrite; xp; xp = xp->i_copyonwrite) {
+ snaphead = &ip->i_devvp->v_rdev->si_snapshots;
+ TAILQ_FOREACH(xp, snaphead, i_nextsnap) {
/*
* Before expunging a snapshot inode, note all the
* blocks that it claims with BLK_SNAP so that fsck will
@@ -451,16 +453,11 @@ restart:
* it must be placed at the end of the list.
*/
fs->fs_snapinum[snaploc] = ip->i_number;
- if (ip->i_copyonwrite != 0)
+ if (ip->i_nextsnap.tqe_prev != 0)
panic("ffs_snapshot: %d already on list", ip->i_number);
- if (devip->i_copyonwrite == 0) {
- devvp->v_flag |= VCOPYONWRITE;
- devip->i_copyonwrite = ip;
- } else {
- for (xp = devip->i_copyonwrite; xp->i_copyonwrite != 0; )
- xp = xp->i_copyonwrite;
- xp->i_copyonwrite = ip;
- }
+ TAILQ_INSERT_TAIL(snaphead, ip, i_nextsnap);
+ ip->i_devvp->v_rdev->si_copyonwrite = ffs_copyonwrite;
+ ip->i_devvp->v_flag |= VCOPYONWRITE;
vp->v_flag |= VSYSTEM;
/*
* Resume operation on filesystem.
@@ -608,8 +605,8 @@ ffs_snapgone(ip)
/*
* Find snapshot in incore list.
*/
- for (xp = VTOI(ip->i_devvp); xp; xp = xp->i_copyonwrite)
- if (xp->i_copyonwrite == ip)
+ TAILQ_FOREACH(xp, &ip->i_devvp->v_rdev->si_snapshots, i_nextsnap)
+ if (xp == ip)
break;
if (xp == 0)
printf("ffs_snapgone: lost snapshot vnode %d\n",
@@ -625,7 +622,7 @@ void
ffs_snapremove(vp)
struct vnode *vp;
{
- struct inode *ip, *xp;
+ struct inode *ip;
struct vnode *devvp;
struct buf *ibp;
struct fs *fs;
@@ -653,18 +650,17 @@ ffs_snapremove(vp)
* Clear copy-on-write flag if last snapshot.
*/
devvp = ip->i_devvp;
- for (xp = VTOI(devvp); xp; xp = xp->i_copyonwrite) {
- if (xp->i_copyonwrite != ip)
- continue;
- xp->i_copyonwrite = ip->i_copyonwrite;
- ip->i_copyonwrite = 0;
- break;
- }
- if (xp == 0)
+ if (ip->i_nextsnap.tqe_prev == 0) {
printf("ffs_snapremove: lost snapshot vnode %d\n",
ip->i_number);
- if (VTOI(devvp)->i_copyonwrite == 0)
- devvp->v_flag &= ~VCOPYONWRITE;
+ } else {
+ TAILQ_REMOVE(&devvp->v_rdev->si_snapshots, ip, i_nextsnap);
+ ip->i_nextsnap.tqe_prev = 0;
+ if (TAILQ_FIRST(&devvp->v_rdev->si_snapshots) == 0) {
+ devvp->v_rdev->si_copyonwrite = 0;
+ devvp->v_flag &= ~VCOPYONWRITE;
+ }
+ }
/*
* Clear all BLK_NOCOPY fields. Pass any block claims to other
* snapshots that want them (see ffs_snapblkfree below).
@@ -730,10 +726,11 @@ ffs_snapblkfree(freeip, bno, size)
struct vnode *vp;
ufs_daddr_t lbn, blkno;
int indiroff = 0, error = 0, claimedblk = 0;
+ struct snaphead *snaphead;
lbn = fragstoblks(fs, bno);
- for (ip = VTOI(freeip->i_devvp)->i_copyonwrite; ip;
- ip = ip->i_copyonwrite) {
+ snaphead = &freeip->i_devvp->v_rdev->si_snapshots;
+ TAILQ_FOREACH(ip, snaphead, i_nextsnap) {
vp = ITOV(ip);
/*
* Lookup block being written.
@@ -875,11 +872,12 @@ ffs_snapshot_mount(mp)
struct ufsmount *ump = VFSTOUFS(mp);
struct fs *fs = ump->um_fs;
struct proc *p = CURPROC;
- struct inode *ip, **listtailp;
+ struct snaphead *snaphead;
struct vnode *vp;
+ struct inode *ip;
int error, snaploc, loc;
- listtailp = &VTOI(ump->um_devvp)->i_copyonwrite;
+ snaphead = &ump->um_devvp->v_rdev->si_snapshots;
for (snaploc = 0; snaploc < FSMAXSNAP; snaploc++) {
if (fs->fs_snapinum[snaploc] == 0)
return;
@@ -901,14 +899,15 @@ ffs_snapshot_mount(mp)
snaploc--;
continue;
}
- if (ip->i_copyonwrite != 0)
+ if (ip->i_nextsnap.tqe_prev != 0)
panic("ffs_snapshot_mount: %d already on list",
ip->i_number);
- *listtailp = ip;
- listtailp = &ip->i_copyonwrite;
+ else
+ TAILQ_INSERT_TAIL(snaphead, ip, i_nextsnap);
vp->v_flag |= VSYSTEM;
- VOP_UNLOCK(vp, 0, p);
+ ump->um_devvp->v_rdev->si_copyonwrite = ffs_copyonwrite;
ump->um_devvp->v_flag |= VCOPYONWRITE;
+ VOP_UNLOCK(vp, 0, p);
}
}
@@ -920,15 +919,16 @@ ffs_snapshot_unmount(mp)
struct mount *mp;
{
struct ufsmount *ump = VFSTOUFS(mp);
- struct inode *devip = VTOI(ump->um_devvp);
+ struct snaphead *snaphead = &ump->um_devvp->v_rdev->si_snapshots;
struct inode *xp;
- while ((xp = devip->i_copyonwrite) != 0) {
- devip->i_copyonwrite = xp->i_copyonwrite;
- xp->i_copyonwrite = 0;
+ while ((xp = TAILQ_FIRST(snaphead)) != 0) {
+ TAILQ_REMOVE(snaphead, xp, i_nextsnap);
+ xp->i_nextsnap.tqe_prev = 0;
if (xp->i_effnlink > 0)
vrele(ITOV(xp));
}
+ ump->um_devvp->v_rdev->si_copyonwrite = 0;
ump->um_devvp->v_flag &= ~VCOPYONWRITE;
}
@@ -936,25 +936,24 @@ ffs_snapshot_unmount(mp)
* Check for need to copy block that is about to be written,
* copying the block if necessary.
*/
-int
-ffs_copyonwrite(ap)
- struct vop_copyonwrite_args /* {
- struct vnode *a_vp;
- struct buf *a_bp;
- } */ *ap;
+static int
+ffs_copyonwrite(devvp, bp)
+ struct vnode *devvp;
+ struct buf *bp;
{
- struct buf *ibp, *cbp, *savedcbp = 0, *bp = ap->a_bp;
- struct fs *fs = VTOI(bp->b_vp)->i_fs;
+ struct buf *ibp, *cbp, *savedcbp = 0;
struct proc *p = CURPROC;
+ struct fs *fs;
struct inode *ip;
struct vnode *vp;
ufs_daddr_t lbn, blkno;
int indiroff, error = 0;
+ fs = TAILQ_FIRST(&devvp->v_rdev->si_snapshots)->i_fs;
lbn = fragstoblks(fs, dbtofsb(fs, bp->b_blkno));
if (p->p_flag & P_COWINPROGRESS)
panic("ffs_copyonwrite: recursive call");
- for (ip = VTOI(ap->a_vp)->i_copyonwrite; ip; ip = ip->i_copyonwrite) {
+ TAILQ_FOREACH(ip, &devvp->v_rdev->si_snapshots, i_nextsnap) {
vp = ITOV(ip);
/*
* We ensure that everything of our own that needs to be
@@ -1020,7 +1019,7 @@ retry:
if (snapdebug) {
printf("Copyonwrite: snapino %d lbn %d for ",
ip->i_number, lbn);
- if (bp->b_vp == ap->a_vp)
+ if (bp->b_vp == devvp)
printf("fs metadata");
else
printf("inum %d", VTOI(bp->b_vp)->i_number);
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index 5155a42..c3471de 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -191,6 +191,7 @@ ffs_isblock(fs, cp, h)
default:
panic("ffs_isblock");
}
+ return (0);
}
/*
@@ -215,6 +216,7 @@ ffs_isfreeblock(fs, cp, h)
default:
panic("ffs_isfreeblock");
}
+ return (0);
}
/*
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 4558780..78aaae5 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -987,15 +987,15 @@ loop:
goto loop;
}
}
- if (waitfor == MNT_NOWAIT) {
+#ifdef QUOTA
+ qsync(mp);
+#endif
+ if (waitfor != MNT_LAZY) {
vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
allerror = error;
VOP_UNLOCK(ump->um_devvp, 0, p);
}
-#ifdef QUOTA
- qsync(mp);
-#endif
/*
* Write back modified superblock.
*/
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index a01217d..4910f6a 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -95,7 +95,6 @@ vop_t **ffs_specop_p;
static struct vnodeopv_entry_desc ffs_specop_entries[] = {
{ &vop_default_desc, (vop_t *) ufs_vnoperatespec },
{ &vop_fsync_desc, (vop_t *) ffs_fsync },
- { &vop_copyonwrite_desc, (vop_t *) ffs_copyonwrite },
#ifdef FFS_EXTATTR
{ &vop_getextattr_desc, (vop_t *) ufs_vop_getextattr },
{ &vop_setextattr_desc, (vop_t *) ufs_vop_setextattr },
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index 515c065..53d497c 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -513,7 +513,8 @@ struct ocg {
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (ip)->i_size))))
#define dblksize(fs, dip, lbn) \
- (((lbn) >= NDADDR || (dip)->di_size >= smalllblktosize(fs, (lbn) + 1)) \
+ (((lbn) >= NDADDR || \
+ (dip)->di_size >= (u_int64_t)smalllblktosize(fs, (lbn) + 1)) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (dip)->di_size))))
#define sblksize(fs, size, lbn) \
diff --git a/sys/ufs/mfs/mfs_vnops.c b/sys/ufs/mfs/mfs_vnops.c
index 872d947..9912dfb 100644
--- a/sys/ufs/mfs/mfs_vnops.c
+++ b/sys/ufs/mfs/mfs_vnops.c
@@ -82,7 +82,6 @@ static struct vnodeopv_entry_desc mfs_vnodeop_entries[] = {
{ &vop_print_desc, (vop_t *) mfs_print },
{ &vop_reclaim_desc, (vop_t *) mfs_reclaim },
{ &vop_strategy_desc, (vop_t *) mfs_strategy },
- { &vop_copyonwrite_desc, (vop_t *) vop_eopnotsupp },
{ &vop_unlock_desc, (vop_t *) vop_defaultop },
{ &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
{ NULL, NULL }
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index 79e79b1..3e7c67d 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -67,6 +67,7 @@ typedef long ufs_lbn_t;
*/
struct inode {
LIST_ENTRY(inode) i_hash;/* Hash chain. */
+ TAILQ_ENTRY(inode) i_nextsnap; /* snapshot file list */
struct vnode *i_vnode;/* Vnode associated with this inode. */
struct vnode *i_devvp;/* Vnode for block I/O. */
u_int32_t i_flag; /* flags, see below */
@@ -83,7 +84,6 @@ struct inode {
struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
u_quad_t i_modrev; /* Revision level for NFS lease. */
struct lockf *i_lockf;/* Head of byte-level lock list. */
- struct inode *i_copyonwrite; /* copy-on-write list */
/*
* Side effects; used during directory lookup.
*/
OpenPOWER on IntegriCloud