Add a request structure and make the implementation use it.
This allows compatibility translation to take place on the stack (md_ioctl is too big) and is more suitable as a public interface within the kernel than the kern_ioctl interface. Except for the initialization of the md_req from the md_ioctl (including detection of kernel md_file pointers) and the updating of the md_ioctl prior to return, this is a mechanical replacment of md_ioctl and mdio with md_req and mdr. Reviewed by: markj, cem, kib (assorted versions) Obtained from: CheriBSD Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D14704
This commit is contained in:
parent
d5925949ac
commit
3e372bcfc3
272
sys/dev/md/md.c
272
sys/dev/md/md.c
@ -114,6 +114,21 @@
|
|||||||
#define MD_NSECT (10000 * 2)
|
#define MD_NSECT (10000 * 2)
|
||||||
#endif
|
#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 */
|
||||||
|
};
|
||||||
|
|
||||||
static MALLOC_DEFINE(M_MD, "md_disk", "Memory Disk");
|
static MALLOC_DEFINE(M_MD, "md_disk", "Memory Disk");
|
||||||
static MALLOC_DEFINE(M_MDSECT, "md_sectors", "Memory Disk Sectors");
|
static MALLOC_DEFINE(M_MDSECT, "md_sectors", "Memory Disk Sectors");
|
||||||
|
|
||||||
@ -1285,29 +1300,29 @@ mdinit(struct md_s *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mdcreate_malloc(struct md_s *sc, struct md_ioctl *mdio)
|
mdcreate_malloc(struct md_s *sc, struct md_req *mdr)
|
||||||
{
|
{
|
||||||
uintptr_t sp;
|
uintptr_t sp;
|
||||||
int error;
|
int error;
|
||||||
off_t u;
|
off_t u;
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
if (mdio->md_options & ~(MD_AUTOUNIT | MD_COMPRESS | MD_RESERVE))
|
if (mdr->md_options & ~(MD_AUTOUNIT | MD_COMPRESS | MD_RESERVE))
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
if (mdio->md_sectorsize != 0 && !powerof2(mdio->md_sectorsize))
|
if (mdr->md_sectorsize != 0 && !powerof2(mdr->md_sectorsize))
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
/* Compression doesn't make sense if we have reserved space */
|
/* Compression doesn't make sense if we have reserved space */
|
||||||
if (mdio->md_options & MD_RESERVE)
|
if (mdr->md_options & MD_RESERVE)
|
||||||
mdio->md_options &= ~MD_COMPRESS;
|
mdr->md_options &= ~MD_COMPRESS;
|
||||||
if (mdio->md_fwsectors != 0)
|
if (mdr->md_fwsectors != 0)
|
||||||
sc->fwsectors = mdio->md_fwsectors;
|
sc->fwsectors = mdr->md_fwsectors;
|
||||||
if (mdio->md_fwheads != 0)
|
if (mdr->md_fwheads != 0)
|
||||||
sc->fwheads = mdio->md_fwheads;
|
sc->fwheads = mdr->md_fwheads;
|
||||||
sc->flags = mdio->md_options & (MD_COMPRESS | MD_FORCE);
|
sc->flags = mdr->md_options & (MD_COMPRESS | MD_FORCE);
|
||||||
sc->indir = dimension(sc->mediasize / sc->sectorsize);
|
sc->indir = dimension(sc->mediasize / sc->sectorsize);
|
||||||
sc->uma = uma_zcreate(sc->name, sc->sectorsize, NULL, NULL, NULL, NULL,
|
sc->uma = uma_zcreate(sc->name, sc->sectorsize, NULL, NULL, NULL, NULL,
|
||||||
0x1ff, 0);
|
0x1ff, 0);
|
||||||
if (mdio->md_options & MD_RESERVE) {
|
if (mdr->md_options & MD_RESERVE) {
|
||||||
off_t nsectors;
|
off_t nsectors;
|
||||||
|
|
||||||
nsectors = sc->mediasize / sc->sectorsize;
|
nsectors = sc->mediasize / sc->sectorsize;
|
||||||
@ -1368,19 +1383,15 @@ mdsetcred(struct md_s *sc, struct ucred *cred)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
|
mdcreate_vnode(struct md_s *sc, struct md_req *mdr, struct thread *td)
|
||||||
{
|
{
|
||||||
struct vattr vattr;
|
struct vattr vattr;
|
||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
char *fname;
|
char *fname;
|
||||||
int error, flags;
|
int error, flags;
|
||||||
|
|
||||||
/*
|
fname = mdr->md_file;
|
||||||
* Kernel-originated requests must have the filename appended
|
if (mdr->md_file_seg == UIO_USERSPACE) {
|
||||||
* to the mdio structure to protect against malicious software.
|
|
||||||
*/
|
|
||||||
fname = mdio->md_file;
|
|
||||||
if ((void *)fname != (void *)(mdio + 1)) {
|
|
||||||
error = copyinstr(fname, sc->file, sizeof(sc->file), NULL);
|
error = copyinstr(fname, sc->file, sizeof(sc->file), NULL);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
@ -1391,8 +1402,8 @@ mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
|
|||||||
* If the user specified that this is a read only device, don't
|
* If the user specified that this is a read only device, don't
|
||||||
* set the FWRITE mask before trying to open the backing store.
|
* set the FWRITE mask before trying to open the backing store.
|
||||||
*/
|
*/
|
||||||
flags = FREAD | ((mdio->md_options & MD_READONLY) ? 0 : FWRITE) \
|
flags = FREAD | ((mdr->md_options & MD_READONLY) ? 0 : FWRITE) \
|
||||||
| ((mdio->md_options & MD_VERIFY) ? O_VERIFY : 0);
|
| ((mdr->md_options & MD_VERIFY) ? O_VERIFY : 0);
|
||||||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, sc->file, td);
|
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, sc->file, td);
|
||||||
error = vn_open(&nd, &flags, 0, NULL);
|
error = vn_open(&nd, &flags, 0, NULL);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
@ -1416,13 +1427,13 @@ mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
|
|||||||
nd.ni_vp->v_vflag |= VV_MD;
|
nd.ni_vp->v_vflag |= VV_MD;
|
||||||
VOP_UNLOCK(nd.ni_vp, 0);
|
VOP_UNLOCK(nd.ni_vp, 0);
|
||||||
|
|
||||||
if (mdio->md_fwsectors != 0)
|
if (mdr->md_fwsectors != 0)
|
||||||
sc->fwsectors = mdio->md_fwsectors;
|
sc->fwsectors = mdr->md_fwsectors;
|
||||||
if (mdio->md_fwheads != 0)
|
if (mdr->md_fwheads != 0)
|
||||||
sc->fwheads = mdio->md_fwheads;
|
sc->fwheads = mdr->md_fwheads;
|
||||||
snprintf(sc->ident, sizeof(sc->ident), "MD-DEV%ju-INO%ju",
|
snprintf(sc->ident, sizeof(sc->ident), "MD-DEV%ju-INO%ju",
|
||||||
(uintmax_t)vattr.va_fsid, (uintmax_t)vattr.va_fileid);
|
(uintmax_t)vattr.va_fsid, (uintmax_t)vattr.va_fileid);
|
||||||
sc->flags = mdio->md_options & (MD_FORCE | MD_ASYNC | MD_VERIFY);
|
sc->flags = mdr->md_options & (MD_FORCE | MD_ASYNC | MD_VERIFY);
|
||||||
if (!(flags & FWRITE))
|
if (!(flags & FWRITE))
|
||||||
sc->flags |= MD_READONLY;
|
sc->flags |= MD_READONLY;
|
||||||
sc->vnode = nd.ni_vp;
|
sc->vnode = nd.ni_vp;
|
||||||
@ -1488,7 +1499,7 @@ mddestroy(struct md_s *sc, struct thread *td)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mdresize(struct md_s *sc, struct md_ioctl *mdio)
|
mdresize(struct md_s *sc, struct md_req *mdr)
|
||||||
{
|
{
|
||||||
int error, res;
|
int error, res;
|
||||||
vm_pindex_t oldpages, newpages;
|
vm_pindex_t oldpages, newpages;
|
||||||
@ -1498,11 +1509,11 @@ mdresize(struct md_s *sc, struct md_ioctl *mdio)
|
|||||||
case MD_NULL:
|
case MD_NULL:
|
||||||
break;
|
break;
|
||||||
case MD_SWAP:
|
case MD_SWAP:
|
||||||
if (mdio->md_mediasize <= 0 ||
|
if (mdr->md_mediasize <= 0 ||
|
||||||
(mdio->md_mediasize % PAGE_SIZE) != 0)
|
(mdr->md_mediasize % PAGE_SIZE) != 0)
|
||||||
return (EDOM);
|
return (EDOM);
|
||||||
oldpages = OFF_TO_IDX(round_page(sc->mediasize));
|
oldpages = OFF_TO_IDX(round_page(sc->mediasize));
|
||||||
newpages = OFF_TO_IDX(round_page(mdio->md_mediasize));
|
newpages = OFF_TO_IDX(round_page(mdr->md_mediasize));
|
||||||
if (newpages < oldpages) {
|
if (newpages < oldpages) {
|
||||||
VM_OBJECT_WLOCK(sc->object);
|
VM_OBJECT_WLOCK(sc->object);
|
||||||
vm_object_page_remove(sc->object, newpages, 0, 0);
|
vm_object_page_remove(sc->object, newpages, 0, 0);
|
||||||
@ -1518,7 +1529,7 @@ mdresize(struct md_s *sc, struct md_ioctl *mdio)
|
|||||||
oldpages), sc->cred);
|
oldpages), sc->cred);
|
||||||
if (!res)
|
if (!res)
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
if ((mdio->md_options & MD_RESERVE) ||
|
if ((mdr->md_options & MD_RESERVE) ||
|
||||||
(sc->flags & MD_RESERVE)) {
|
(sc->flags & MD_RESERVE)) {
|
||||||
error = swap_pager_reserve(sc->object,
|
error = swap_pager_reserve(sc->object,
|
||||||
oldpages, newpages - oldpages);
|
oldpages, newpages - oldpages);
|
||||||
@ -1539,7 +1550,7 @@ mdresize(struct md_s *sc, struct md_ioctl *mdio)
|
|||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
sc->mediasize = mdio->md_mediasize;
|
sc->mediasize = mdr->md_mediasize;
|
||||||
g_topology_lock();
|
g_topology_lock();
|
||||||
g_resize_provider(sc->pp, sc->mediasize);
|
g_resize_provider(sc->pp, sc->mediasize);
|
||||||
g_topology_unlock();
|
g_topology_unlock();
|
||||||
@ -1547,7 +1558,7 @@ mdresize(struct md_s *sc, struct md_ioctl *mdio)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mdcreate_swap(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
|
mdcreate_swap(struct md_s *sc, struct md_req *mdr, struct thread *td)
|
||||||
{
|
{
|
||||||
vm_ooffset_t npage;
|
vm_ooffset_t npage;
|
||||||
int error;
|
int error;
|
||||||
@ -1565,19 +1576,19 @@ mdcreate_swap(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
|
|||||||
* Note the truncation.
|
* Note the truncation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((mdio->md_options & MD_VERIFY) != 0)
|
if ((mdr->md_options & MD_VERIFY) != 0)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
npage = mdio->md_mediasize / PAGE_SIZE;
|
npage = mdr->md_mediasize / PAGE_SIZE;
|
||||||
if (mdio->md_fwsectors != 0)
|
if (mdr->md_fwsectors != 0)
|
||||||
sc->fwsectors = mdio->md_fwsectors;
|
sc->fwsectors = mdr->md_fwsectors;
|
||||||
if (mdio->md_fwheads != 0)
|
if (mdr->md_fwheads != 0)
|
||||||
sc->fwheads = mdio->md_fwheads;
|
sc->fwheads = mdr->md_fwheads;
|
||||||
sc->object = vm_pager_allocate(OBJT_SWAP, NULL, PAGE_SIZE * npage,
|
sc->object = vm_pager_allocate(OBJT_SWAP, NULL, PAGE_SIZE * npage,
|
||||||
VM_PROT_DEFAULT, 0, td->td_ucred);
|
VM_PROT_DEFAULT, 0, td->td_ucred);
|
||||||
if (sc->object == NULL)
|
if (sc->object == NULL)
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
sc->flags = mdio->md_options & (MD_FORCE | MD_RESERVE);
|
sc->flags = mdr->md_options & (MD_FORCE | MD_RESERVE);
|
||||||
if (mdio->md_options & MD_RESERVE) {
|
if (mdr->md_options & MD_RESERVE) {
|
||||||
if (swap_pager_reserve(sc->object, 0, npage) < 0) {
|
if (swap_pager_reserve(sc->object, 0, npage) < 0) {
|
||||||
error = EDOM;
|
error = EDOM;
|
||||||
goto finish;
|
goto finish;
|
||||||
@ -1593,7 +1604,7 @@ mdcreate_swap(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mdcreate_null(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
|
mdcreate_null(struct md_s *sc, struct md_req *mdr, struct thread *td)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1607,7 +1618,7 @@ mdcreate_null(struct md_s *sc, struct md_ioctl *mdio, struct thread *td)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mdattach_locked(struct thread *td, struct md_ioctl *mdio)
|
kern_mdattach_locked(struct thread *td, struct md_req *mdr)
|
||||||
{
|
{
|
||||||
struct md_s *sc;
|
struct md_s *sc;
|
||||||
unsigned sectsize;
|
unsigned sectsize;
|
||||||
@ -1615,7 +1626,7 @@ kern_mdattach_locked(struct thread *td, struct md_ioctl *mdio)
|
|||||||
|
|
||||||
sx_assert(&md_sx, SA_XLOCKED);
|
sx_assert(&md_sx, SA_XLOCKED);
|
||||||
|
|
||||||
switch (mdio->md_type) {
|
switch (mdr->md_type) {
|
||||||
case MD_MALLOC:
|
case MD_MALLOC:
|
||||||
case MD_PRELOAD:
|
case MD_PRELOAD:
|
||||||
case MD_VNODE:
|
case MD_VNODE:
|
||||||
@ -1625,35 +1636,35 @@ kern_mdattach_locked(struct thread *td, struct md_ioctl *mdio)
|
|||||||
default:
|
default:
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
if (mdio->md_sectorsize == 0)
|
if (mdr->md_sectorsize == 0)
|
||||||
sectsize = DEV_BSIZE;
|
sectsize = DEV_BSIZE;
|
||||||
else
|
else
|
||||||
sectsize = mdio->md_sectorsize;
|
sectsize = mdr->md_sectorsize;
|
||||||
if (sectsize > MAXPHYS || mdio->md_mediasize < sectsize)
|
if (sectsize > MAXPHYS || mdr->md_mediasize < sectsize)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
if (mdio->md_options & MD_AUTOUNIT)
|
if (mdr->md_options & MD_AUTOUNIT)
|
||||||
sc = mdnew(-1, &error, mdio->md_type);
|
sc = mdnew(-1, &error, mdr->md_type);
|
||||||
else {
|
else {
|
||||||
if (mdio->md_unit > INT_MAX)
|
if (mdr->md_unit > INT_MAX)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
sc = mdnew(mdio->md_unit, &error, mdio->md_type);
|
sc = mdnew(mdr->md_unit, &error, mdr->md_type);
|
||||||
}
|
}
|
||||||
if (sc == NULL)
|
if (sc == NULL)
|
||||||
return (error);
|
return (error);
|
||||||
if (mdio->md_label != NULL)
|
if (mdr->md_label != NULL)
|
||||||
error = copyinstr(mdio->md_label, sc->label,
|
error = copyinstr(mdr->md_label, sc->label,
|
||||||
sizeof(sc->label), NULL);
|
sizeof(sc->label), NULL);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
goto err_after_new;
|
goto err_after_new;
|
||||||
if (mdio->md_options & MD_AUTOUNIT)
|
if (mdr->md_options & MD_AUTOUNIT)
|
||||||
mdio->md_unit = sc->unit;
|
mdr->md_unit = sc->unit;
|
||||||
sc->mediasize = mdio->md_mediasize;
|
sc->mediasize = mdr->md_mediasize;
|
||||||
sc->sectorsize = sectsize;
|
sc->sectorsize = sectsize;
|
||||||
error = EDOOFUS;
|
error = EDOOFUS;
|
||||||
switch (sc->type) {
|
switch (sc->type) {
|
||||||
case MD_MALLOC:
|
case MD_MALLOC:
|
||||||
sc->start = mdstart_malloc;
|
sc->start = mdstart_malloc;
|
||||||
error = mdcreate_malloc(sc, mdio);
|
error = mdcreate_malloc(sc, mdr);
|
||||||
break;
|
break;
|
||||||
case MD_PRELOAD:
|
case MD_PRELOAD:
|
||||||
/*
|
/*
|
||||||
@ -1665,15 +1676,15 @@ kern_mdattach_locked(struct thread *td, struct md_ioctl *mdio)
|
|||||||
break;
|
break;
|
||||||
case MD_VNODE:
|
case MD_VNODE:
|
||||||
sc->start = mdstart_vnode;
|
sc->start = mdstart_vnode;
|
||||||
error = mdcreate_vnode(sc, mdio, td);
|
error = mdcreate_vnode(sc, mdr, td);
|
||||||
break;
|
break;
|
||||||
case MD_SWAP:
|
case MD_SWAP:
|
||||||
sc->start = mdstart_swap;
|
sc->start = mdstart_swap;
|
||||||
error = mdcreate_swap(sc, mdio, td);
|
error = mdcreate_swap(sc, mdr, td);
|
||||||
break;
|
break;
|
||||||
case MD_NULL:
|
case MD_NULL:
|
||||||
sc->start = mdstart_null;
|
sc->start = mdstart_null;
|
||||||
error = mdcreate_null(sc, mdio, td);
|
error = mdcreate_null(sc, mdr, td);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
err_after_new:
|
err_after_new:
|
||||||
@ -1691,122 +1702,122 @@ kern_mdattach_locked(struct thread *td, struct md_ioctl *mdio)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mdattach(struct thread *td, struct md_ioctl *mdio)
|
kern_mdattach(struct thread *td, struct md_req *mdr)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sx_xlock(&md_sx);
|
sx_xlock(&md_sx);
|
||||||
error = kern_mdattach_locked(td, mdio);
|
error = kern_mdattach_locked(td, mdr);
|
||||||
sx_xunlock(&md_sx);
|
sx_xunlock(&md_sx);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mddetach_locked(struct thread *td, struct md_ioctl *mdio)
|
kern_mddetach_locked(struct thread *td, struct md_req *mdr)
|
||||||
{
|
{
|
||||||
struct md_s *sc;
|
struct md_s *sc;
|
||||||
|
|
||||||
sx_assert(&md_sx, SA_XLOCKED);
|
sx_assert(&md_sx, SA_XLOCKED);
|
||||||
|
|
||||||
if (mdio->md_mediasize != 0 ||
|
if (mdr->md_mediasize != 0 ||
|
||||||
(mdio->md_options & ~MD_FORCE) != 0)
|
(mdr->md_options & ~MD_FORCE) != 0)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
sc = mdfind(mdio->md_unit);
|
sc = mdfind(mdr->md_unit);
|
||||||
if (sc == NULL)
|
if (sc == NULL)
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
if (sc->opencount != 0 && !(sc->flags & MD_FORCE) &&
|
if (sc->opencount != 0 && !(sc->flags & MD_FORCE) &&
|
||||||
!(mdio->md_options & MD_FORCE))
|
!(mdr->md_options & MD_FORCE))
|
||||||
return (EBUSY);
|
return (EBUSY);
|
||||||
return (mddestroy(sc, td));
|
return (mddestroy(sc, td));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mddetach(struct thread *td, struct md_ioctl *mdio)
|
kern_mddetach(struct thread *td, struct md_req *mdr)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sx_xlock(&md_sx);
|
sx_xlock(&md_sx);
|
||||||
error = kern_mddetach_locked(td, mdio);
|
error = kern_mddetach_locked(td, mdr);
|
||||||
sx_xunlock(&md_sx);
|
sx_xunlock(&md_sx);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mdresize_locked(struct md_ioctl *mdio)
|
kern_mdresize_locked(struct md_req *mdr)
|
||||||
{
|
{
|
||||||
struct md_s *sc;
|
struct md_s *sc;
|
||||||
|
|
||||||
sx_assert(&md_sx, SA_XLOCKED);
|
sx_assert(&md_sx, SA_XLOCKED);
|
||||||
|
|
||||||
if ((mdio->md_options & ~(MD_FORCE | MD_RESERVE)) != 0)
|
if ((mdr->md_options & ~(MD_FORCE | MD_RESERVE)) != 0)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
sc = mdfind(mdio->md_unit);
|
sc = mdfind(mdr->md_unit);
|
||||||
if (sc == NULL)
|
if (sc == NULL)
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
if (mdio->md_mediasize < sc->sectorsize)
|
if (mdr->md_mediasize < sc->sectorsize)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
if (mdio->md_mediasize < sc->mediasize &&
|
if (mdr->md_mediasize < sc->mediasize &&
|
||||||
!(sc->flags & MD_FORCE) &&
|
!(sc->flags & MD_FORCE) &&
|
||||||
!(mdio->md_options & MD_FORCE))
|
!(mdr->md_options & MD_FORCE))
|
||||||
return (EBUSY);
|
return (EBUSY);
|
||||||
return (mdresize(sc, mdio));
|
return (mdresize(sc, mdr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mdresize(struct md_ioctl *mdio)
|
kern_mdresize(struct md_req *mdr)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sx_xlock(&md_sx);
|
sx_xlock(&md_sx);
|
||||||
error = kern_mdresize_locked(mdio);
|
error = kern_mdresize_locked(mdr);
|
||||||
sx_xunlock(&md_sx);
|
sx_xunlock(&md_sx);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mdquery_locked(struct md_ioctl *mdio)
|
kern_mdquery_locked(struct md_req *mdr)
|
||||||
{
|
{
|
||||||
struct md_s *sc;
|
struct md_s *sc;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sx_assert(&md_sx, SA_XLOCKED);
|
sx_assert(&md_sx, SA_XLOCKED);
|
||||||
|
|
||||||
sc = mdfind(mdio->md_unit);
|
sc = mdfind(mdr->md_unit);
|
||||||
if (sc == NULL)
|
if (sc == NULL)
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
mdio->md_type = sc->type;
|
mdr->md_type = sc->type;
|
||||||
mdio->md_options = sc->flags;
|
mdr->md_options = sc->flags;
|
||||||
mdio->md_mediasize = sc->mediasize;
|
mdr->md_mediasize = sc->mediasize;
|
||||||
mdio->md_sectorsize = sc->sectorsize;
|
mdr->md_sectorsize = sc->sectorsize;
|
||||||
error = 0;
|
error = 0;
|
||||||
if (mdio->md_label != NULL) {
|
if (mdr->md_label != NULL) {
|
||||||
error = copyout(sc->label, mdio->md_label,
|
error = copyout(sc->label, mdr->md_label,
|
||||||
strlen(sc->label) + 1);
|
strlen(sc->label) + 1);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
if (sc->type == MD_VNODE ||
|
if (sc->type == MD_VNODE ||
|
||||||
(sc->type == MD_PRELOAD && mdio->md_file != NULL))
|
(sc->type == MD_PRELOAD && mdr->md_file != NULL))
|
||||||
error = copyout(sc->file, mdio->md_file,
|
error = copyout(sc->file, mdr->md_file,
|
||||||
strlen(sc->file) + 1);
|
strlen(sc->file) + 1);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mdquery(struct md_ioctl *mdio)
|
kern_mdquery(struct md_req *mdr)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sx_xlock(&md_sx);
|
sx_xlock(&md_sx);
|
||||||
error = kern_mdquery_locked(mdio);
|
error = kern_mdquery_locked(mdr);
|
||||||
sx_xunlock(&md_sx);
|
sx_xunlock(&md_sx);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mdlist_locked(struct md_ioctl *mdio)
|
kern_mdlist_locked(struct md_req *mdr)
|
||||||
{
|
{
|
||||||
struct md_s *sc;
|
struct md_s *sc;
|
||||||
int i;
|
int i;
|
||||||
@ -1814,9 +1825,9 @@ kern_mdlist_locked(struct md_ioctl *mdio)
|
|||||||
sx_assert(&md_sx, SA_XLOCKED);
|
sx_assert(&md_sx, SA_XLOCKED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write the number of md devices to mdio->md_pad[0].
|
* Write the number of md devices to mdr->md_units[0].
|
||||||
* Write the unit number of the first (MDNPAD - 2) units
|
* Write the unit number of the first (mdr->md_units_nitems - 2)
|
||||||
* to mdio->md_pad[1::(MDNPAD - 2)] and terminate the
|
* units to mdr->md_units[1::(mdr->md_units - 2)] and terminate the
|
||||||
* list with -1.
|
* list with -1.
|
||||||
*
|
*
|
||||||
* XXX: There is currently no mechanism to retrieve unit
|
* XXX: There is currently no mechanism to retrieve unit
|
||||||
@ -1827,22 +1838,22 @@ kern_mdlist_locked(struct md_ioctl *mdio)
|
|||||||
*/
|
*/
|
||||||
i = 1;
|
i = 1;
|
||||||
LIST_FOREACH(sc, &md_softc_list, list) {
|
LIST_FOREACH(sc, &md_softc_list, list) {
|
||||||
if (i < MDNPAD - 1)
|
if (i < mdr->md_units_nitems - 1)
|
||||||
mdio->md_pad[i] = sc->unit;
|
mdr->md_units[i] = sc->unit;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
mdio->md_pad[MIN(i, MDNPAD - 1)] = -1;
|
mdr->md_units[MIN(i, mdr->md_units_nitems - 1)] = -1;
|
||||||
mdio->md_pad[0] = i - 1;
|
mdr->md_units[0] = i - 1;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kern_mdlist(struct md_ioctl *mdio)
|
kern_mdlist(struct md_req *mdr)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sx_xlock(&md_sx);
|
sx_xlock(&md_sx);
|
||||||
error = kern_mdlist_locked(mdio);
|
error = kern_mdlist_locked(mdr);
|
||||||
sx_xunlock(&md_sx);
|
sx_xunlock(&md_sx);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -1851,6 +1862,7 @@ static int
|
|||||||
mdctlioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
|
mdctlioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
|
||||||
struct thread *td)
|
struct thread *td)
|
||||||
{
|
{
|
||||||
|
struct md_req mdr;
|
||||||
struct md_ioctl *mdio;
|
struct md_ioctl *mdio;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
@ -1858,37 +1870,67 @@ mdctlioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
|
|||||||
printf("mdctlioctl(%s %lx %p %x %p)\n",
|
printf("mdctlioctl(%s %lx %p %x %p)\n",
|
||||||
devtoname(dev), cmd, addr, flags, td);
|
devtoname(dev), cmd, addr, flags, td);
|
||||||
|
|
||||||
mdio = (struct md_ioctl *)addr;
|
switch (cmd) {
|
||||||
if (mdio->md_version != MDIOVERSION)
|
case MDIOCATTACH:
|
||||||
return (EINVAL);
|
case MDIOCDETACH:
|
||||||
|
case MDIOCRESIZE:
|
||||||
|
case MDIOCQUERY:
|
||||||
|
case MDIOCLIST:
|
||||||
|
mdio = (struct md_ioctl *)addr;
|
||||||
|
if (mdio->md_version != MDIOVERSION)
|
||||||
|
return (EINVAL);
|
||||||
|
mdr.md_unit = mdio->md_unit;
|
||||||
|
mdr.md_type = mdio->md_type;
|
||||||
|
mdr.md_mediasize = mdio->md_mediasize;
|
||||||
|
mdr.md_sectorsize = mdio->md_sectorsize;
|
||||||
|
mdr.md_options = mdio->md_options;
|
||||||
|
mdr.md_fwheads = mdio->md_fwheads;
|
||||||
|
mdr.md_fwsectors = mdio->md_fwsectors;
|
||||||
|
mdr.md_file = mdio->md_file;
|
||||||
|
/* 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;
|
||||||
|
else
|
||||||
|
mdr.md_file_seg = UIO_USERSPACE;
|
||||||
|
mdr.md_label = mdio->md_label;
|
||||||
|
mdr.md_units = &mdio->md_pad[0];
|
||||||
|
mdr.md_units_nitems = nitems(mdio->md_pad);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* We assert the version number in the individual ioctl
|
|
||||||
* handlers instead of out here because (a) it is possible we
|
|
||||||
* may add another ioctl in the future which doesn't read an
|
|
||||||
* mdio, and (b) the correct return value for an unknown ioctl
|
|
||||||
* is ENOIOCTL, not EINVAL.
|
|
||||||
*/
|
|
||||||
error = 0;
|
error = 0;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case MDIOCATTACH:
|
case MDIOCATTACH:
|
||||||
error = kern_mdattach(td, mdio);
|
error = kern_mdattach(td, &mdr);
|
||||||
break;
|
break;
|
||||||
case MDIOCDETACH:
|
case MDIOCDETACH:
|
||||||
error = kern_mddetach(td, mdio);
|
error = kern_mddetach(td, &mdr);
|
||||||
break;
|
break;
|
||||||
case MDIOCRESIZE:
|
case MDIOCRESIZE:
|
||||||
error = kern_mdresize(mdio);
|
error = kern_mdresize(&mdr);
|
||||||
break;
|
break;
|
||||||
case MDIOCQUERY:
|
case MDIOCQUERY:
|
||||||
error = kern_mdquery(mdio);
|
error = kern_mdquery(&mdr);
|
||||||
break;
|
break;
|
||||||
case MDIOCLIST:
|
case MDIOCLIST:
|
||||||
error = kern_mdlist(mdio);
|
error = kern_mdlist(&mdr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error = ENOIOCTL;
|
error = ENOIOCTL;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case MDIOCATTACH:
|
||||||
|
case MDIOCQUERY:
|
||||||
|
mdio->md_unit = mdr.md_unit;
|
||||||
|
mdio->md_type = mdr.md_type;
|
||||||
|
mdio->md_mediasize = mdr.md_mediasize;
|
||||||
|
mdio->md_sectorsize = mdr.md_sectorsize;
|
||||||
|
mdio->md_options = mdr.md_options;
|
||||||
|
mdio->md_fwheads = mdr.md_fwheads;
|
||||||
|
mdio->md_fwsectors = mdr.md_fwsectors;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user