aboutsummaryrefslogtreecommitdiff
path: root/sys/miscfs
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2000-07-11 22:07:57 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2000-07-11 22:07:57 +0000
commitf2a2857bb34f5525f21ad016c25b20348d7a1fab (patch)
treeca1f94a427c4ab94cb5de2c2a7b557655d1a6376 /sys/miscfs
parentaa02fb5729dd652fa1da3f9e8e1152cca9010a1c (diff)
downloadsrc-f2a2857bb34f5525f21ad016c25b20348d7a1fab.tar.gz
src-f2a2857bb34f5525f21ad016c25b20348d7a1fab.zip
Add snapshots to the fast filesystem. Most of the changes support
the gating of system calls that cause modifications to the underlying filesystem. The gating can be enabled by any filesystem that needs to consistently suspend operations by adding the vop_stdgetwritemount to their set of vnops. Once gating is enabled, the function vfs_write_suspend stops all new write operations to a filesystem, allows any filesystem modifying system calls already in progress to complete, then sync's the filesystem to disk and returns. The function vfs_write_resume allows the suspended write operations to begin again. Gating is not added by default for all filesystems as for SMP systems it adds two extra locks to such critical kernel paths as the write system call. Thus, gating should only be added as needed. Details on the use and current status of snapshots in FFS can be found in /sys/ufs/ffs/README.snapshot so for brevity and timelyness is not included here. Unless and until you create a snapshot file, these changes should have no effect on your system (famous last words).
Notes
Notes: svn path=/head/; revision=62976
Diffstat (limited to 'sys/miscfs')
-rw-r--r--sys/miscfs/fdesc/fdesc_vnops.c9
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c1
-rw-r--r--sys/miscfs/specfs/spec_vnops.c22
-rw-r--r--sys/miscfs/union/union_subr.c30
-rw-r--r--sys/miscfs/union/union_vnops.c16
5 files changed, 66 insertions, 12 deletions
diff --git a/sys/miscfs/fdesc/fdesc_vnops.c b/sys/miscfs/fdesc/fdesc_vnops.c
index 772a94ca3776..72c7caee81be 100644
--- a/sys/miscfs/fdesc/fdesc_vnops.c
+++ b/sys/miscfs/fdesc/fdesc_vnops.c
@@ -383,6 +383,8 @@ fdesc_setattr(ap)
{
struct filedesc *fdp = ap->a_p->p_fd;
struct vattr *vap = ap->a_vap;
+ struct vnode *vp;
+ struct mount *mp;
struct file *fp;
unsigned fd;
int error;
@@ -403,8 +405,11 @@ fdesc_setattr(ap)
switch (fp->f_type) {
case DTYPE_FIFO:
case DTYPE_VNODE:
- error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap,
- ap->a_cred, ap->a_p);
+ vp = (struct vnode *)fp->f_data;
+ if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
+ return (error);
+ error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred, ap->a_p);
+ vn_finished_write(mp);
break;
default:
diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c
index 5bd13a771d48..03e3e374ba2e 100644
--- a/sys/miscfs/fifofs/fifo_vnops.c
+++ b/sys/miscfs/fifofs/fifo_vnops.c
@@ -107,6 +107,7 @@ static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
{ &vop_open_desc, (vop_t *) fifo_open },
{ &vop_pathconf_desc, (vop_t *) fifo_pathconf },
{ &vop_poll_desc, (vop_t *) fifo_poll },
+ { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
{ &vop_print_desc, (vop_t *) fifo_print },
{ &vop_read_desc, (vop_t *) fifo_read },
{ &vop_readdir_desc, (vop_t *) fifo_badop },
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
index cbe52f4ee748..baf40c3255d8 100644
--- a/sys/miscfs/specfs/spec_vnops.c
+++ b/sys/miscfs/specfs/spec_vnops.c
@@ -88,6 +88,7 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_open_desc, (vop_t *) spec_open },
{ &vop_pathconf_desc, (vop_t *) vop_stdpathconf },
{ &vop_poll_desc, (vop_t *) spec_poll },
+ { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
{ &vop_print_desc, (vop_t *) spec_print },
{ &vop_read_desc, (vop_t *) spec_read },
{ &vop_readdir_desc, (vop_t *) vop_panic },
@@ -415,16 +416,29 @@ spec_strategy(ap)
struct buf *bp;
struct vnode *vp;
struct mount *mp;
+ int error;
bp = ap->a_bp;
- if ((bp->b_iocmd == BIO_WRITE) && (LIST_FIRST(&bp->b_dep)) != NULL)
- buf_start(bp);
-
+ vp = ap->a_vp;
+ if ((bp->b_iocmd == BIO_WRITE)) {
+ if (vp->v_mount != NULL &&
+ (vp->v_mount->mnt_kern_flag & MNTK_SUSPENDED) != 0)
+ panic("spec_strategy: bad I/O");
+ if (LIST_FIRST(&bp->b_dep) != NULL)
+ buf_start(bp);
+ if ((vp->v_flag & VCOPYONWRITE) &&
+ (error = VOP_COPYONWRITE(vp, bp)) != 0 &&
+ error != EOPNOTSUPP) {
+ bp->b_io.bio_error = error;
+ bp->b_io.bio_flags |= BIO_ERROR;
+ biodone(&bp->b_io);
+ return (0);
+ }
+ }
/*
* Collect statistics on synchronous and asynchronous read
* and write counts for disks that have associated filesystems.
*/
- vp = ap->a_vp;
if (vn_isdisk(vp, NULL) && (mp = vp->v_specmountpoint) != NULL) {
if (bp->b_iocmd == BIO_WRITE) {
if (bp->b_lock.lk_lockholder == LK_KERNPROC)
diff --git a/sys/miscfs/union/union_subr.c b/sys/miscfs/union/union_subr.c
index 6b88befc18ed..d1d6e31f7056 100644
--- a/sys/miscfs/union/union_subr.c
+++ b/sys/miscfs/union/union_subr.c
@@ -747,6 +747,7 @@ union_copyup(un, docopy, cred, p)
struct proc *p;
{
int error;
+ struct mount *mp;
struct vnode *lvp, *uvp;
/*
@@ -759,9 +760,12 @@ union_copyup(un, docopy, cred, p)
if (error)
return (error);
- error = union_vn_create(&uvp, un, p);
- if (error)
+ if ((error = vn_start_write(un->un_dirvp, &mp, V_WAIT | PCATCH)) != 0)
return (error);
+ if ((error = union_vn_create(&uvp, un, p)) != 0) {
+ vn_finished_write(mp);
+ return (error);
+ }
lvp = un->un_lowervp;
@@ -785,6 +789,7 @@ union_copyup(un, docopy, cred, p)
}
VOP_UNLOCK(uvp, 0, p);
+ vn_finished_write(mp);
union_newupper(un, uvp);
KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
union_vn_close(uvp, FWRITE, cred, p);
@@ -910,11 +915,15 @@ union_mkshadow(um, dvp, cnp, vpp)
struct vattr va;
struct proc *p = cnp->cn_proc;
struct componentname cn;
+ struct mount *mp;
- error = union_relookup(um, dvp, vpp, cnp, &cn,
- cnp->cn_nameptr, cnp->cn_namelen);
- if (error)
+ if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)) != 0)
+ return (error);
+ if ((error = union_relookup(um, dvp, vpp, cnp, &cn,
+ cnp->cn_nameptr, cnp->cn_namelen)) != 0) {
+ vn_finished_write(mp);
return (error);
+ }
if (*vpp) {
if (cn.cn_flags & HASBUF) {
@@ -925,6 +934,7 @@ union_mkshadow(um, dvp, cnp, vpp)
vrele(*vpp);
else
vput(*vpp);
+ vn_finished_write(mp);
*vpp = NULLVP;
return (EEXIST);
}
@@ -950,6 +960,7 @@ union_mkshadow(um, dvp, cnp, vpp)
cn.cn_flags &= ~HASBUF;
}
/*vput(dvp);*/
+ vn_finished_write(mp);
return (error);
}
@@ -973,10 +984,15 @@ union_mkwhiteout(um, dvp, cnp, path)
struct proc *p = cnp->cn_proc;
struct vnode *wvp;
struct componentname cn;
+ struct mount *mp;
+ if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)) != 0)
+ return (error);
error = union_relookup(um, dvp, &wvp, cnp, &cn, path, strlen(path));
- if (error)
+ if (error) {
+ vn_finished_write(mp);
return (error);
+ }
if (wvp) {
if (cn.cn_flags & HASBUF) {
@@ -987,6 +1003,7 @@ union_mkwhiteout(um, dvp, cnp, path)
vrele(wvp);
else
vput(wvp);
+ vn_finished_write(mp);
return (EEXIST);
}
@@ -998,6 +1015,7 @@ union_mkwhiteout(um, dvp, cnp, path)
zfree(namei_zone, cn.cn_pnbuf);
cn.cn_flags &= ~HASBUF;
}
+ vn_finished_write(mp);
return (error);
}
diff --git a/sys/miscfs/union/union_vnops.c b/sys/miscfs/union/union_vnops.c
index 1c5ed5d5ff47..d7b95f38f8d4 100644
--- a/sys/miscfs/union/union_vnops.c
+++ b/sys/miscfs/union/union_vnops.c
@@ -93,6 +93,7 @@ static int union_print __P((struct vop_print_args *ap));
static int union_read __P((struct vop_read_args *ap));
static int union_readdir __P((struct vop_readdir_args *ap));
static int union_readlink __P((struct vop_readlink_args *ap));
+static int union_getwritemount __P((struct vop_getwritemount_args *ap));
static int union_reclaim __P((struct vop_reclaim_args *ap));
static int union_remove __P((struct vop_remove_args *ap));
static int union_rename __P((struct vop_rename_args *ap));
@@ -1681,6 +1682,20 @@ union_readlink(ap)
return (error);
}
+static int
+union_getwritemount(ap)
+ struct vop_getwritemount_args /* {
+ struct vnode *a_vp;
+ struct mount **a_mpp;
+ } */ *ap;
+{
+ struct vnode *vp = UPPERVP(ap->a_vp);
+
+ if (vp == NULL)
+ panic("union: missing upper layer in getwritemount");
+ return(VOP_GETWRITEMOUNT(vp, ap->a_mpp));
+}
+
/*
* union_inactive:
*
@@ -1963,6 +1978,7 @@ static struct vnodeopv_entry_desc union_vnodeop_entries[] = {
{ &vop_read_desc, (vop_t *) union_read },
{ &vop_readdir_desc, (vop_t *) union_readdir },
{ &vop_readlink_desc, (vop_t *) union_readlink },
+ { &vop_getwritemount_desc, (vop_t *) union_getwritemount },
{ &vop_reclaim_desc, (vop_t *) union_reclaim },
{ &vop_remove_desc, (vop_t *) union_remove },
{ &vop_rename_desc, (vop_t *) union_rename },