diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1998-11-12 04:30:04 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1998-11-12 04:30:04 +0000 |
commit | 0a12e173ebc48873aa6964dd3a91bf32635e5a67 (patch) | |
tree | dd60cd68eab27eaec9bf1dd1f4fd2d518eac6bb2 /sys/ufs | |
parent | e2bcb0a0f821ee6e693b46fb23b1e9cf47e1e0c7 (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.c | 61 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 354 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vnops.c | 9 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 68 |
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; |