aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_conf.c
diff options
context:
space:
mode:
authorJustin T. Gibbs <gibbs@FreeBSD.org>2011-06-14 16:29:43 +0000
committerJustin T. Gibbs <gibbs@FreeBSD.org>2011-06-14 16:29:43 +0000
commitaa76615dd1b6df8a2dd7b31cd183b59410b92c1e (patch)
treeb5837253e7d00c27355ed10d509f55e980e44161 /sys/kern/kern_conf.c
parentba12978b8a7b8f7e4497080ecc966a0b597e15b9 (diff)
downloadsrc-aa76615dd1b6df8a2dd7b31cd183b59410b92c1e.tar.gz
src-aa76615dd1b6df8a2dd7b31cd183b59410b92c1e.zip
Notes
Diffstat (limited to 'sys/kern/kern_conf.c')
-rw-r--r--sys/kern/kern_conf.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index 59b876c18e55..a4d90c78218e 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -963,6 +963,68 @@ make_dev_alias_p(int flags, struct cdev **cdev, struct cdev *pdev,
return (res);
}
+int
+make_dev_physpath_alias(int flags, struct cdev **cdev, struct cdev *pdev,
+ struct cdev *old_alias, const char *physpath)
+{
+ char *devfspath;
+ int physpath_len;
+ int max_parentpath_len;
+ int parentpath_len;
+ int devfspathbuf_len;
+ int mflags;
+ int ret;
+
+ *cdev = NULL;
+ devfspath = NULL;
+ physpath_len = strlen(physpath);
+ ret = EINVAL;
+ if (physpath_len == 0)
+ goto out;
+
+ if (strncmp("id1,", physpath, 4) == 0) {
+ physpath += 4;
+ physpath_len -= 4;
+ if (physpath_len == 0)
+ goto out;
+ }
+
+ max_parentpath_len = SPECNAMELEN - physpath_len - /*/*/1;
+ parentpath_len = strlen(pdev->si_name);
+ if (max_parentpath_len < parentpath_len) {
+ printf("make_dev_physpath_alias: WARNING - Unable to alias %s "
+ "to %s/%s - path too long\n",
+ pdev->si_name, physpath, pdev->si_name);
+ ret = ENAMETOOLONG;
+ goto out;
+ }
+
+ mflags = (flags & MAKEDEV_NOWAIT) ? M_NOWAIT : M_WAITOK;
+ devfspathbuf_len = physpath_len + /*/*/1 + parentpath_len + /*NUL*/1;
+ devfspath = malloc(devfspathbuf_len, M_DEVBUF, mflags);
+ if (devfspath == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ sprintf(devfspath, "%s/%s", physpath, pdev->si_name);
+ if (old_alias != NULL
+ && strcmp(old_alias->si_name, devfspath) == 0) {
+ /* Retain the existing alias. */
+ *cdev = old_alias;
+ old_alias = NULL;
+ ret = 0;
+ } else {
+ ret = make_dev_alias_p(flags, cdev, pdev, devfspath);
+ }
+out:
+ if (old_alias != NULL)
+ destroy_dev(old_alias);
+ if (devfspath != NULL)
+ free(devfspath, M_DEVBUF);
+ return (ret);
+}
+
static void
destroy_devl(struct cdev *dev)
{