Index: sys/dev/md/md.c =================================================================== --- sys/dev/md/md.c +++ sys/dev/md/md.c @@ -116,21 +116,6 @@ #define MD_NSECT (10000 * 2) #endif -struct md_req { - unsigned md_unit; /* unit number */ - enum md_types md_type; /* type of disk */ - off_t md_mediasize; /* size of disk in bytes */ - unsigned md_sectorsize; /* sectorsize */ - unsigned md_options; /* options */ - int md_fwheads; /* firmware heads */ - int md_fwsectors; /* firmware sectors */ - char *md_file; /* pathname of file to mount */ - enum uio_seg md_file_seg; /* location of md_file */ - char *md_label; /* label of the device (userspace) */ - int *md_units; /* pointer to units array (kernel) */ - size_t md_units_nitems; /* items in md_units array */ -}; - #ifdef COMPAT_FREEBSD32 struct md_ioctl32 { unsigned md_version; @@ -1933,10 +1918,6 @@ return (EINVAL); MD_IOCTL2REQ(mdio, &mdr); mdr.md_file = mdio->md_file; - mdr.md_file_seg = UIO_USERSPACE; - /* If the file is adjacent to the md_ioctl it's in kernel. */ - if ((void *)mdio->md_file == (void *)(mdio + 1)) - mdr.md_file_seg = UIO_SYSSPACE; mdr.md_label = mdio->md_label; break; } @@ -2101,6 +2082,8 @@ md_vnode_pbuf_freecnt = nswbuf / 10; status_dev = make_dev(&mdctl_cdevsw, INT_MAX, UID_ROOT, GID_WHEEL, 0600, MDCTL_NAME); + kern_mdattach_p = &kern_mdattach; + kern_mddetach_p = &kern_mddetach; g_topology_lock(); } Index: sys/kern/vfs_mountroot.c =================================================================== --- sys/kern/vfs_mountroot.c +++ sys/kern/vfs_mountroot.c @@ -107,6 +107,15 @@ char *rootdevnames[2] = {NULL, NULL}; +/* + * Hooks into md(4) for mount.conf(8)'s .md support. Stored here as + * this is the only place they are used. Great care should be taken + * when expanding use as crashes may occur if md(4) is unloaded during + * calls. + */ +int (*kern_mdattach_p)(struct thread *td, struct md_req *mdr); +int (*kern_mddetach_p)(struct thread *td, struct md_req *mdr); + struct mtx root_holds_mtx; MTX_SYSINIT(root_holds, &root_holds_mtx, "root_holds", MTX_DEF); @@ -546,70 +555,59 @@ { struct stat sb; struct thread *td; - struct md_ioctl *mdio; - char *path, *tok; - int error, fd, len; + struct md_req mdr; + char *path; + int error; + + if (kern_mdattach_p == NULL || kern_mddetach_p == NULL) + return (ENOENT); td = curthread; - error = parse_token(conf, &tok); + error = parse_token(conf, &path); if (error) return (error); - len = strlen(tok); - mdio = malloc(sizeof(*mdio) + len + 1, M_TEMP, M_WAITOK | M_ZERO); - path = (void *)(mdio + 1); - bcopy(tok, path, len); - free(tok, M_TEMP); - /* Get file status. */ error = kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &sb, NULL); if (error) goto out; - /* Open /dev/mdctl so that we can attach/detach. */ - error = kern_openat(td, AT_FDCWD, "/dev/" MDCTL_NAME, UIO_SYSSPACE, - O_RDWR, 0); - if (error) - goto out; - - fd = td->td_retval[0]; - mdio->md_version = MDIOVERSION; - mdio->md_type = MD_VNODE; + bzero(&mdr, sizeof(mdr)); + mdr.md_type = MD_VNODE; if (root_mount_mddev != -1) { - mdio->md_unit = root_mount_mddev; - error = kern_ioctl(td, fd, MDIOCDETACH, (void *)mdio); + mdr.md_unit = root_mount_mddev; + error = kern_mddetach_p(td, &mdr); /* Ignore errors. We don't care. */ root_mount_mddev = -1; } - mdio->md_file = (void *)(mdio + 1); - mdio->md_options = MD_AUTOUNIT | MD_READONLY; - mdio->md_mediasize = sb.st_size; - mdio->md_unit = 0; - error = kern_ioctl(td, fd, MDIOCATTACH, (void *)mdio); + mdr.md_file = path; + mdr.md_file_seg = UIO_SYSSPACE; + mdr.md_options = MD_AUTOUNIT | MD_READONLY; + mdr.md_mediasize = sb.st_size; + mdr.md_unit = 0; + error = kern_mdattach_p(td, &mdr); if (error) goto out; - if (mdio->md_unit > 9) { + if (mdr.md_unit > 9) { printf("rootmount: too many md units\n"); - mdio->md_file = NULL; - mdio->md_options = 0; - mdio->md_mediasize = 0; - error = kern_ioctl(td, fd, MDIOCDETACH, (void *)mdio); + mdr.md_file = NULL; + mdr.md_options = 0; + mdr.md_mediasize = 0; + error = kern_mddetach_p(td, &mdr); /* Ignore errors. We don't care. */ error = ERANGE; goto out; } - root_mount_mddev = mdio->md_unit; - printf(MD_NAME "%u attached to %s\n", root_mount_mddev, mdio->md_file); - - error = kern_close(td, fd); + root_mount_mddev = mdr.md_unit; + printf(MD_NAME "%u attached to %s\n", root_mount_mddev, path); - out: - free(mdio, M_TEMP); +out: + free(path, M_TEMP); return (error); } Index: sys/sys/mdioctl.h =================================================================== --- sys/sys/mdioctl.h +++ sys/sys/mdioctl.h @@ -45,6 +45,10 @@ #ifndef _SYS_MDIOCTL_H_ #define _SYS_MDIOCTL_H_ +#ifdef _KERNEL +#include +#endif + enum md_types {MD_MALLOC, MD_PRELOAD, MD_VNODE, MD_SWAP, MD_NULL}; /* @@ -93,4 +97,24 @@ #define MD_ASYNC 0x40 /* Asynchronous mode */ #define MD_VERIFY 0x80 /* Open file with O_VERIFY (vnode only) */ +#ifdef _KERNEL +struct md_req { + unsigned md_unit; /* unit number */ + enum md_types md_type; /* type of disk */ + off_t md_mediasize; /* size of disk in bytes */ + unsigned md_sectorsize; /* sectorsize */ + unsigned md_options; /* options */ + int md_fwheads; /* firmware heads */ + int md_fwsectors; /* firmware sectors */ + char *md_file; /* pathname of file to mount */ + enum uio_seg md_file_seg; /* location of md_file */ + char *md_label; /* label of the device (userspace) */ + int *md_units; /* pointer to units array (kernel) */ + size_t md_units_nitems; /* items in md_units array */ +}; + +extern int (*kern_mdattach_p)(struct thread *td, struct md_req *mdr); +extern int (*kern_mddetach_p)(struct thread *td, struct md_req *mdr); +#endif + #endif /* _SYS_MDIOCTL_H_*/