sys/sys/conf.h:

sys/kern/kern_conf.c:
	Add make_dev_physpath_alias().  This interface takes
	the parent cdev of the alias, an old alias cdev (if any)
	to replace with the newly created alias, and the physical
	path string.  The alias is visiable as a symlink to the
	parent, with the same name as the parent, rooted at
	physpath in devfs.

	Note: make_dev_physpath_alias() has hard coded knowledge of the
	      Solaris style prefix convention for physical path data,
	      "id1,".  In the future, I expect the convention to change
	      to allow "physical path quality" to be reported in the
	      prefix.  For example, a physical path based on NewBus
	      topology would be of "lower quality" than a physical path
	      reported by a device enclosure.

Sponsored by:	Spectra Logic Corporation
This commit is contained in:
gibbs 2011-06-14 16:29:43 +00:00
parent 896ba7687e
commit 9d45c190c8
2 changed files with 65 additions and 0 deletions

View File

@ -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)
{

View File

@ -280,6 +280,9 @@ struct cdev *make_dev_alias(struct cdev *_pdev, const char *_fmt, ...)
__printflike(2, 3);
int make_dev_alias_p(int _flags, struct cdev **_cdev, struct cdev *_pdev,
const char *_fmt, ...) __printflike(4, 5);
int make_dev_physpath_alias(int _flags, struct cdev **_cdev,
struct cdev *_pdev, struct cdev *_old_alias,
const char *_physpath);
void dev_lock(void);
void dev_unlock(void);
void setconf(void);