summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/modctl.c
diff options
context:
space:
mode:
authorllai1 <none@none>2006-08-25 17:24:25 -0700
committerllai1 <none@none>2006-08-25 17:24:25 -0700
commitfacf4a8d7b59fde89a8662b4f4c73a758e6c402c (patch)
tree4e0024c5508351006df1496ec4be6e7b564c3ce8 /usr/src/uts/common/os/modctl.c
parentadcafb0fe4c49c4d46c0b393dfba36d4e1b55c0e (diff)
downloadillumos-gate-facf4a8d7b59fde89a8662b4f4c73a758e6c402c.tar.gz
PSARC/2003/246 Filesystem Driven Device Naming
5050715 logical device names not created during early boot 6292952 devfsadm mishandles optarg 6362924 devfsadm secondary link generation is not zones aware 6413127 Integrate the Devname Project 6464196 bfu should remove pt_chmod, obsoleted by /dev filesystem --HG-- rename : usr/src/cmd/pt_chmod/Makefile => deleted_files/usr/src/cmd/pt_chmod/Makefile rename : usr/src/cmd/pt_chmod/pt_chmod.c => deleted_files/usr/src/cmd/pt_chmod/pt_chmod.c
Diffstat (limited to 'usr/src/uts/common/os/modctl.c')
-rw-r--r--usr/src/uts/common/os/modctl.c164
1 files changed, 159 insertions, 5 deletions
diff --git a/usr/src/uts/common/os/modctl.c b/usr/src/uts/common/os/modctl.c
index e776a36310..3509231ee2 100644
--- a/usr/src/uts/common/os/modctl.c
+++ b/usr/src/uts/common/os/modctl.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -79,6 +78,7 @@
#include <ipp/ipp_impl.h>
#include <sys/fs/dv_node.h>
#include <sys/strsubr.h>
+#include <sys/fs/sdev_node.h>
static int mod_circdep(struct modctl *);
static int modinfo(modid_t, struct modinfo *);
@@ -679,7 +679,8 @@ new_vfs_in_modpath()
return (1); /* always reread driver.conf the first time */
}
-static int modctl_load_drvconf(major_t major)
+static int
+modctl_load_drvconf(major_t major)
{
int ret;
@@ -785,6 +786,8 @@ modctl_getmaj(char *uname, uint_t ulen, int *umajorp)
int retval;
major_t major;
+ if (ulen == 0)
+ return (EINVAL);
if ((retval = copyinstr(uname, name,
(ulen < 256) ? ulen : 256, 0)) != 0)
return (retval);
@@ -1640,6 +1643,144 @@ modctl_allocpriv(const char *name)
return (error);
}
+static int
+modctl_devexists(const char *upath, int pathlen)
+{
+ char *path;
+ int ret;
+
+ /*
+ * copy in the path, including the terminating null
+ */
+ pathlen++;
+ if (pathlen <= 1 || pathlen > MAXPATHLEN)
+ return (EINVAL);
+ path = kmem_zalloc(pathlen + 1, KM_SLEEP);
+ if ((ret = copyinstr(upath, path, pathlen, NULL)) == 0) {
+ ret = sdev_modctl_devexists(path);
+ }
+
+ kmem_free(path, pathlen + 1);
+ return (ret);
+}
+
+static int
+modctl_devreaddir(const char *udir, int udirlen,
+ char *upaths, int64_t *ulensp)
+{
+ char *paths = NULL;
+ char **dirlist = NULL;
+ char *dir;
+ int64_t ulens;
+ int64_t lens;
+ int i, n;
+ int ret = 0;
+ char *p;
+ int npaths;
+ int npaths_alloc;
+
+ /*
+ * If upaths is NULL then we are only computing the amount of space
+ * needed to return the paths, with the value returned in *ulensp. If we
+ * are copying out paths then we get the amount of space allocated by
+ * the caller. If the actual space needed for paths is larger, or
+ * things are changing out from under us, then we return EAGAIN.
+ */
+ if (upaths) {
+ if (ulensp == NULL)
+ return (EINVAL);
+ if (copyin(ulensp, &ulens, sizeof (ulens)) != 0)
+ return (EFAULT);
+ }
+
+ /*
+ * copyin the /dev path including terminating null
+ */
+ udirlen++;
+ if (udirlen <= 1 || udirlen > MAXPATHLEN)
+ return (EINVAL);
+ dir = kmem_zalloc(udirlen + 1, KM_SLEEP);
+ if ((ret = copyinstr(udir, dir, udirlen, NULL)) != 0)
+ goto err;
+
+ if ((ret = sdev_modctl_readdir(dir, &dirlist,
+ &npaths, &npaths_alloc)) != 0) {
+ ASSERT(dirlist == NULL);
+ goto err;
+ }
+
+ lens = 0;
+ for (i = 0; i < npaths; i++) {
+ lens += strlen(dirlist[i]) + 1;
+ }
+ lens++; /* add one for double termination */
+
+ if (upaths) {
+ if (lens > ulens) {
+ ret = EAGAIN;
+ goto out;
+ }
+
+ paths = kmem_alloc(lens, KM_SLEEP);
+
+ p = paths;
+ for (i = 0; i < npaths; i++) {
+ n = strlen(dirlist[i]) + 1;
+ bcopy(dirlist[i], p, n);
+ p += n;
+ }
+ *p = 0;
+
+ if (copyout(paths, upaths, lens)) {
+ ret = EFAULT;
+ goto err;
+ }
+ }
+
+out:
+ /* copy out the amount of space needed to hold the paths */
+ if (copyout(&lens, ulensp, sizeof (lens)))
+ ret = EFAULT;
+
+err:
+ if (dirlist)
+ sdev_modctl_readdir_free(dirlist, npaths, npaths_alloc);
+ if (paths)
+ kmem_free(paths, lens);
+ kmem_free(dir, udirlen + 1);
+ return (ret);
+}
+
+int
+modctl_moddevname(int subcmd, uintptr_t a1, uintptr_t a2)
+{
+ int error = 0;
+
+ switch (subcmd) {
+ case MODDEVNAME_LOOKUPDOOR:
+ case MODDEVNAME_DEVFSADMNODE:
+ error = devname_filename_register(subcmd, (char *)a1);
+ break;
+ case MODDEVNAME_NSMAPS:
+ error = devname_nsmaps_register((char *)a1, (size_t)a2);
+ break;
+ case MODDEVNAME_PROFILE:
+ error = devname_profile_update((char *)a1, (size_t)a2);
+ break;
+ case MODDEVNAME_RECONFIG:
+ i_ddi_set_reconfig();
+ break;
+ case MODDEVNAME_SYSAVAIL:
+ i_ddi_set_sysavail();
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
/*ARGSUSED5*/
int
modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4,
@@ -1845,6 +1986,19 @@ modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4,
error = modctl_remdrv_cleanup((const char *)a1);
break;
+ case MODDEVEXISTS: /* non-reconfiguring /dev lookup */
+ error = modctl_devexists((const char *)a1, (size_t)a2);
+ break;
+
+ case MODDEVREADDIR: /* non-reconfiguring /dev readdir */
+ error = modctl_devreaddir((const char *)a1, (size_t)a2,
+ (char *)a3, (int64_t *)a4);
+ break;
+
+ case MODDEVNAME:
+ error = modctl_moddevname((int)a1, a2, a3);
+ break;
+
default:
error = EINVAL;
break;
@@ -3626,7 +3780,7 @@ mod_in_autounload()
if (c == 0) \
return (0);
-static int
+int
gmatch(const char *s, const char *p)
{
int c, sc;