summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcsapuntz <csapuntz@openbsd.org>1998-11-12 04:30:01 +0000
committercsapuntz <csapuntz@openbsd.org>1998-11-12 04:30:01 +0000
commit313df5db05c2816eef6468506a83d99bee97a20d (patch)
tree2a3697e7eb8246ed71155ccef88ab2f873b23741
parentMerge with FreeBSD: (diff)
downloadwireguard-openbsd-313df5db05c2816eef6468506a83d99bee97a20d.tar.xz
wireguard-openbsd-313df5db05c2816eef6468506a83d99bee97a20d.zip
Integrate latest soft updates patches for McKusick.
Integrate cleaner ffs mount code from FreeBSD. Most notably, this mount code prevents you from mounting an unclean file system read-write.
-rw-r--r--sys/kern/vfs_subr.c23
-rw-r--r--sys/kern/vfs_syscalls.c24
-rw-r--r--sys/sys/buf.h4
-rw-r--r--sys/ufs/ffs/ffs_softdep.c61
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c354
-rw-r--r--sys/ufs/ffs/ffs_vnops.c9
-rw-r--r--sys/ufs/ufs/ufs_vnops.c68
7 files changed, 369 insertions, 174 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index dc87e22f497..f639aba92f9 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_subr.c,v 1.23 1998/10/13 16:42:01 csapuntz Exp $ */
+/* $OpenBSD: vfs_subr.c,v 1.24 1998/11/12 04:30:02 csapuntz Exp $ */
/* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */
/*
@@ -1838,11 +1838,22 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
struct buf *nbp, *blist;
int s, error;
- if ((flags & V_SAVE) && vp->v_dirtyblkhd.lh_first != NULL) {
- if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)) != 0)
- return (error);
- if (vp->v_dirtyblkhd.lh_first != NULL)
- panic("vinvalbuf: dirty bufs");
+ if (flags & V_SAVE) {
+ s = splbio();
+ while (vp->v_numoutput) {
+ vp->v_flag |= VBWAIT;
+ sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
+ }
+ if (vp->v_dirtyblkhd.lh_first != NULL) {
+ splx(s);
+ if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)) != 0)
+ return (error);
+ s = splbio();
+ if (vp->v_numoutput > 0 ||
+ vp->v_dirtyblkhd.lh_first != NULL)
+ panic("vinvalbuf: dirty bufs");
+ }
+ splx(s);
}
for (;;) {
if ((blist = vp->v_cleanblkhd.lh_first) &&
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index f14b7f97cb4..8abc6e739a1 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.46 1998/09/27 03:23:47 millert Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.47 1998/11/12 04:30:01 csapuntz Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -566,6 +566,10 @@ sys_statfs(p, v, retval)
if ((error = VFS_STATFS(mp, sp, p)) != 0)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+#if notyet
+ if (mp->mnt_flag & MNT_SOFTDEP)
+ sp->f_eflags = STATFS_SOFTUPD;
+#endif
/* Don't let non-root see filesystem id (for NFS security) */
if (suser(p->p_ucred, &p->p_acflag)) {
bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
@@ -602,6 +606,10 @@ sys_fstatfs(p, v, retval)
if ((error = VFS_STATFS(mp, sp, p)) != 0)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+#if notyet
+ if (mp->mnt_flag & MNT_SOFTDEP)
+ sp->f_eflags = STATFS_SOFTUPD;
+#endif
/* Don't let non-root see filesystem id (for NFS security) */
if (suser(p->p_ucred, &p->p_acflag)) {
bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
@@ -645,7 +653,10 @@ sys_getfsstat(p, v, retval)
sp = &mp->mnt_stat;
/* Refresh stats unless MNT_NOWAIT is specified */
- if ((flags != MNT_NOWAIT) &&
+ if (flags != MNT_NOWAIT &&
+ flags != MNT_LAZY &&
+ (flags == MNT_WAIT ||
+ flags == 0) &&
(error = VFS_STATFS(mp, sp, p))) {
simple_lock(&mountlist_slock);
nmp = mp->mnt_list.cqe_next;
@@ -654,6 +665,10 @@ sys_getfsstat(p, v, retval)
}
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+#if notyet
+ if (mp->mnt_flag & MNT_SOFTDEP)
+ sp->f_eflags = STATFS_SOFTUPD;
+#endif
if (suser(p->p_ucred, &p->p_acflag)) {
bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
@@ -1991,7 +2006,10 @@ sys_fsync(p, v, retval)
return (error);
vp = (struct vnode *)fp->f_data;
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
+ if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p)) == 0 &&
+ bioops.io_fsync != NULL)
+ error = (*bioops.io_fsync)(vp);
+
VOP_UNLOCK(vp, 0, p);
return (error);
}
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index 674069bae1e..869b978fee2 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: buf.h,v 1.13 1998/08/04 22:01:49 millert Exp $ */
+/* $OpenBSD: buf.h,v 1.14 1998/11/12 04:30:02 csapuntz Exp $ */
/* $NetBSD: buf.h,v 1.25 1997/04/09 21:12:17 mycroft Exp $ */
/*
@@ -48,6 +48,7 @@
#define NOLIST ((struct buf *)0x87654321)
struct buf;
+struct vnode;
/*
* To avoid including <ufs/ffs/softdep.h>
@@ -66,6 +67,7 @@ extern struct bio_ops {
void (*io_start) __P((struct buf *));
void (*io_complete) __P((struct buf *));
void (*io_deallocate) __P((struct buf *));
+ int (*io_fsync) __P((struct vnode *));
int (*io_sync) __P((struct mount *));
} bioops;
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index abf7f8d6944..b286321fc53 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -52,7 +52,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ffs_softdep.c 9.27 (McKusick) 6/12/98
+ * @(#)ffs_softdep.c 9.30 (McKusick) 10/3/98
*/
#ifdef FFS_SOFTUPDATES
@@ -175,6 +175,7 @@ struct bio_ops bioops = {
softdep_disk_io_initiation, /* io_start */
softdep_disk_write_complete, /* io_complete */
softdep_deallocate_dependencies, /* io_deallocate */
+ softdep_fsync, /* io_fsync */
softdep_process_worklist, /* io_sync */
};
@@ -938,8 +939,20 @@ softdep_mount(devvp, mp, fs, cred)
brelse(bp);
}
#ifdef DEBUG
- if (!bcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal))
+ if (bcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal)) {
printf("ffs_mountfs: superblock updated\n");
+ printf ("%d %d %d %d\n",
+ cstotal.cs_nffree,
+ cstotal.cs_nbfree,
+ cstotal.cs_nifree,
+ cstotal.cs_ndir);
+
+ printf ("%d %d %d %d\n",
+ fs->fs_cstotal.cs_nffree,
+ fs->fs_cstotal.cs_nbfree,
+ fs->fs_cstotal.cs_nifree,
+ fs->fs_cstotal.cs_ndir);
+ }
#endif
bcopy(&cstotal, &fs->fs_cstotal, sizeof cstotal);
return (0);
@@ -2179,6 +2192,15 @@ softdep_change_directoryentry_offset(dp, base, oldloc, newloc, entrysize)
dap, da_pdlist);
break;
}
+ if (dap == NULL) {
+ for (dap = LIST_FIRST(&pagedep->pd_pendinghd);
+ dap; dap = LIST_NEXT(dap, da_pdlist)) {
+ if (dap->da_offset == oldoffset) {
+ dap->da_offset = newoffset;
+ break;
+ }
+ }
+ }
done:
bcopy(oldloc, newloc, entrysize);
FREE_LOCK(&lk);
@@ -2208,6 +2230,7 @@ free_diradd(dap)
} else {
dirrem = dap->da_previous;
pagedep = dirrem->dm_pagedep;
+ dirrem->dm_dirinum = pagedep->pd_ino;
add_to_worklist(&dirrem->dm_list);
}
if (inodedep_lookup(VFSTOUFS(pagedep->pd_mnt)->um_fs, dap->da_newinum,
@@ -2373,7 +2396,7 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
offset = blkoff(dp->i_fs, dp->i_offset);
/*
- * Whiteouts do not need addition dependencies.
+ * Whiteouts do not need diradd dependencies.
*/
if (newinum != WINO) {
MALLOC(dap, struct diradd *, sizeof(struct diradd),
@@ -2390,6 +2413,20 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
*/
dirrem = newdirrem(bp, dp, ip, isrmdir);
pagedep = dirrem->dm_pagedep;
+ /*
+ * The possible values for isrmdir:
+ * 0 - non-directory file rename
+ * 1 - directory rename within same directory
+ * inum - directory rename to new directory of given inode number
+ * When renaming to a new directory, we are both deleting and
+ * creating a new directory entry, so the link count on the new
+ * directory should not change. Thus we do not need the followup
+ * dirrem which is usually done in handle_workitem_remove. We set
+ * the DIRCHG flag to tell handle_workitem_remove to skip the
+ * followup dirrem.
+ */
+ if (isrmdir > 1)
+ dirrem->dm_state |= DIRCHG;
/*
* Whiteouts have no additional dependencies,
@@ -2405,7 +2442,7 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
}
FREE_LOCK(&lk);
return;
- }
+ }
/*
* Link into its inodedep. Put it on the id_bufwait list if the inode
@@ -2433,9 +2470,9 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
dap->da_state &= ~DIRCHG;
dap->da_pagedep = pagedep;
dirrem->dm_dirinum = pagedep->pd_ino;
- add_to_worklist(&dirrem->dm_list);
- }
- FREE_LOCK(&lk);
+ add_to_worklist(&dirrem->dm_list);
+ }
+ FREE_LOCK(&lk);
}
/*
@@ -2499,6 +2536,16 @@ handle_workitem_remove(dirrem)
ip->i_flag |= IN_CHANGE;
if ((error = VOP_TRUNCATE(vp, (off_t)0, 0, p->p_ucred, p)) != 0)
softdep_error("handle_workitem_remove: truncate", error);
+ /*
+ * Rename a directory to a new parent. Since, we are both deleting
+ * and creating a new directory entry, the link count on the new
+ * directory should not change. Thus we skip the followup dirrem.
+ */
+ if (dirrem->dm_state & DIRCHG) {
+ vput(vp);
+ WORKITEM_FREE(dirrem, D_DIRREM);
+ return;
+ }
ACQUIRE_LOCK(&lk);
(void) inodedep_lookup(ip->i_fs, dirrem->dm_oldinum, DEPALLOC,
&inodedep);
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 01def1c3f58..a0022678393 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_vfsops.c,v 1.17 1998/02/08 22:41:50 tholo Exp $ */
+/* $OpenBSD: ffs_vfsops.c,v 1.18 1998/11/12 04:30:03 csapuntz Exp $ */
/* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */
/*
@@ -123,7 +123,6 @@ ffs_mountroot()
fs = ump->um_fs;
(void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
(void)ffs_statfs(mp, &mp->mnt_stat, p);
-
vfs_unbusy(mp, p);
inittodr(fs->fs_time);
return (0);
@@ -146,13 +145,14 @@ ffs_mount(mp, path, data, ndp, p)
struct ufs_args args;
struct ufsmount *ump = NULL;
register struct fs *fs;
- size_t size;
- int error, flags;
+ int err = 0, flags;
+ int ronly;
mode_t accessmode;
+ size_t size;
- error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
- if (error)
- return (error);
+ err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
+ if (err)
+ return (err);
/*
* If updating, check whether changing from read-only to
* read/write; if there is no device name, that's all we do.
@@ -160,56 +160,80 @@ ffs_mount(mp, path, data, ndp, p)
if (mp->mnt_flag & MNT_UPDATE) {
ump = VFSTOUFS(mp);
fs = ump->um_fs;
- if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
+ devvp = ump->um_devvp;
+ err = 0;
+ ronly = fs->fs_ronly;
+
+ if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
if (mp->mnt_flag & MNT_SOFTDEP)
- error = softdep_flushfiles(mp, flags, p);
+ err = softdep_flushfiles(mp, flags, p);
else
- error = ffs_flushfiles(mp, flags, p);
- if (error == 0 &&
- ffs_cgupdate(ump, MNT_WAIT) == 0 &&
- fs->fs_clean & FS_WASCLEAN) {
- fs->fs_clean = FS_ISCLEAN;
- (void) ffs_sbupdate(ump, MNT_WAIT);
- }
- if (error)
- return (error);
- fs->fs_ronly = 1;
- }
- if (mp->mnt_flag & MNT_RELOAD) {
- error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
- if (error)
- return (error);
+ err = ffs_flushfiles(mp, flags, p);
+ ronly = 1;
}
- if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
+ if (!err && (mp->mnt_flag & MNT_RELOAD))
+ err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
+ if (err)
+ goto error_1;
+
+ if (ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
/*
* If upgrade to read-write by non-root, then verify
* that user has necessary permissions on the device.
*/
if (p->p_ucred->cr_uid != 0) {
- devvp = ump->um_devvp;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
- error = VOP_ACCESS(devvp, VREAD | VWRITE,
- p->p_ucred, p);
- if (error) {
- VOP_UNLOCK(devvp, 0, p);
- return (error);
- }
+ err = VOP_ACCESS(devvp, VREAD | VWRITE,
+ p->p_ucred, p);
VOP_UNLOCK(devvp, 0, p);
+ if (err) goto error_1;
+ }
+
+ if (fs->fs_clean == 0) {
+ if (mp->mnt_flag & MNT_FORCE) {
+ printf(
+"WARNING: %s was not properly dismounted\n",
+ fs->fs_fsmnt);
+ } else {
+ printf(
+"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
+ fs->fs_fsmnt);
+ err = EPERM;
+ goto error_1;
+ }
+ }
+
+ if ((fs->fs_flags & FS_DOSOFTDEP)) {
+ err = softdep_mount(devvp, mp, fs, p->p_ucred);
+ if (err)
+ goto error_1;
}
- fs->fs_ronly = 0;
- if (fs->fs_clean & FS_ISCLEAN)
- fs->fs_clean = FS_WASCLEAN;
- fs->fs_fmod = 1;
- (void) ffs_sbupdate(ump, MNT_WAIT);
+
+ ronly = 0;
}
+ /*
+ * Soft updates is incompatible with "async",
+ * so if we are doing softupdates stop the user
+ * from setting the async flag in an update.
+ * Softdep_mount() clears it in an initial mount
+ * or ro->rw remount.
+ */
+ if (mp->mnt_flag & MNT_SOFTDEP) {
+ mp->mnt_flag &= ~MNT_ASYNC;
+ }
+
if (args.fspec == 0) {
/*
* Process export requests.
*/
- return (vfs_export(mp, &ump->um_export, &args.export));
+ err = vfs_export(mp, &ump->um_export, &args.export);
+ if (err)
+ goto error_1;
+ else
+ goto success;
}
}
/*
@@ -217,18 +241,21 @@ ffs_mount(mp, path, data, ndp, p)
* and verify that it refers to a sensible block device.
*/
NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
- if ((error = namei(ndp)) != 0)
- return (error);
+ if ((err = namei(ndp)) != 0)
+ goto error_1;
+
devvp = ndp->ni_vp;
if (devvp->v_type != VBLK) {
- vrele(devvp);
- return (ENOTBLK);
+ err = ENOTBLK;
+ goto error_2;
}
+
if (major(devvp->v_rdev) >= nblkdev) {
- vrele(devvp);
- return (ENXIO);
+ err = ENXIO;
+ goto error_2;
}
+
/*
* If mount by non-root, then verify that user has necessary
* permissions on the device.
@@ -238,43 +265,91 @@ ffs_mount(mp, path, data, ndp, p)
if ((mp->mnt_flag & MNT_RDONLY) == 0)
accessmode |= VWRITE;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
- error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
- if (error) {
- vput(devvp);
- return (error);
- }
+ err = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
VOP_UNLOCK(devvp, 0, p);
+ if (err)
+ goto error_2;
}
- if ((mp->mnt_flag & MNT_UPDATE) == 0)
- error = ffs_mountfs(devvp, mp, p);
- else {
- if (devvp != ump->um_devvp)
- error = EINVAL; /* XXX needs translation */
- else
- vrele(devvp);
- }
- if (error) {
- vrele(devvp);
- return (error);
- }
- ump = VFSTOUFS(mp);
- fs = ump->um_fs;
- (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
- bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
- bcopy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
- (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
- &size);
- bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
- if (fs->fs_fmod != 0) { /* XXX */
- fs->fs_fmod = 0;
- if (fs->fs_clean & FS_WASCLEAN)
- fs->fs_time = time.tv_sec;
- else
- printf("%s: file system not clean; please fsck(8)\n",
- mp->mnt_stat.f_mntfromname);
- (void) ffs_cgupdate(ump, MNT_WAIT);
+
+ if (mp->mnt_flag & MNT_UPDATE) {
+ /*
+ ********************
+ * UPDATE
+ * If it's not the same vnode, or at least the same device
+ * then it's not correct.
+ ********************
+ */
+
+ if (devvp != ump->um_devvp) {
+ if (devvp->v_rdev == ump->um_devvp->v_rdev) {
+ vrele(devvp);
+ } else {
+ err = EINVAL; /* needs translation */
+ }
+ } else
+ vrele(devvp);
+ /*
+ * Update device name only on success
+ */
+ if (!err) {
+ /* Save "mounted from" info for mount point (NULL pad)*/
+ copyinstr(args.fspec,
+ mp->mnt_stat.f_mntfromname,
+ MNAMELEN - 1,
+ &size);
+ bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
+ }
+ } else {
+ /*
+ * Since this is a new mount, we want the names for
+ * the device and the mount point copied in. If an
+ * error occurs, the mountpoint is discarded by the
+ * upper level code.
+ */
+ /* Save "last mounted on" info for mount point (NULL pad)*/
+ copyinstr(path, /* mount point*/
+ mp->mnt_stat.f_mntonname, /* save area*/
+ MNAMELEN - 1, /* max size*/
+ &size); /* real size*/
+ bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
+
+ /* Save "mounted from" info for mount point (NULL pad)*/
+ copyinstr(args.fspec, /* device name*/
+ mp->mnt_stat.f_mntfromname, /* save area*/
+ MNAMELEN - 1, /* max size*/
+ &size); /* real size*/
+ bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
+
+ err = ffs_mountfs(devvp, mp, p);
}
+
+ if (err) goto error_2;
+
+ /*
+ * Initialize FS stat information in mount struct; uses both
+ * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
+ *
+ * This code is common to root and non-root mounts
+ */
+ (void)VFS_STATFS(mp, &mp->mnt_stat, p);
+
+success:
+ if (path && (mp->mnt_flag & MNT_UPDATE)) {
+ /* Update clean flag after changing read-onlyness. */
+ fs = ump->um_fs;
+ if (ronly != fs->fs_ronly) {
+ fs->fs_ronly = ronly;
+ fs->fs_clean = ronly &&
+ (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0;
+ ffs_sbupdate(ump, MNT_WAIT);
+ }
+ }
return (0);
+
+error_2: /* error with devvp held */
+ vrele (devvp);
+error_1: /* no state to back out */
+ return (err);
}
/*
@@ -347,6 +422,7 @@ ffs_reload(mountp, cred, p)
brelse(bp);
mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
ffs_oldfscompat(fs);
+ (void)ffs_statfs(mountp, &mountp->mnt_stat, p);
/*
* Step 3: re-read summary information from disk.
*/
@@ -363,6 +439,10 @@ ffs_reload(mountp, cred, p)
bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
brelse(bp);
}
+ if ((fs->fs_flags & FS_DOSOFTDEP))
+ (void) softdep_mount(devvp, mountp, fs, cred);
+ else
+ mountp->mnt_flag &= ~MNT_SOFTDEP;
/*
* We no longer know anything about clusters per cylinder group.
*/
@@ -434,6 +514,7 @@ ffs_mountfs(devvp, mp, p)
caddr_t base, space;
int error, i, blks, size, ronly;
int32_t *lp;
+ size_t strsize;
struct ucred *cred;
extern struct vnode *rootvp;
u_int64_t maxfilesize; /* XXX */
@@ -476,6 +557,22 @@ ffs_mountfs(devvp, mp, p)
error = EFTYPE; /* Inappropriate format */
goto out;
}
+ fs->fs_fmod = 0;
+ fs->fs_flags &= ~FS_UNCLEAN;
+ if (fs->fs_clean == 0) {
+ fs->fs_flags |= FS_UNCLEAN;
+ if (ronly || (mp->mnt_flag & MNT_FORCE)) {
+ printf(
+"WARNING: %s was not properly dismounted\n",
+ fs->fs_fsmnt);
+ } else {
+ printf(
+"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
+ fs->fs_fsmnt);
+ error = EPERM;
+ goto out;
+ }
+ }
/* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
error = EROFS; /* XXX what should be returned? */
@@ -492,6 +589,10 @@ ffs_mountfs(devvp, mp, p)
bp = NULL;
fs = ump->um_fs;
fs->fs_ronly = ronly;
+ if (ronly == 0) {
+ fs->fs_fmod = 1;
+ fs->fs_clean = 0;
+ }
size = fs->fs_cssize;
blks = howmany(size, fs->fs_fsize);
if (fs->fs_contigsumsize > 0)
@@ -526,6 +627,7 @@ ffs_mountfs(devvp, mp, p)
else
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
+ mp->mnt_flag |= MNT_LOCAL;
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
@@ -536,6 +638,27 @@ ffs_mountfs(devvp, mp, p)
ump->um_quotas[i] = NULLVP;
devvp->v_specmountpoint = mp;
ffs_oldfscompat(fs);
+
+ /*
+ * Set FS local "last mounted on" information (NULL pad)
+ */
+ copystr(mp->mnt_stat.f_mntonname, /* mount point*/
+ fs->fs_fsmnt, /* copy area*/
+ sizeof(fs->fs_fsmnt) - 1, /* max size*/
+ &strsize); /* real size*/
+ bzero(fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize);
+
+#if 0
+ if( mp->mnt_flag & MNT_ROOTFS) {
+ /*
+ * Root mount; update timestamp in mount structure.
+ * this will be used by the common root mount code
+ * to update the system clock.
+ */
+ mp->mnt_time = fs->fs_time;
+ }
+#endif
+
ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1; /* XXX */
if (fs->fs_maxfilesize > maxfilesize) /* XXX */
@@ -546,9 +669,7 @@ ffs_mountfs(devvp, mp, p)
free(base, M_UFSMNT);
goto out;
}
- if (fs->fs_clean & FS_ISCLEAN)
- fs->fs_clean = FS_WASCLEAN;
-
+ fs->fs_clean = 0;
(void) ffs_sbupdate(ump, MNT_WAIT);
}
return (0);
@@ -620,13 +741,17 @@ ffs_unmount(mp, mntflags, p)
ump = VFSTOUFS(mp);
fs = ump->um_fs;
- if (fs->fs_ronly == 0 &&
- ffs_cgupdate(ump, MNT_WAIT) == 0 &&
- fs->fs_clean & FS_WASCLEAN) {
- fs->fs_clean = FS_ISCLEAN;
- (void) ffs_sbupdate(ump, MNT_WAIT);
+ if (fs->fs_ronly == 0) {
+ fs->fs_clean = (fs->fs_flags & FS_UNCLEAN) ? 0 : 1;
+ error = ffs_sbupdate(ump, MNT_WAIT);
+ if (error) {
+ fs->fs_clean = 0;
+ return (error);
+ }
}
ump->um_devvp->v_specmountpoint = NULL;
+
+ vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
NOCRED, p);
vrele(ump->um_devvp);
@@ -634,6 +759,7 @@ ffs_unmount(mp, mntflags, p)
free(fs, M_UFSMNT);
free(ump, M_UFSMNT);
mp->mnt_data = (qaddr_t)0;
+ mp->mnt_flag &= ~MNT_LOCAL;
return (error);
}
@@ -774,14 +900,15 @@ loop:
continue;
}
simple_unlock(&mntvnode_slock);
- error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
+ error =
+ vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
if (error) {
simple_lock(&mntvnode_slock);
if (error == ENOENT)
goto loop;
continue;
}
- if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
+ if ((error = VOP_FSYNC(vp, cred, waitfor, p)))
allerror = error;
VOP_UNLOCK(vp, 0, p);
vrele(vp);
@@ -1002,44 +1129,13 @@ ffs_sbupdate(mp, waitfor)
{
register struct fs *dfs, *fs = mp->um_fs;
register struct buf *bp;
- int i, error = 0;
-
- bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb),
- (int)fs->fs_sbsize, 0, 0);
- bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
- /* Restore compatibility to old file systems. XXX */
- dfs = (struct fs *)bp->b_data; /* XXX */
- if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
- dfs->fs_nrpos = -1; /* XXX */
- if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
- int32_t *lp, tmp; /* XXX */
- /* XXX */
- lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
- tmp = lp[4]; /* XXX */
- for (i = 4; i > 0; i--) /* XXX */
- lp[i] = lp[i-1]; /* XXX */
- lp[0] = tmp; /* XXX */
- } /* XXX */
- dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
- if (waitfor == MNT_WAIT)
- error = bwrite(bp);
- else
- bawrite(bp);
- return (error);
-}
-
-int
-ffs_cgupdate(mp, waitfor)
- struct ufsmount *mp;
- int waitfor;
-{
- register struct fs *fs = mp->um_fs, *dfs;
- register struct buf *bp;
int blks;
caddr_t space;
- int i, size, error = 0, allerror = 0;
+ int i, size, error, allerror = 0;
- allerror = ffs_sbupdate(mp, waitfor);
+ /*
+ * First write back the summary information.
+ */
blks = howmany(fs->fs_cssize, fs->fs_fsize);
space = (caddr_t)fs->fs_csp[0];
for (i = 0; i < blks; i += fs->fs_frag) {
@@ -1050,12 +1146,11 @@ ffs_cgupdate(mp, waitfor)
size, 0, 0);
bcopy(space, bp->b_data, (u_int)size);
space += size;
- if (waitfor == MNT_WAIT)
- error = bwrite(bp);
- else
+ if (waitfor != MNT_WAIT)
bawrite(bp);
+ else if ((error = bwrite(bp)))
+ allerror = error;
}
-
/*
* Now write back the superblock itself. If any errors occurred
* up to this point, then fail so that the superblock avoids
@@ -1063,7 +1158,9 @@ ffs_cgupdate(mp, waitfor)
*/
if (allerror)
return (allerror);
- bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
+
+ bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb),
+ (int)fs->fs_sbsize, 0, 0);
fs->fs_fmod = 0;
fs->fs_time = time.tv_sec;
bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
@@ -1083,9 +1180,8 @@ ffs_cgupdate(mp, waitfor)
dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
if (waitfor != MNT_WAIT)
bawrite(bp);
- else if ((error = bwrite(bp)) != 0)
+ else if ((error = bwrite(bp)))
allerror = error;
-
return (allerror);
}
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 6224aad25a0..52f027086fb 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_vnops.c,v 1.7 1998/08/06 19:35:07 csapuntz Exp $ */
+/* $OpenBSD: ffs_vnops.c,v 1.8 1998/11/12 04:30:02 csapuntz Exp $ */
/* $NetBSD: ffs_vnops.c,v 1.7 1996/05/11 18:27:24 mycroft Exp $ */
/*
@@ -157,6 +157,7 @@ struct vnodeopv_entry_desc ffs_specop_entries[] = {
{ &vop_islocked_desc, ufs_islocked }, /* islocked */
{ &vop_pathconf_desc, spec_pathconf }, /* pathconf */
{ &vop_advlock_desc, spec_advlock }, /* advlock */
+ { &vop_vfree_desc, ffs_vfree }, /* vfree */
{ &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */
{ &vop_valloc_desc, spec_valloc }, /* valloc */
{ &vop_reallocblks_desc, spec_reallocblks }, /* reallocblks */
@@ -209,6 +210,7 @@ struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
{ &vop_islocked_desc, ufs_islocked }, /* islocked */
{ &vop_pathconf_desc, fifo_pathconf }, /* pathconf */
{ &vop_advlock_desc, fifo_advlock }, /* advlock */
+ { &vop_vfree_desc, ffs_vfree }, /* vfree */
{ &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */
{ &vop_valloc_desc, fifo_valloc }, /* valloc */
{ &vop_reallocblks_desc, fifo_reallocblks }, /* reallocblks */
@@ -318,10 +320,7 @@ loop2:
}
splx(s);
TIMEVAL_TO_TIMESPEC(&time, &ts);
- if ((error = VOP_UPDATE(vp, &ts, &ts, ap->a_waitfor == MNT_WAIT)) != 0) return (error);
- if (DOINGSOFTDEP(vp) && ap->a_waitfor == MNT_WAIT)
- error = softdep_fsync(vp);
- return (error);
+ return (VOP_UPDATE(vp, &ts, &ts, ap->a_waitfor == MNT_WAIT));
}
/*
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 2c755bbc5b8..7f899bac0bf 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ufs_vnops.c,v 1.20 1998/08/06 19:35:15 csapuntz Exp $ */
+/* $OpenBSD: ufs_vnops.c,v 1.21 1998/11/12 04:30:03 csapuntz Exp $ */
/* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */
/*
@@ -664,13 +664,11 @@ ufs_remove(v)
ip = VTOI(vp);
if (vp->v_type == VDIR || (ip->i_ffs_flags & (IMMUTABLE | APPEND)) ||
- (VTOI(dvp)->i_ffs_flags & APPEND)) {
+ (VTOI(dvp)->i_ffs_flags & APPEND))
error = EPERM;
- goto out;
- }
- if ((error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0)) != 0)
- goto out;
-out:
+ else
+ error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
+
if (dvp == vp)
vrele(vp);
else
@@ -955,7 +953,7 @@ abortit:
}
ip->i_flag |= IN_RENAME;
oldparent = dp->i_number;
- doingdirectory++;
+ doingdirectory = 1;
}
/* Why? */
vrele(fdvp);
@@ -1046,8 +1044,12 @@ abortit:
if (DOINGSOFTDEP(tdvp))
softdep_increase_linkcnt(dp);
if ((error = VOP_UPDATE(tdvp, &ts, &ts,
- !DOINGSOFTDEP(tdvp))) != 0)
+ !DOINGSOFTDEP(tdvp))) != 0) {
+ dp->i_effnlink--;
+ dp->i_ffs_nlink--;
+ dp->i_flag |= IN_CHANGE;
goto bad;
+ }
}
ufs_makedirentry(ip, tcnp, &newdir);
if ((error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL)) != 0) {
@@ -1102,11 +1104,14 @@ abortit:
}
if ((error = ufs_dirrewrite(dp, xp, ip->i_number,
- IFTODT(ip->i_ffs_mode), doingdirectory)) != 0)
+ IFTODT(ip->i_ffs_mode), (doingdirectory && newparent) ?
+ newparent : doingdirectory)) != 0)
goto bad;
if (doingdirectory) {
- dp->i_effnlink--;
- dp->i_flag |= IN_CHANGE;
+ if (!newparent) {
+ dp->i_effnlink--;
+ dp->i_flag |= IN_CHANGE;
+ }
xp->i_effnlink--;
xp->i_flag |= IN_CHANGE;
}
@@ -1122,7 +1127,9 @@ abortit:
* disk, so when running with that code we avoid doing
* them now.
*/
- dp->i_ffs_nlink--;
+ if (!newparent)
+ dp->i_ffs_nlink--;
+
xp->i_ffs_nlink--;
if ((error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC,
tcnp->cn_cred, tcnp->cn_proc)) != 0)
@@ -1226,7 +1233,7 @@ ufs_mkdir(v)
struct direct newdir;
struct dirtemplate dirtemplate, *dtp;
struct timespec ts;
- int error, dmode;
+ int error, dmode, blkoff;
#ifdef DIAGNOSTIC
if ((cnp->cn_flags & HASBUF) == 0)
@@ -1302,6 +1309,20 @@ ufs_mkdir(v)
ip->i_flag |= IN_CHANGE | IN_UPDATE;
vnode_pager_setsize(tvp, (u_long)ip->i_ffs_size);
bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
+ if (DOINGSOFTDEP(tvp)) {
+ /*
+ * Ensure that the entire newly allocated block is a
+ * valid directory so that future growth within the
+ * block does not have to ensure that the block is
+ * written before the inode
+ */
+ blkoff = DIRBLKSIZ;
+ while (blkoff < bp->b_bcount) {
+ ((struct direct *)
+ (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ;
+ blkoff += DIRBLKSIZ;
+ }
+ }
if ((error = VOP_UPDATE(tvp, &ts, &ts, !DOINGSOFTDEP(tvp))) != 0) {
(void)VOP_BWRITE(bp);
goto bad;
@@ -1368,10 +1389,13 @@ ufs_rmdir(v)
ip = VTOI(vp);
dp = VTOI(dvp);
/*
- * No rmdir "." please.
+ * No rmdir "." or of mounted on directories.
*/
- if (dp == ip) {
- vrele(dvp);
+ if (dp == ip || vp->v_mountedhere != 0) {
+ if (dp == ip)
+ vrele(dvp);
+ else
+ vput(dvp);
vput(vp);
return (EINVAL);
}
@@ -1408,12 +1432,10 @@ ufs_rmdir(v)
* Truncate inode. The only stuff left in the directory is "." and
* "..". The "." reference is inconsequential since we are quashing
* it. We have removed the "." reference and the reference in the
- * parent directory, but there may be other hard links. So,
- * ufs_dirremove will set the UF_IMMUTABLE flag to ensure that no
- * new entries are made. The soft dependency code will arrange to
- * do these operations after the parent directory entry has been
- * deleted on disk, so when running with that code we avoid doing
- * them now.
+ * parent directory, but there may be other hard links. The soft
+ * update code will arange to do these operations after the parent
+ * directory has been deleted on disk, so when running with
+ * that code we avoid doing them now.
*/
dp->i_effnlink--;
dp->i_flag |= IN_CHANGE;