summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ufs
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2000-07-11 22:07:57 +0000
committermckusick <mckusick@FreeBSD.org>2000-07-11 22:07:57 +0000
commita3d0c189ea25a7af3dfab30112f5d8d65e214e1c (patch)
treec84458dcf49aaf90ff010ebc108cb3b6ca3c2f4a /sys/ufs/ufs
parentc8c04452402a28eabd1ed8a1a06e0a14ac3d22c6 (diff)
downloadFreeBSD-src-a3d0c189ea25a7af3dfab30112f5d8d65e214e1c.zip
FreeBSD-src-a3d0c189ea25a7af3dfab30112f5d8d65e214e1c.tar.gz
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).
Diffstat (limited to 'sys/ufs/ufs')
-rw-r--r--sys/ufs/ufs/inode.h1
-rw-r--r--sys/ufs/ufs/ufs_bmap.c23
-rw-r--r--sys/ufs/ufs/ufs_extern.h1
-rw-r--r--sys/ufs/ufs/ufs_inode.c12
-rw-r--r--sys/ufs/ufs/ufs_quota.c2
-rw-r--r--sys/ufs/ufs/ufs_vnops.c3
6 files changed, 33 insertions, 9 deletions
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index 83960b0..6417a10 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -84,6 +84,7 @@ 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/ufs/ufs/ufs_bmap.c b/sys/ufs/ufs/ufs_bmap.c
index 9056340..ab4ac52 100644
--- a/sys/ufs/ufs/ufs_bmap.c
+++ b/sys/ufs/ufs/ufs_bmap.c
@@ -47,6 +47,7 @@
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/resourcevar.h>
+#include <sys/stat.h>
#include <ufs/ufs/extattr.h>
#include <ufs/ufs/quota.h>
@@ -115,7 +116,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
struct indir a[NIADDR+1], *xap;
ufs_daddr_t daddr;
long metalbn;
- int error, maxrun, num;
+ int error, num, maxrun = 0;
ip = VTOI(vp);
mp = vp->v_mount;
@@ -127,6 +128,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
#endif
if (runp) {
+ maxrun = mp->mnt_iosize_max / mp->mnt_stat.f_iosize - 1;
*runp = 0;
}
@@ -134,7 +136,6 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
*runb = 0;
}
- maxrun = mp->mnt_iosize_max / mp->mnt_stat.f_iosize - 1;
xap = ap == NULL ? a : ap;
if (!nump)
@@ -146,9 +147,12 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
num = *nump;
if (num == 0) {
*bnp = blkptrtodb(ump, ip->i_db[bn]);
- if (*bnp == 0)
- *bnp = -1;
- else if (runp) {
+ if (*bnp == 0) {
+ if (ip->i_flags & SF_SNAPSHOT)
+ *bnp = blkptrtodb(ump, bn * ump->um_seqinc);
+ else
+ *bnp = -1;
+ } else if (runp) {
daddr_t bnb = bn;
for (++bn; bn < NDADDR && *runp < maxrun &&
is_sequential(ump, ip->i_db[bn - 1], ip->i_db[bn]);
@@ -226,8 +230,13 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
if (bp)
bqrelse(bp);
- daddr = blkptrtodb(ump, daddr);
- *bnp = daddr == 0 ? -1 : daddr;
+ *bnp = blkptrtodb(ump, daddr);
+ if (*bnp == 0) {
+ if (ip->i_flags & SF_SNAPSHOT)
+ *bnp = blkptrtodb(ump, bn * ump->um_seqinc);
+ else
+ *bnp = -1;
+ }
return (0);
}
diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h
index d576be9..b740792 100644
--- a/sys/ufs/ufs/ufs_extern.h
+++ b/sys/ufs/ufs/ufs_extern.h
@@ -87,6 +87,7 @@ int ufs_init __P((struct vfsconf *));
void ufs_itimes __P((struct vnode *vp));
int ufs_lookup __P((struct vop_cachedlookup_args *));
int ufs_reclaim __P((struct vop_reclaim_args *));
+void ffs_snapremove __P((struct vnode *vp));
int ufs_root __P((struct mount *, struct vnode **));
int ufs_start __P((struct mount *, int, struct proc *));
int ufs_vinit __P((struct mount *, vop_t **, vop_t **, struct vnode **));
diff --git a/sys/ufs/ufs/ufs_inode.c b/sys/ufs/ufs/ufs_inode.c
index 507e716..485a6d2 100644
--- a/sys/ufs/ufs/ufs_inode.c
+++ b/sys/ufs/ufs/ufs_inode.c
@@ -77,6 +77,7 @@ ufs_inactive(ap)
if (ip->i_mode == 0)
goto out;
if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
+ (void) vn_write_suspend_wait(vp, V_WAIT);
#ifdef QUOTA
if (!getinoquota(ip))
(void)chkiq(ip, -1, NOCRED, 0);
@@ -91,8 +92,15 @@ ufs_inactive(ap)
ip->i_flag |= IN_CHANGE | IN_UPDATE;
UFS_VFREE(vp, ip->i_number, mode);
}
- if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE))
- UFS_UPDATE(vp, 0);
+ if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) {
+ if ((ip->i_flag & (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) == 0 &&
+ vn_write_suspend_wait(vp, V_NOWAIT)) {
+ ip->i_flag &= ~IN_ACCESS;
+ } else {
+ (void) vn_write_suspend_wait(vp, V_WAIT);
+ UFS_UPDATE(vp, 0);
+ }
+ }
out:
VOP_UNLOCK(vp, 0, p);
/*
diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c
index 574a330..6396f67 100644
--- a/sys/ufs/ufs/ufs_quota.c
+++ b/sys/ufs/ufs/ufs_quota.c
@@ -889,6 +889,7 @@ dqsync(vp, dq)
struct vnode *dqvp;
struct iovec aiov;
struct uio auio;
+ struct mount *mp;
int error;
if (dq == NODQUOT)
@@ -897,6 +898,7 @@ dqsync(vp, dq)
return (0);
if ((dqvp = dq->dq_ump->um_quotas[dq->dq_type]) == NULLVP)
panic("dqsync: file");
+ (void) vn_write_suspend_wait(dqvp, V_WAIT);
if (vp != dqvp)
vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, p);
while (dq->dq_flags & DQ_LOCK) {
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index e3b6e29..d97568c 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -702,6 +702,8 @@ ufs_remove(ap)
int error;
ip = VTOI(vp);
+ if ((ip->i_flags & SF_SNAPSHOT) != 0)
+ ffs_snapremove(vp);
if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
(VTOI(dvp)->i_flags & APPEND)) {
error = EPERM;
@@ -2215,6 +2217,7 @@ static struct vnodeopv_entry_desc ufs_vnodeop_entries[] = {
{ &vop_open_desc, (vop_t *) ufs_open },
{ &vop_pathconf_desc, (vop_t *) ufs_pathconf },
{ &vop_poll_desc, (vop_t *) vop_stdpoll },
+ { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
{ &vop_print_desc, (vop_t *) ufs_print },
{ &vop_readdir_desc, (vop_t *) ufs_readdir },
{ &vop_readlink_desc, (vop_t *) ufs_readlink },
OpenPOWER on IntegriCloud