a issue about getting a devfs node's fullpath
Zhichao1.Li at dell.com
Zhichao1.Li at dell.com
Thu Oct 10 05:50:09 UTC 2019
Dear freebsd developers
I know you're swamped, so I'll be brief.
I am trying to get a node's full under /dev by calling the function 'vn_fullpath', when dealing with things like '/dev/null' or '/dev/usb/1.0.1', it works well.
However when dealing a node under more than 2 sub directories (e.g. /dev/bus/usb/001/002) which I made by calling 'make_dev_s' , it goes a little bit different, I got a string "/dev/bus/usb/bus/usb/001/002"
And I found the function 'devfs_vptocnp' gets the string wrongly when dealing multi slashes path string, I have remark the code as followed and put some comments
would you please take a look, and tell me what the purpose this func pass the string that way?
static int
devfs_vptocnp(struct vop_vptocnp_args *ap)
{
struct vnode *vp = ap->a_vp;
struct vnode **dvp = ap->a_vpp;
struct devfs_mount *dmp;
char *buf = ap->a_buf;
int *buflen = ap->a_buflen;
struct devfs_dirent *dd, *de;
int i, error;
dmp = VFSTODEVFS(vp->v_mount);
error = devfs_populate_vp(vp);
if (error != 0)
return (error);
i = *buflen;
dd = vp->v_data;
if (vp->v_type == VCHR) {
i -= strlen(dd->de_cdp->cdp_c.si_name);
if (i < 0) {
error = ENOMEM;
goto finished;
}
bcopy(dd->de_cdp->cdp_c.si_name, buf + i,
strlen(dd->de_cdp->cdp_c.si_name));
/*
* when dealing with VCHR
* the element 'si_name' already
* holds the full path string
* except rootdir, why not just go
* to the rootdir?
*/
de = dd->de_dir;
} else if (vp->v_type == VDIR) {
if (dd == dmp->dm_rootdir) {
*dvp = vp;
vref(*dvp);
goto finished;
}
i -= dd->de_dirent->d_namlen;
if (i < 0) {
error = ENOMEM;
goto finished;
}
bcopy(dd->de_cdp->cdp_c.si_name, buf + i,
strlen(dd->de_cdp->cdp_c.si_name));
de = dd->de_dir;
} else if (vp->v_type == VDIR) {
if (dd == dmp->dm_rootdir) {
*dvp = vp;
vref(*dvp);
goto finished;
}
i -= dd->de_dirent->d_namlen;
if (i < 0) {
error = ENOMEM;
goto finished;
}
bcopy(dd->de_dirent->d_name, buf + i,
dd->de_dirent->d_namlen);
de = dd;
} else {
error = ENOENT;
goto finished;
}
*buflen = i;
de = devfs_parent_dirent(de);
if (de == NULL) {
error = ENOENT;
goto finished;
}
mtx_lock(&devfs_de_interlock);
*dvp = de->de_vnode;
if (*dvp != NULL) {
VI_LOCK(*dvp);
mtx_unlock(&devfs_de_interlock);
vholdl(*dvp);
VI_UNLOCK(*dvp);
vref(*dvp);
vdrop(*dvp);
} else {
mtx_unlock(&devfs_de_interlock);
error = ENOENT;
}
finished:
sx_xunlock(&dmp->dm_lock);
return (error);
}
More information about the freebsd-drivers
mailing list