summaryrefslogtreecommitdiff
path: root/sys/ufs
diff options
context:
space:
mode:
authorConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>1998-11-12 04:30:04 +0000
committerConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>1998-11-12 04:30:04 +0000
commit0a12e173ebc48873aa6964dd3a91bf32635e5a67 (patch)
treedd60cd68eab27eaec9bf1dd1f4fd2d518eac6bb2 /sys/ufs
parente2bcb0a0f821ee6e693b46fb23b1e9cf47e1e0c7 (diff)
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.
Diffstat (limited to 'sys/ufs')
-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
4 files changed, 328 insertions, 164 deletions
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;