summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs/ffs_vfsops.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ufs/ffs/ffs_vfsops.c')
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c404
1 files changed, 276 insertions, 128 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 505dd5d..1fd5951 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
+ * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
*/
#include <sys/param.h>
@@ -73,22 +73,19 @@ struct vfsops ufs_vfsops = {
ffs_fhtovp,
ffs_vptofh,
ffs_init,
+ ffs_sysctl,
};
extern u_long nextgennumber;
/*
* Called by main() when ufs is going to be mounted as root.
- *
- * Name is updated by mount(8) after booting.
*/
-#define ROOTNAME "root_device"
-
ffs_mountroot()
{
extern struct vnode *rootvp;
- register struct fs *fs;
- register struct mount *mp;
+ struct fs *fs;
+ struct mount *mp;
struct proc *p = curproc; /* XXX */
struct ufsmount *ump;
u_int size;
@@ -97,36 +94,27 @@ ffs_mountroot()
/*
* Get vnodes for swapdev and rootdev.
*/
- if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
- panic("ffs_mountroot: can't setup bdevvp's");
-
- mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
- bzero((char *)mp, (u_long)sizeof(struct mount));
- mp->mnt_op = &ufs_vfsops;
- mp->mnt_flag = MNT_RDONLY;
- if (error = ffs_mountfs(rootvp, mp, p)) {
- free(mp, M_MOUNT);
+ if ((error = bdevvp(swapdev, &swapdev_vp)) ||
+ (error = bdevvp(rootdev, &rootvp))) {
+ printf("ffs_mountroot: can't setup bdevvp's");
return (error);
}
- if (error = vfs_lock(mp)) {
- (void)ffs_unmount(mp, 0, p);
+ if (error = vfs_rootmountalloc("ufs", "root_device", &mp))
+ return (error);
+ if (error = ffs_mountfs(rootvp, mp, p)) {
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
free(mp, M_MOUNT);
return (error);
}
- TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
- mp->mnt_flag |= MNT_ROOTFS;
- mp->mnt_vnodecovered = NULLVP;
+ simple_lock(&mountlist_slock);
+ CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
+ simple_unlock(&mountlist_slock);
ump = VFSTOUFS(mp);
fs = ump->um_fs;
- bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
- fs->fs_fsmnt[0] = '/';
- bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
- MNAMELEN);
- (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
- &size);
- bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
+ (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
(void)ffs_statfs(mp, &mp->mnt_stat, p);
- vfs_unlock(mp);
+ vfs_unbusy(mp, p);
inittodr(fs->fs_time);
return (0);
}
@@ -150,6 +138,7 @@ ffs_mount(mp, path, data, ndp, p)
register struct fs *fs;
u_int size;
int error, flags;
+ mode_t accessmode;
if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
return (error);
@@ -160,22 +149,42 @@ ffs_mount(mp, path, data, ndp, p)
if (mp->mnt_flag & MNT_UPDATE) {
ump = VFSTOUFS(mp);
fs = ump->um_fs;
- error = 0;
if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- if (vfs_busy(mp))
- return (EBUSY);
- error = ffs_flushfiles(mp, flags, p);
- vfs_unbusy(mp);
+ if (error = ffs_flushfiles(mp, flags, p))
+ return (error);
+ fs->fs_clean = 1;
+ fs->fs_ronly = 1;
+ if (error = ffs_sbupdate(ump, MNT_WAIT)) {
+ fs->fs_clean = 0;
+ fs->fs_ronly = 0;
+ return (error);
+ }
}
- if (!error && (mp->mnt_flag & MNT_RELOAD))
- error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
- if (error)
+ if ((mp->mnt_flag & MNT_RELOAD) &&
+ (error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p)))
return (error);
- if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR))
+ if (fs->fs_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);
+ if (error = VOP_ACCESS(devvp, VREAD | VWRITE,
+ p->p_ucred, p)) {
+ VOP_UNLOCK(devvp, 0, p);
+ return (error);
+ }
+ VOP_UNLOCK(devvp, 0, p);
+ }
fs->fs_ronly = 0;
+ fs->fs_clean = 0;
+ (void) ffs_sbupdate(ump, MNT_WAIT);
+ }
if (args.fspec == 0) {
/*
* Process export requests.
@@ -200,6 +209,21 @@ ffs_mount(mp, path, data, ndp, p)
vrele(devvp);
return (ENXIO);
}
+ /*
+ * If mount by non-root, then verify that user has necessary
+ * permissions on the device.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ accessmode = VREAD;
+ if ((mp->mnt_flag & MNT_RDONLY) == 0)
+ accessmode |= VWRITE;
+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
+ vput(devvp);
+ return (error);
+ }
+ VOP_UNLOCK(devvp, 0, p);
+ }
if ((mp->mnt_flag & MNT_UPDATE) == 0)
error = ffs_mountfs(devvp, mp, p);
else {
@@ -247,8 +271,10 @@ ffs_reload(mountp, cred, p)
struct inode *ip;
struct csum *space;
struct buf *bp;
- struct fs *fs;
+ struct fs *fs, *newfs;
+ struct partinfo dpart;
int i, blks, size, error;
+ int32_t *lp;
if ((mountp->mnt_flag & MNT_RDONLY) == 0)
return (EINVAL);
@@ -261,21 +287,31 @@ ffs_reload(mountp, cred, p)
/*
* Step 2: re-read superblock from disk.
*/
- if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp))
+ if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
+ size = DEV_BSIZE;
+ else
+ size = dpart.disklab->d_secsize;
+ if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp))
return (error);
- fs = (struct fs *)bp->b_data;
- if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
- fs->fs_bsize < sizeof(struct fs)) {
+ newfs = (struct fs *)bp->b_data;
+ if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
+ newfs->fs_bsize < sizeof(struct fs)) {
brelse(bp);
return (EIO); /* XXX needs translation */
}
fs = VFSTOUFS(mountp)->um_fs;
- bcopy(&fs->fs_csp[0], &((struct fs *)bp->b_data)->fs_csp[0],
- sizeof(fs->fs_csp));
- bcopy(bp->b_data, fs, (u_int)fs->fs_sbsize);
+ /*
+ * Copy pointer fields back into superblock before copying in XXX
+ * new superblock. These should really be in the ufsmount. XXX
+ * Note that important parameters (eg fs_ncg) are unchanged.
+ */
+ bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
+ newfs->fs_maxcluster = fs->fs_maxcluster;
+ bcopy(newfs, fs, (u_int)fs->fs_sbsize);
if (fs->fs_sbsize < SBSIZE)
bp->b_flags |= B_INVAL;
brelse(bp);
+ mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
ffs_oldfscompat(fs);
/*
* Step 3: re-read summary information from disk.
@@ -292,21 +328,36 @@ ffs_reload(mountp, cred, p)
bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
brelse(bp);
}
+ /*
+ * We no longer know anything about clusters per cylinder group.
+ */
+ if (fs->fs_contigsumsize > 0) {
+ lp = fs->fs_maxcluster;
+ for (i = 0; i < fs->fs_ncg; i++)
+ *lp++ = fs->fs_contigsumsize;
+ }
+
loop:
+ simple_lock(&mntvnode_slock);
for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
+ if (vp->v_mount != mountp) {
+ simple_unlock(&mntvnode_slock);
+ goto loop;
+ }
nvp = vp->v_mntvnodes.le_next;
/*
* Step 4: invalidate all inactive vnodes.
*/
- if (vp->v_usecount == 0) {
- vgone(vp);
- continue;
- }
+ if (vrecycle(vp, &mntvnode_slock, p))
+ goto loop;
/*
* Step 5: invalidate all cached file data.
*/
- if (vget(vp, 1))
+ simple_lock(&vp->v_interlock);
+ simple_unlock(&mntvnode_slock);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
goto loop;
+ }
if (vinvalbuf(vp, 0, cred, p, 0, 0))
panic("ffs_reload: dirty2");
/*
@@ -323,9 +374,9 @@ loop:
ino_to_fsbo(fs, ip->i_number));
brelse(bp);
vput(vp);
- if (vp->v_mount != mountp)
- goto loop;
+ simple_lock(&mntvnode_slock);
}
+ simple_unlock(&mntvnode_slock);
return (0);
}
@@ -341,14 +392,17 @@ ffs_mountfs(devvp, mp, p)
register struct ufsmount *ump;
struct buf *bp;
register struct fs *fs;
- dev_t dev = devvp->v_rdev;
+ dev_t dev;
struct partinfo dpart;
caddr_t base, space;
- int havepart = 0, blks;
- int error, i, size;
- int ronly;
+ int error, i, blks, size, ronly;
+ int32_t *lp;
+ struct ucred *cred;
extern struct vnode *rootvp;
+ u_int64_t maxfilesize; /* XXX */
+ dev = devvp->v_rdev;
+ cred = p ? p->p_ucred : NOCRED;
/*
* Disallow multiple mounts of the same device.
* Disallow mounting of a device that is currently in use
@@ -359,22 +413,20 @@ ffs_mountfs(devvp, mp, p)
return (error);
if (vcount(devvp) > 1 && devvp != rootvp)
return (EBUSY);
- if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0))
+ if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
return (error);
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
return (error);
- if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
+ if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
size = DEV_BSIZE;
- else {
- havepart = 1;
+ else
size = dpart.disklab->d_secsize;
- }
bp = NULL;
ump = NULL;
- if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp))
+ if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, cred, &bp))
goto out;
fs = (struct fs *)bp->b_data;
if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
@@ -382,6 +434,11 @@ ffs_mountfs(devvp, mp, p)
error = EINVAL; /* XXX needs translation */
goto out;
}
+ /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
+ if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
+ error = EROFS; /* needs translation */
+ goto out;
+ }
ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
bzero((caddr_t)ump, sizeof *ump);
ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
@@ -393,18 +450,17 @@ ffs_mountfs(devvp, mp, p)
bp = NULL;
fs = ump->um_fs;
fs->fs_ronly = ronly;
- if (ronly == 0)
- fs->fs_fmod = 1;
- blks = howmany(fs->fs_cssize, fs->fs_fsize);
- base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT,
- M_WAITOK);
+ size = fs->fs_cssize;
+ blks = howmany(size, fs->fs_fsize);
+ if (fs->fs_contigsumsize > 0)
+ size += fs->fs_ncg * sizeof(int32_t);
+ base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
for (i = 0; i < blks; i += fs->fs_frag) {
size = fs->fs_bsize;
if (i + fs->fs_frag > blks)
size = (blks - i) * fs->fs_fsize;
- error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
- NOCRED, &bp);
- if (error) {
+ if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
+ cred, &bp)) {
free(base, M_UFSMNT);
goto out;
}
@@ -414,11 +470,15 @@ ffs_mountfs(devvp, mp, p)
brelse(bp);
bp = NULL;
}
+ if (fs->fs_contigsumsize > 0) {
+ fs->fs_maxcluster = lp = (int32_t *)space;
+ for (i = 0; i < fs->fs_ncg; i++)
+ *lp++ = fs->fs_contigsumsize;
+ }
mp->mnt_data = (qaddr_t)ump;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
- mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS;
+ 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;
@@ -429,11 +489,19 @@ ffs_mountfs(devvp, mp, p)
ump->um_quotas[i] = NULLVP;
devvp->v_specflags |= SI_MOUNTEDON;
ffs_oldfscompat(fs);
+ ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
+ maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
+ if (fs->fs_maxfilesize > maxfilesize) /* XXX */
+ fs->fs_maxfilesize = maxfilesize; /* XXX */
+ if (ronly == 0) {
+ fs->fs_clean = 0;
+ (void) ffs_sbupdate(ump, MNT_WAIT);
+ }
return (0);
out:
if (bp)
brelse(bp);
- (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
+ (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
if (ump) {
free(ump->um_fs, M_UFSMNT);
free(ump, M_UFSMNT);
@@ -457,7 +525,7 @@ ffs_oldfscompat(fs)
if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
fs->fs_nrpos = 8; /* XXX */
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
- quad_t sizepb = fs->fs_bsize; /* XXX */
+ u_int64_t sizepb = fs->fs_bsize; /* XXX */
/* XXX */
fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
for (i = 0; i < NIADDR; i++) { /* XXX */
@@ -481,28 +549,30 @@ ffs_unmount(mp, mntflags, p)
{
register struct ufsmount *ump;
register struct fs *fs;
- int error, flags, ronly;
+ int error, flags;
flags = 0;
- if (mntflags & MNT_FORCE) {
- if (mp->mnt_flag & MNT_ROOTFS)
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
if (error = ffs_flushfiles(mp, flags, p))
return (error);
ump = VFSTOUFS(mp);
fs = ump->um_fs;
- ronly = !fs->fs_ronly;
+ if (fs->fs_ronly == 0) {
+ fs->fs_clean = 1;
+ if (error = ffs_sbupdate(ump, MNT_WAIT)) {
+ fs->fs_clean = 0;
+ return (error);
+ }
+ }
ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
- error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
+ error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
NOCRED, p);
vrele(ump->um_devvp);
free(fs->fs_csp[0], M_UFSMNT);
free(fs, M_UFSMNT);
free(ump, M_UFSMNT);
mp->mnt_data = (qaddr_t)0;
- mp->mnt_flag &= ~MNT_LOCAL;
return (error);
}
@@ -514,12 +584,9 @@ ffs_flushfiles(mp, flags, p)
int flags;
struct proc *p;
{
- extern int doforce;
register struct ufsmount *ump;
int i, error;
- if (!doforce)
- flags &= ~FORCECLOSE;
ump = VFSTOUFS(mp);
#ifdef QUOTA
if (mp->mnt_flag & MNT_QUOTA) {
@@ -556,7 +623,6 @@ ffs_statfs(mp, sbp, p)
fs = ump->um_fs;
if (fs->fs_magic != FS_MAGIC)
panic("ffs_statfs");
- sbp->f_type = MOUNT_UFS;
sbp->f_bsize = fs->fs_fsize;
sbp->f_iosize = fs->fs_bsize;
sbp->f_blocks = fs->fs_dsize;
@@ -567,6 +633,7 @@ ffs_statfs(mp, sbp, p)
sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
sbp->f_ffree = fs->fs_cstotal.cs_nifree;
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy((caddr_t)mp->mnt_stat.f_mntonname,
(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
@@ -589,53 +656,55 @@ ffs_sync(mp, waitfor, cred, p)
struct ucred *cred;
struct proc *p;
{
- register struct vnode *vp;
- register struct inode *ip;
- register struct ufsmount *ump = VFSTOUFS(mp);
- register struct fs *fs;
+ struct vnode *nvp, *vp;
+ struct inode *ip;
+ struct ufsmount *ump = VFSTOUFS(mp);
+ struct fs *fs;
int error, allerror = 0;
fs = ump->um_fs;
- /*
- * Write back modified superblock.
- * Consistency check that the superblock
- * is still in the buffer cache.
- */
- if (fs->fs_fmod != 0) {
- if (fs->fs_ronly != 0) { /* XXX */
- printf("fs = %s\n", fs->fs_fsmnt);
- panic("update: rofs mod");
- }
- fs->fs_fmod = 0;
- fs->fs_time = time.tv_sec;
- allerror = ffs_sbupdate(ump, waitfor);
+ if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
+ printf("fs = %s\n", fs->fs_fsmnt);
+ panic("update: rofs mod");
}
/*
* Write back each (modified) inode.
*/
+ simple_lock(&mntvnode_slock);
loop:
for (vp = mp->mnt_vnodelist.lh_first;
vp != NULL;
- vp = vp->v_mntvnodes.le_next) {
+ vp = nvp) {
/*
* If the vnode that we are about to sync is no longer
* associated with this mount point, start over.
*/
if (vp->v_mount != mp)
goto loop;
- if (VOP_ISLOCKED(vp))
- continue;
+ simple_lock(&vp->v_interlock);
+ nvp = vp->v_mntvnodes.le_next;
ip = VTOI(vp);
if ((ip->i_flag &
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
- vp->v_dirtyblkhd.lh_first == NULL)
+ vp->v_dirtyblkhd.lh_first == NULL) {
+ simple_unlock(&vp->v_interlock);
continue;
- if (vget(vp, 1))
- goto loop;
+ }
+ simple_unlock(&mntvnode_slock);
+ 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))
allerror = error;
- vput(vp);
+ VOP_UNLOCK(vp, 0, p);
+ vrele(vp);
+ simple_lock(&mntvnode_slock);
}
+ simple_unlock(&mntvnode_slock);
/*
* Force stale file system control information to be flushed.
*/
@@ -644,6 +713,15 @@ loop:
#ifdef QUOTA
qsync(mp);
#endif
+ /*
+ * Write back modified superblock.
+ */
+ if (fs->fs_fmod != 0) {
+ fs->fs_fmod = 0;
+ fs->fs_time = time.tv_sec;
+ if (error = ffs_sbupdate(ump, waitfor))
+ allerror = error;
+ }
return (allerror);
}
@@ -659,8 +737,9 @@ ffs_vget(mp, ino, vpp)
ino_t ino;
struct vnode **vpp;
{
- register struct fs *fs;
- register struct inode *ip;
+ struct proc *p = curproc; /* XXX */
+ struct fs *fs;
+ struct inode *ip;
struct ufsmount *ump;
struct buf *bp;
struct vnode *vp;
@@ -680,6 +759,7 @@ ffs_vget(mp, ino, vpp)
type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
bzero((caddr_t)ip, sizeof(struct inode));
+ lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_fs = fs = ump->um_fs;
@@ -802,6 +882,53 @@ ffs_vptofh(vp, fhp)
}
/*
+ * Initialize the filesystem; just use ufs_init.
+ */
+int
+ffs_init(vfsp)
+ struct vfsconf *vfsp;
+{
+
+ return (ufs_init(vfsp));
+}
+
+/*
+ * fast filesystem related variables.
+ */
+ffs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+ int *name;
+ u_int namelen;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+ struct proc *p;
+{
+ extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree;
+
+ /* all sysctl names at this level are terminal */
+ if (namelen != 1)
+ return (ENOTDIR); /* overloaded */
+
+ switch (name[0]) {
+ case FFS_CLUSTERREAD:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &doclusterread));
+ case FFS_CLUSTERWRITE:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &doclusterwrite));
+ case FFS_REALLOCBLKS:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &doreallocblks));
+ case FFS_ASYNCFREE:
+ return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree));
+ default:
+ return (EOPNOTSUPP);
+ }
+ /* NOTREACHED */
+}
+
+/*
* Write a superblock and associated information back to disk.
*/
int
@@ -809,21 +936,15 @@ ffs_sbupdate(mp, waitfor)
struct ufsmount *mp;
int waitfor;
{
- register struct fs *fs = mp->um_fs;
+ register struct fs *dfs, *fs = mp->um_fs;
register struct buf *bp;
int blks;
caddr_t space;
- int i, size, error = 0;
+ int i, size, error, allerror = 0;
- bp = getblk(mp->um_devvp, SBLOCK, (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 */
- if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
- ((struct fs *)bp->b_data)->fs_nrpos = -1; /* XXX */
- if (waitfor == MNT_WAIT)
- error = bwrite(bp);
- else
- bawrite(bp);
+ /*
+ * 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) {
@@ -834,10 +955,37 @@ ffs_sbupdate(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;
}
- return (error);
+ /*
+ * Now write back the superblock itself. If any errors occurred
+ * up to this point, then fail so that the superblock avoids
+ * being written out as clean.
+ */
+ if (allerror)
+ return (allerror);
+ bp = getblk(mp->um_devvp, SBLOCK, (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)
+ bawrite(bp);
+ else if (error = bwrite(bp))
+ allerror = error;
+ return (allerror);
}
OpenPOWER on IntegriCloud