diff options
author | julian <julian@FreeBSD.org> | 1995-08-28 09:19:25 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 1995-08-28 09:19:25 +0000 |
commit | ebb726ec45c12268b6b931aa636809cc9cb99a90 (patch) | |
tree | 53b6da073fd58ab81ebf18bb0642954c76b642bd /sys/ufs | |
parent | 6f51a7615899188fd49e4446341be92684c778de (diff) | |
download | FreeBSD-src-ebb726ec45c12268b6b931aa636809cc9cb99a90.zip FreeBSD-src-ebb726ec45c12268b6b931aa636809cc9cb99a90.tar.gz |
Reviewed by: julian with quick glances by bruce and others
Submitted by: terry (terry lambert)
This is a composite of 3 patch sets submitted by terry.
they are:
New low-level init code that supports loadbal modules better
some cleanups in the namei code to help terry in 16-bit character support
some changes to the mount-root code to make it a little more
modular..
NOTE: mounting root off cdrom or NFS MIGHT be broken as I haven't been able
to test those cases..
certainly mounting root of disk still works just fine..
mfs should work but is untested. (tomorrows task)
The low level init stuff includes a total rewrite of init_main.c
to make it possible for new modules to have an init phase by simply
adding an entry to a TEXT_SET (or is it DATA_SET) list. thus a new module can
be added to the kernel without editing any other files other than the
'files' file.
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 324 | ||||
-rw-r--r-- | sys/ufs/lfs/lfs_vfsops.c | 118 | ||||
-rw-r--r-- | sys/ufs/mfs/mfs_extern.h | 4 | ||||
-rw-r--r-- | sys/ufs/mfs/mfs_vfsops.c | 266 | ||||
-rw-r--r-- | sys/ufs/ufs/dir.h | 13 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_lookup.c | 50 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 10 |
7 files changed, 515 insertions, 270 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 19c78cf..78cbfda 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94 - * $Id: ffs_vfsops.c,v 1.26 1995/08/06 11:56:42 davidg Exp $ + * $Id: ffs_vfsops.c,v 1.27 1995/08/11 11:31:15 davidg Exp $ */ #include <sys/param.h> @@ -87,85 +87,103 @@ VFS_SET(ufs_vfsops, ufs, MOUNT_UFS, 0); extern u_long nextgennumber; + /* - * Called by main() when ufs is going to be mounted as root. + * ffs_mount + * + * Called when mounting local physical media + * + * PARAMETERS: + * mountroot + * mp mount point structure + * path NULL (flag for root mount!!!) + * data <unused> + * ndp <unused> + * p process (user credentials check [statfs]) + * + * mount + * mp mount point structure + * path path to mount point + * data pointer to argument struct in user space + * ndp mount point namei() return (used for + * credentials on reload), reused to look + * up block device. + * p process (user credentials check) + * + * RETURNS: 0 Success + * !0 error number (errno.h) + * + * LOCK STATE: + * + * ENTRY + * mount point is locked + * EXIT + * mount point is locked * - * Name is updated by mount(8) after booting. + * NOTES: + * A NULL path can be used for a flag since the mount + * system call will fail with EFAULT in copyinstr in + * namei() if it is a genuine NULL from the user. */ -#define ROOTNAME "root_device" - int -ffs_mountroot() +ffs_mount( mp, path, data, ndp, p) + register struct mount *mp; /* mount struct pointer*/ + char *path; /* path to mount point*/ + caddr_t data; /* arguments to FS specific mount*/ + struct nameidata *ndp; /* mount point credentials*/ + struct proc *p; /* process requesting mount*/ { + u_int size; + int err = 0; + struct vnode *devvp; + + struct ufs_args args; + struct ufsmount *ump = 0; register struct fs *fs; - register struct mount *mp; - struct proc *p = curproc; /* XXX */ - struct ufsmount *ump; - u_int size; - int error; + int flags; /* - * Get vnode for rootdev. + * Use NULL path to flag a root mount */ - if (bdevvp(rootdev, &rootvp)) - panic("ffs_mountroot: can't setup bdevvp for root"); - - 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; - error = ffs_mountfs(rootvp, mp, p); - if (error) { - free(mp, M_MOUNT); - return (error); - } - error = vfs_lock(mp); - if (error) { - (void)ffs_unmount(mp, 0, p); - free(mp, M_MOUNT); - return (error); + if( path == NULL) { + /* + *** + * Mounting root file system + *** + */ + + /* Get vnode for root device*/ + if( bdevvp( rootdev, &rootvp)) + panic("ffs_mountroot: can't setup bdevvp for root"); + + /* + * FS specific handling + */ + mp->mnt_flag |= MNT_RDONLY; /* XXX globally applicable?*/ + + /* + * Attempt mount + */ + if( ( err = ffs_mountfs(rootvp, mp, p)) != 0) { + /* fs specific cleanup (if any)*/ + goto error_1; + } + + goto dostatfs; /* success*/ + } - CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); - mp->mnt_flag |= MNT_ROOTFS; - mp->mnt_vnodecovered = NULLVP; - 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)ffs_statfs(mp, &mp->mnt_stat, p); - vfs_unlock(mp); - inittodr(fs->fs_time); - return (0); -} -/* - * VFS Operations. - * - * mount system call - */ -int -ffs_mount(mp, path, data, ndp, p) - register struct mount *mp; - char *path; - caddr_t data; - struct nameidata *ndp; - struct proc *p; -{ - struct vnode *devvp; - struct ufs_args args; - struct ufsmount *ump = 0; - register struct fs *fs; - u_int size; - int error, flags; + /* + *** + * Mounting non-root file system or updating a file system + *** + */ + + /* copy in user arguments*/ + err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); + if (err) + goto error_1; /* can't get arguments*/ - error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); - if (error) - return (error); /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. @@ -173,20 +191,23 @@ ffs_mount(mp, path, data, ndp, p) if (mp->mnt_flag & MNT_UPDATE) { ump = VFSTOUFS(mp); fs = ump->um_fs; - error = 0; + err = 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); + if (vfs_busy(mp)) { + err = EBUSY; + goto error_1; + } + err = ffs_flushfiles(mp, flags, p); vfs_unbusy(mp); } - if (!error && (mp->mnt_flag & MNT_RELOAD)) - error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); - if (error) - return (error); + if (!err && (mp->mnt_flag & MNT_RELOAD)) + err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); + if (err) { + goto error_1; + } if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { if (!fs->fs_clean) { if (mp->mnt_flag & MNT_FORCE) { @@ -194,7 +215,8 @@ ffs_mount(mp, path, data, ndp, p) } else { printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck.\n", fs->fs_fsmnt); - return (EPERM); + err = EPERM; + goto error_1; } } fs->fs_ronly = 0; @@ -203,56 +225,117 @@ ffs_mount(mp, path, data, ndp, p) fs->fs_clean = 0; ffs_sbupdate(ump, MNT_WAIT); } + /* if not updating name...*/ if (args.fspec == 0) { /* - * Process export requests. + * Process export requests. Jumping to "success" + * will return the vfs_export() error code. */ - return (vfs_export(mp, &ump->um_export, &args.export)); + err = vfs_export(mp, &ump->um_export, &args.export); + goto success; } } + /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); - error = namei(ndp); - if (error) - return (error); + err = namei(ndp); + if (err) { + /* can't get devvp!*/ + 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 ((mp->mnt_flag & MNT_UPDATE) == 0) - error = ffs_mountfs(devvp, mp, p); - else { + if (mp->mnt_flag & MNT_UPDATE) { + /* + ******************** + * UPDATE + ******************** + */ + if (devvp != ump->um_devvp) - error = EINVAL; /* needs translation */ + 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 { + /* + ******************** + * NEW MOUNT + ******************** + */ + + /* + * 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 (error) { - vrele(devvp); - return (error); + if (err) { + goto error_2; } - 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((caddr_t)fs->fs_fsmnt, (caddr_t)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); - (void)ffs_statfs(mp, &mp->mnt_stat, p); - return (0); + +dostatfs: + /* + * 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); + + goto success; + + +error_2: /* error with devvp held*/ + + /* release devvp before failing*/ + vrele(devvp); + +error_1: /* no state to back out*/ + +success: + return( err); } + /* * Reload all incore data for a filesystem (used after running fsck on * the root filesystem and finding things to fix). The filesystem must @@ -267,8 +350,8 @@ ffs_mount(mp, path, data, ndp, p) * 6) re-read inode data for all active vnodes. */ int -ffs_reload(mountp, cred, p) - register struct mount *mountp; +ffs_reload(mp, cred, p) + register struct mount *mp; struct ucred *cred; struct proc *p; { @@ -279,12 +362,12 @@ ffs_reload(mountp, cred, p) struct fs *fs; int i, blks, size, error; - if ((mountp->mnt_flag & MNT_RDONLY) == 0) + if ((mp->mnt_flag & MNT_RDONLY) == 0) return (EINVAL); /* * Step 1: invalidate all cached meta-data. */ - devvp = VFSTOUFS(mountp)->um_devvp; + devvp = VFSTOUFS(mp)->um_devvp; if (vinvalbuf(devvp, 0, cred, p, 0, 0)) panic("ffs_reload: dirty1"); /* @@ -299,7 +382,7 @@ ffs_reload(mountp, cred, p) brelse(bp); return (EIO); /* XXX needs translation */ } - fs = VFSTOUFS(mountp)->um_fs; + fs = VFSTOUFS(mp)->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); @@ -325,7 +408,7 @@ ffs_reload(mountp, cred, p) brelse(bp); } loop: - for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { + for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { nvp = vp->v_mntvnodes.le_next; /* * Step 4: invalidate all inactive vnodes. @@ -356,7 +439,7 @@ loop: ino_to_fsbo(fs, ip->i_number)); brelse(bp); vput(vp); - if (vp->v_mount != mountp) + if (vp->v_mount != mp) goto loop; } return (0); @@ -380,6 +463,7 @@ ffs_mountfs(devvp, mp, p) int havepart = 0, blks; int error, i, size; int ronly; + u_int strsize; /* * Disallow multiple mounts of the same device. @@ -477,6 +561,24 @@ ffs_mountfs(devvp, mp, p) devvp->v_specflags |= SI_MOUNTEDON; ffs_oldfscompat(fs); ffs_vmlimits(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( 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; + } if (ronly == 0) ffs_sbupdate(ump, MNT_WAIT); return (0); diff --git a/sys/ufs/lfs/lfs_vfsops.c b/sys/ufs/lfs/lfs_vfsops.c index e571dcd..80fb731 100644 --- a/sys/ufs/lfs/lfs_vfsops.c +++ b/sys/ufs/lfs/lfs_vfsops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)lfs_vfsops.c 8.7 (Berkeley) 4/16/94 - * $Id: lfs_vfsops.c,v 1.10 1995/03/16 18:16:48 bde Exp $ + * $Id: lfs_vfsops.c,v 1.11 1995/03/19 14:29:20 davidg Exp $ */ #include <sys/param.h> @@ -78,16 +78,45 @@ struct vfsops lfs_vfsops = { VFS_SET(lfs_vfsops, lfs, MOUNT_LFS, 0); -int -lfs_mountroot() -{ - panic("lfs_mountroot"); /* XXX -- implement */ -} /* - * VFS Operations. + * lfs_mount + * + * Called when mounting local physical media + * + * PARAMETERS: + * mountroot + * mp mount point structure + * path NULL (flag for root mount!!!) + * data <unused> + * ndp <unused> + * p process (user credentials check [statfs]) + * + * mount + * mp mount point structure + * path path to mount point + * data pointer to argument struct in user space + * ndp mount point namei() return (used for + * credentials on reload), reused to look + * up block device. + * p process (user credentials check) + * + * RETURNS: 0 Success + * !0 error number (errno.h) + * + * LOCK STATE: * - * mount system call + * ENTRY + * mount point is locked + * EXIT + * mount point is locked + * + * NOTES: + * A NULL path can be used for a flag since the mount + * system call will fail with EFAULT in copyinstr in + * namei() if it is a genuine NULL from the user. + * + * Root mounts are not currently supported. */ int lfs_mount(mp, path, data, ndp, p) @@ -102,14 +131,37 @@ lfs_mount(mp, path, data, ndp, p) struct ufsmount *ump = 0; register struct lfs *fs; /* LFS */ u_int size; - int error; + int err; - if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) - return (error); + /* + * Use NULL path to flag a root mount + */ + if( path == NULL) { + /* + *** + * Mounting root file system + *** + */ + + /* XXX -- implement*/ + panic("lfs_mountroot: can't setup bdevvp for root"); + } + + /* + *** + * Mounting non-root file system or updating a file system + *** + */ + + /* copy in user arguments*/ + if (err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) + goto error_1; /* Until LFS can do NFS right. XXX */ - if (args.export.ex_flags & MNT_EXPORTED) - return (EINVAL); + if (args.export.ex_flags & MNT_EXPORTED) { + err = EINVAL; + goto error_1; + } /* * If updating, check whether changing from read-only to @@ -128,9 +180,11 @@ lfs_mount(mp, path, data, ndp, p) #endif if (args.fspec == 0) { /* - * Process export requests. + * Process export requests. Jumping to "success" + * will return the vfs_export() error code. */ - return (vfs_export(mp, &ump->um_export, &args.export)); + err = vfs_export(mp, &ump->um_export, &args.export); + goto success; } } /* @@ -138,28 +192,27 @@ lfs_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)) - return (error); + if (err = namei(ndp)) + 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 ((mp->mnt_flag & MNT_UPDATE) == 0) - error = lfs_mountfs(devvp, mp, p); /* LFS */ + err = lfs_mountfs(devvp, mp, p); /* LFS */ else { if (devvp != ump->um_devvp) - error = EINVAL; /* needs translation */ + err = EINVAL; /* needs translation */ else vrele(devvp); } - if (error) { - vrele(devvp); - return (error); + if (err) { + goto error_2; } ump = VFSTOUFS(mp); fs = ump->um_lfs; /* LFS */ @@ -182,7 +235,18 @@ lfs_mount(mp, path, data, ndp, p) bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); (void) lfs_statfs(mp, &mp->mnt_stat, p); #endif - return (0); + + + +error_2: /* error with devvp held*/ + + /* release devvp before failing*/ + vrele(devvp); + +error_1: /* no state to back out*/ + +success: + return( err); } /* diff --git a/sys/ufs/mfs/mfs_extern.h b/sys/ufs/mfs/mfs_extern.h index fa51177..887c3d7 100644 --- a/sys/ufs/mfs/mfs_extern.h +++ b/sys/ufs/mfs/mfs_extern.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)mfs_extern.h 8.1 (Berkeley) 6/11/93 - * $Id: mfs_extern.h,v 1.2 1994/08/02 07:54:42 davidg Exp $ + * $Id: mfs_extern.h,v 1.3 1994/08/21 07:16:10 paul Exp $ */ #ifndef _UFS_MFS_MFS_EXTERN_H_ @@ -56,6 +56,8 @@ int mfs_init __P((void)); int mfs_ioctl __P((struct vop_ioctl_args *)); int mfs_mount __P((struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct proc *p)); +int mfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); +int mfs_mountroot __P((void)); int mfs_open __P((struct vop_open_args *)); int mfs_print __P((struct vop_print_args *)); /* XXX */ int mfs_start __P((struct mount *mp, int flags, struct proc *p)); diff --git a/sys/ufs/mfs/mfs_vfsops.c b/sys/ufs/mfs/mfs_vfsops.c index cc62f94..3213cea 100644 --- a/sys/ufs/mfs/mfs_vfsops.c +++ b/sys/ufs/mfs/mfs_vfsops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)mfs_vfsops.c 8.4 (Berkeley) 4/16/94 - * $Id: mfs_vfsops.c,v 1.10 1995/08/11 11:31:18 davidg Exp $ + * $Id: mfs_vfsops.c,v 1.11 1995/08/20 10:26:00 davidg Exp $ */ #include <sys/param.h> @@ -40,11 +40,17 @@ #include <sys/kernel.h> #include <sys/proc.h> #include <sys/buf.h> +#include <sys/mbuf.h> +#include <sys/file.h> +#include <sys/disklabel.h> +#include <sys/ioctl.h> #include <sys/mount.h> #include <sys/signalvar.h> #include <sys/vnode.h> #include <sys/malloc.h> +#include <miscfs/specfs/specdev.h> + #include <ufs/ufs/quota.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufsmount.h> @@ -82,74 +88,14 @@ struct vfsops mfs_vfsops = { VFS_SET(mfs_vfsops, mfs, MOUNT_MFS, 0); -/* - * Called by main() when mfs is going to be mounted as root. - * - * Name is updated by mount(8) after booting. - */ -#define ROOTNAME "mfs_root" - -int -mfs_mountroot() -{ - register struct fs *fs; - register struct mount *mp; - struct proc *p = curproc; /* XXX */ - struct ufsmount *ump; - struct mfsnode *mfsp; - u_int size; - int error; - - /* - * Get vnode for rootdev. - */ - if (bdevvp(rootdev, &rootvp)) - panic("mfs_mountroot: can't setup bdevvp for rootdev"); - - mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); - bzero((char *)mp, (u_long)sizeof(struct mount)); - mp->mnt_op = &mfs_vfsops; - mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); - rootvp->v_data = mfsp; - rootvp->v_op = mfs_vnodeop_p; - rootvp->v_tag = VT_MFS; - mfsp->mfs_baseoff = mfs_rootbase; - mfsp->mfs_size = mfs_rootsize; - mfsp->mfs_vnode = rootvp; - mfsp->mfs_pid = p->p_pid; - mfsp->mfs_buflist = (struct buf *)0; - if (error = ffs_mountfs(rootvp, mp, p)) { - free(mp, M_MOUNT); - free(mfsp, M_MFSNODE); - return (error); - } - if (error = vfs_lock(mp)) { - (void)ffs_unmount(mp, 0, p); - free(mp, M_MOUNT); - free(mfsp, M_MFSNODE); - return (error); - } - CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); - mp->mnt_flag |= MNT_ROOTFS; - mp->mnt_vnodecovered = NULLVP; - 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)ffs_statfs(mp, &mp->mnt_stat, p); - vfs_unlock(mp); - inittodr((time_t)0); - return (0); -} +int vfs_mountroot __P((caddr_t)); /* XXX goes away*/ /* * This is called early in boot to set the base address and size * of the mini-root. + * + * XXX THIS IS A DESIGN ERROR; THIS CODE SHOULD BE MOVED INTO + * XXX THE ROOT MOUNT CODE IN "mfs_mount"!!! */ int mfs_initminiroot(base) @@ -161,7 +107,8 @@ mfs_initminiroot(base) if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) return (0); - mountroot = mfs_mountroot; + mountroot = vfs_mountroot; /* XXX goes away*/ + mountrootvfsops = &mfs_vfsops; mfs_rootbase = base; mfs_rootsize = fs->fs_fsize * fs->fs_size; rootdev = makedev(255, mfs_minor++); @@ -169,10 +116,43 @@ mfs_initminiroot(base) return (mfs_rootsize); } + /* - * VFS Operations. + * mfs_mount + * + * Called when mounting local physical media + * + * PARAMETERS: + * mountroot + * mp mount point structure + * path NULL (flag for root mount!!!) + * data <unused> + * ndp <unused> + * p process (user credentials check [statfs]) + * + * mount + * mp mount point structure + * path path to mount point + * data pointer to argument struct in user space + * ndp mount point namei() return (used for + * credentials on reload), reused to look + * up block device. + * p process (user credentials check) * - * mount system call + * RETURNS: 0 Success + * !0 error number (errno.h) + * + * LOCK STATE: + * + * ENTRY + * mount point is locked + * EXIT + * mount point is locked + * + * NOTES: + * A NULL path can be used for a flag since the mount + * system call will fail with EFAULT in copyinstr in + * namei() if it is a genuine NULL from the user. */ /* ARGSUSED */ int @@ -189,40 +169,103 @@ mfs_mount(mp, path, data, ndp, p) register struct fs *fs; register struct mfsnode *mfsp; u_int size; - int flags, error; + int flags, err; + + /* + * Use NULL path to flag a root mount + */ + if( path == NULL) { + /* + *** + * Mounting root file system + *** + */ - if (error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) - return (error); + /* Get vnode for root device*/ + if( bdevvp( rootdev, &rootvp)) + panic("mfs_mountroot: can't setup bdevvp for rootdev"); + + /* + * FS specific handling + */ + mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); + rootvp->v_data = mfsp; + rootvp->v_op = mfs_vnodeop_p; + rootvp->v_tag = VT_MFS; + mfsp->mfs_baseoff = mfs_rootbase; + mfsp->mfs_size = mfs_rootsize; + mfsp->mfs_vnode = rootvp; + mfsp->mfs_pid = p->p_pid; + mfsp->mfs_buflist = (struct buf *)0; + + /* + * Attempt mount + */ + if( (err = ffs_mountfs(rootvp, mp, p)) != 0 ) { + /* fs specific cleanup (if any)*/ + rootvp->v_data = NULL; + free(mfsp, M_MFSNODE); + goto error_1; + } + + goto dostatfs; /* success*/ + } + + /* + *** + * Mounting non-root file system or updating a file system + *** + */ + + /* copy in user arguments*/ + if (err = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) + goto error_1; /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { + /* + ******************** + * UPDATE + ******************** + */ ump = VFSTOUFS(mp); fs = ump->um_fs; 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); + if (vfs_busy(mp)) { + err = EBUSY; + goto error_1; + } + err = ffs_flushfiles(mp, flags, p); vfs_unbusy(mp); - if (error) - return (error); + if (err) + goto error_1; } if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) fs->fs_ronly = 0; #ifdef EXPORTMFS - if (args.fspec == 0) - return (vfs_export(mp, &ump->um_export, &args.export)); + /* if not updating name...*/ + if (args.fspec == 0) { + /* + * Process export requests. Jumping to "success" + * will return the vfs_export() error code. + */ + err = vfs_export(mp, &ump->um_export, &args.export); + goto success; + } #endif - return (0); + + /* XXX MFS does not support name updating*/ + goto success; } - error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp); - if (error) - return (error); + err = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp); + if (err) + goto error_1; devvp->v_type = VBLK; if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0)) panic("mfs_mount: dup dev"); @@ -233,24 +276,55 @@ mfs_mount(mp, path, data, ndp, p) mfsp->mfs_vnode = devvp; mfsp->mfs_pid = p->p_pid; mfsp->mfs_buflist = (struct buf *)0; - if (error = ffs_mountfs(devvp, mp, p)) { + + /* + * 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); + + if (err = ffs_mountfs(devvp, mp, p)) { mfsp->mfs_buflist = (struct buf *)-1; - vrele(devvp); - return (error); + goto error_2; } - 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((caddr_t)fs->fs_fsmnt, (caddr_t)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); - (void) mfs_statfs(mp, &mp->mnt_stat, p); - return (0); + +dostatfs: + /* + * 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); + + goto success; + +error_2: /* error with devvp held*/ + + /* release devvp before failing*/ + vrele(devvp); + +error_1: /* no state to back out*/ + +success: + return( err); } + int mfs_pri = PWAIT | PCATCH; /* XXX prob. temp */ /* diff --git a/sys/ufs/ufs/dir.h b/sys/ufs/ufs/dir.h index f18eca8..3eae47a 100644 --- a/sys/ufs/ufs/dir.h +++ b/sys/ufs/ufs/dir.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)dir.h 8.2 (Berkeley) 1/21/94 - * $Id: dir.h,v 1.2 1994/08/02 07:54:48 davidg Exp $ + * $Id: dir.h,v 1.3 1994/08/21 07:16:14 paul Exp $ */ #ifndef _UFS_UFS_DIR_H_ @@ -101,15 +101,18 @@ struct direct { * the directory entry. This requires the amount of space in struct direct * without the d_name field, plus enough space for the name with a terminating * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + * + * */ +#define DIRECTSIZ(namlen) \ + (((int)&((struct direct *)0)->d_name + \ + ((namlen)+1)*sizeof(((struct direct *)0)->d_name[0]) + 3) & ~3) #if (BYTE_ORDER == LITTLE_ENDIAN) #define DIRSIZ(oldfmt, dp) \ - ((oldfmt) ? \ - ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_type+1 + 3) &~ 3)) : \ - ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))) + ((oldfmt) ? DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen)) #else #define DIRSIZ(oldfmt, dp) \ - ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) + DIRECTSIZ((dp)->d_namlen) #endif #define OLDDIRFMT 1 #define NEWDIRFMT 0 diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index 2994c5c..045de4b 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94 - * $Id: ufs_lookup.c,v 1.3 1994/10/08 06:57:26 phk Exp $ + * $Id: ufs_lookup.c,v 1.4 1995/07/29 11:43:23 bde Exp $ */ #include <sys/param.h> @@ -59,7 +59,8 @@ int dirchk = 1; int dirchk = 0; #endif -#define FSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0) +/* true if old FS format...*/ +#define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0) /* * Convert a component of a pathname into a pointer to a locked inode. @@ -210,8 +211,7 @@ ufs_lookup(ap) if ((nameiop == CREATE || nameiop == RENAME) && (flags & ISLASTCN)) { slotstatus = NONE; - slotneeded = (sizeof(struct direct) - MAXNAMLEN + - cnp->cn_namelen + 3) &~ 3; + slotneeded = DIRECTSIZ(cnp->cn_namelen); } /* @@ -295,7 +295,7 @@ searchloop: int size = ep->d_reclen; if (ep->d_ino != 0) - size -= DIRSIZ(FSFMT(vdp), ep); + size -= DIRSIZ(OFSFMT(vdp), ep); if (size > 0) { if (size >= slotneeded) { slotstatus = FOUND; @@ -319,10 +319,10 @@ searchloop: */ if (ep->d_ino) { # if (BYTE_ORDER == LITTLE_ENDIAN) - if (vdp->v_mount->mnt_maxsymlinklen > 0) - namlen = ep->d_namlen; - else + if (OFSFMT(vdp)) namlen = ep->d_type; + else + namlen = ep->d_namlen; # else namlen = ep->d_namlen; # endif @@ -426,9 +426,9 @@ found: * Check that directory length properly reflects presence * of this entry. */ - if (entryoffsetinblock + DIRSIZ(FSFMT(vdp), ep) > dp->i_size) { + if (entryoffsetinblock + DIRSIZ(OFSFMT(vdp), ep) > dp->i_size) { ufs_dirbad(dp, dp->i_offset, "i_size too small"); - dp->i_size = entryoffsetinblock + DIRSIZ(FSFMT(vdp), ep); + dp->i_size = entryoffsetinblock + DIRSIZ(OFSFMT(vdp), ep); dp->i_flag |= IN_CHANGE | IN_UPDATE; } @@ -604,16 +604,16 @@ ufs_dirbadentry(dp, ep, entryoffsetinblock) int namlen; # if (BYTE_ORDER == LITTLE_ENDIAN) - if (dp->v_mount->mnt_maxsymlinklen > 0) - namlen = ep->d_namlen; - else + if (OFSFMT(dp)) namlen = ep->d_type; + else + namlen = ep->d_namlen; # else namlen = ep->d_namlen; # endif if ((ep->d_reclen & 0x3) != 0 || ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) || - ep->d_reclen < DIRSIZ(FSFMT(dp), ep) || namlen > MAXNAMLEN) { + ep->d_reclen < DIRSIZ(OFSFMT(dp), ep) || namlen > MAXNAMLEN) { /*return (1); */ printf("First bad\n"); goto bad; @@ -663,7 +663,7 @@ ufs_direnter(ip, dvp, cnp) newdir.d_ino = ip->i_number; newdir.d_namlen = cnp->cn_namelen; bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1); - if (dvp->v_mount->mnt_maxsymlinklen > 0) + if (!OFSFMT(dvp)) newdir.d_type = IFTODT(ip->i_mode); else { newdir.d_type = 0; @@ -673,7 +673,7 @@ ufs_direnter(ip, dvp, cnp) newdir.d_type = tmp; } # endif } - newentrysize = DIRSIZ(FSFMT(dvp), &newdir); + newentrysize = DIRSIZ(OFSFMT(dvp), &newdir); if (dp->i_count == 0) { /* * If dp->i_count is 0, then namei could find no @@ -737,7 +737,7 @@ ufs_direnter(ip, dvp, cnp) * space. */ ep = (struct direct *)dirbuf; - dsize = DIRSIZ(FSFMT(dvp), ep); + dsize = DIRSIZ(OFSFMT(dvp), ep); spacefree = ep->d_reclen - dsize; for (loc = ep->d_reclen; loc < dp->i_count; ) { nep = (struct direct *)(dirbuf + loc); @@ -749,7 +749,7 @@ ufs_direnter(ip, dvp, cnp) /* overwrite; nothing there; header is ours */ spacefree += dsize; } - dsize = DIRSIZ(FSFMT(dvp), nep); + dsize = DIRSIZ(OFSFMT(dvp), nep); spacefree += nep->d_reclen - dsize; loc += nep->d_reclen; bcopy((caddr_t)nep, (caddr_t)ep, dsize); @@ -846,7 +846,7 @@ ufs_dirrewrite(dp, ip, cnp) if (error) return (error); ep->d_ino = ip->i_number; - if (vdp->v_mount->mnt_maxsymlinklen > 0) + if (!OFSFMT(vdp)) ep->d_type = IFTODT(ip->i_mode); error = VOP_BWRITE(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; @@ -891,10 +891,10 @@ ufs_dirempty(ip, parentino, cred) continue; /* accept only "." and ".." */ # if (BYTE_ORDER == LITTLE_ENDIAN) - if (ITOV(ip)->v_mount->mnt_maxsymlinklen > 0) - namlen = dp->d_namlen; - else + if (OFSFMT(ITOV(ip))) namlen = dp->d_type; + else + namlen = dp->d_namlen; # else namlen = dp->d_namlen; # endif @@ -951,10 +951,10 @@ ufs_checkpath(source, target, cred) if (error != 0) break; # if (BYTE_ORDER == LITTLE_ENDIAN) - if (vp->v_mount->mnt_maxsymlinklen > 0) - namlen = dirbuf.dotdot_namlen; - else + if (OFSFMT(vp)) namlen = dirbuf.dotdot_type; + else + namlen = dirbuf.dotdot_namlen; # else namlen = dirbuf.dotdot_namlen; # endif diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 37000cc..371cd06 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)ufs_vnops.c 8.10 (Berkeley) 4/1/94 - * $Id: ufs_vnops.c,v 1.25 1995/06/28 07:06:55 davidg Exp $ + * $Id: ufs_vnops.c,v 1.26 1995/08/01 18:51:02 davidg Exp $ */ #include <sys/param.h> @@ -1123,12 +1123,12 @@ out: * A virgin directory (no blushing please). */ static struct dirtemplate mastertemplate = { - 0, 12, DT_DIR, 1, ".", - 0, DIRBLKSIZ - 12, DT_DIR, 2, ".." + 0, 12, DT_DIR, 1, { '.', 0 }, + 0, DIRBLKSIZ - 12, DT_DIR, 2, { '.', '.', 0 } }; static struct odirtemplate omastertemplate = { - 0, 12, 1, ".", - 0, DIRBLKSIZ - 12, 2, ".." + 0, 12, 1, { '.', 0 }, + 0, DIRBLKSIZ - 12, 2, { '.', '.', 0 } }; /* |