Reorder vop's alphabetically.
Smarter use of devfs_allocv() (from bp@) Introduce devfs_find() ".." fixes to devfs_lookup (from bp@)
This commit is contained in:
parent
62ddc84e08
commit
c32d0a1dcd
@ -88,6 +88,8 @@ extern unsigned devfs_generation;
|
||||
extern vop_t **devfs_vnodeop_p;
|
||||
extern vop_t **devfs_specop_p;
|
||||
|
||||
int devfs_allocv __P((struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct proc *p));
|
||||
struct devfs_dirent * devfs_find __P((struct devfs_dirent *dd, const char *name, int namelen));
|
||||
int devfs_populate __P((struct devfs_mount *dm));
|
||||
struct devfs_dirent * devfs_newdirent __P((char *name, int namelen));
|
||||
void devfs_purge __P((struct devfs_dirent *dd));
|
||||
|
@ -41,6 +41,21 @@
|
||||
#define DEVFS_INTERN
|
||||
#include <fs/devfs/devfs.h>
|
||||
|
||||
struct devfs_dirent *
|
||||
devfs_find(struct devfs_dirent *dd, const char *name, int namelen)
|
||||
{
|
||||
struct devfs_dirent *de;
|
||||
|
||||
TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
|
||||
if (namelen != de->de_dirent->d_namlen)
|
||||
continue;
|
||||
if (bcmp(name, de->de_dirent->d_name, namelen) != 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
return (de);
|
||||
}
|
||||
|
||||
struct devfs_dirent *
|
||||
devfs_newdirent(char *name, int namelen)
|
||||
{
|
||||
@ -161,25 +176,20 @@ devfs_populate(struct devfs_mount *dm)
|
||||
continue;
|
||||
dd = dm->dm_basedir;
|
||||
s = dev->si_name;
|
||||
nextdir:
|
||||
for (q = s; *q != '/' && *q != '\0'; q++)
|
||||
continue;
|
||||
if (*q == '/') {
|
||||
TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
|
||||
if (de->de_dirent->d_namlen != q - s)
|
||||
continue;
|
||||
if (bcmp(de->de_dirent->d_name, s, q - s))
|
||||
continue;
|
||||
goto fdir;
|
||||
for (;;) {
|
||||
for (q = s; *q != '/' && *q != '\0'; q++)
|
||||
continue;
|
||||
if (*q != '/')
|
||||
break;
|
||||
de = devfs_find(dd, s, q - s);
|
||||
if (de == NULL) {
|
||||
de = devfs_vmkdir(s, q - s, dd);
|
||||
de->de_inode = dm->dm_inode++;
|
||||
TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
|
||||
dd->de_links++;
|
||||
}
|
||||
de = devfs_vmkdir(s, q - s, dd);
|
||||
de->de_inode = dm->dm_inode++;
|
||||
TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
|
||||
dd->de_links++;
|
||||
fdir:
|
||||
s = q + 1;
|
||||
dd = de;
|
||||
goto nextdir;
|
||||
}
|
||||
de = devfs_newdirent(s, q - s);
|
||||
if (dev->si_flags & SI_ALIAS) {
|
||||
@ -200,6 +210,7 @@ devfs_populate(struct devfs_mount *dm)
|
||||
de->de_dirent->d_type = DT_CHR;
|
||||
}
|
||||
dm->dm_dirent[i] = de;
|
||||
de->de_dir = dd;
|
||||
TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
|
||||
#if 0
|
||||
printf("Add ino%d %s\n", i, dev->si_name);
|
||||
|
@ -67,43 +67,39 @@ devfs_mount(mp, path, data, ndp, p)
|
||||
struct nameidata *ndp;
|
||||
struct proc *p;
|
||||
{
|
||||
int error = 0;
|
||||
int error;
|
||||
u_int size;
|
||||
struct devfs_mount *fmp;
|
||||
struct vnode *rvp;
|
||||
|
||||
error = 0;
|
||||
/*
|
||||
* Update is a no-op
|
||||
* XXX: flag changes.
|
||||
*/
|
||||
if (mp->mnt_flag & MNT_UPDATE)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
MALLOC(fmp, struct devfs_mount *, sizeof(struct devfs_mount), M_DEVFS, M_WAITOK);
|
||||
|
||||
MALLOC(fmp, struct devfs_mount *, sizeof(struct devfs_mount),
|
||||
M_DEVFS, M_WAITOK);
|
||||
bzero(fmp, sizeof(*fmp));
|
||||
|
||||
error = getnewvnode(VT_DEVFS, mp, devfs_vnodeop_p, &rvp);
|
||||
if (error) {
|
||||
FREE(fmp, M_DEVFS);
|
||||
return (error);
|
||||
}
|
||||
|
||||
vhold(rvp);
|
||||
rvp->v_type = VDIR;
|
||||
rvp->v_flag |= VROOT;
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_data = (qaddr_t) fmp;
|
||||
vfs_getnewfsid(mp);
|
||||
|
||||
fmp->dm_inode = NDEVINO;
|
||||
fmp->dm_root = rvp;
|
||||
|
||||
fmp->dm_rootdir = devfs_vmkdir("(root)", 6, NULL);
|
||||
fmp->dm_rootdir->de_inode = 2;
|
||||
rvp->v_data = fmp->dm_rootdir;
|
||||
|
||||
fmp->dm_basedir = fmp->dm_rootdir;
|
||||
|
||||
error = devfs_root(mp, &rvp);
|
||||
if (error) {
|
||||
FREE(fmp, M_DEVFS);
|
||||
return (error);
|
||||
}
|
||||
VOP_UNLOCK(rvp, 0, p);
|
||||
|
||||
if (path != NULL) {
|
||||
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
|
||||
} else {
|
||||
@ -127,55 +123,47 @@ devfs_unmount(mp, mntflags, p)
|
||||
{
|
||||
int error;
|
||||
int flags = 0;
|
||||
struct vnode *rootvp = VFSTODEVFS(mp)->dm_root;
|
||||
struct vnode *rootvp;
|
||||
struct devfs_mount *fmp;
|
||||
|
||||
fmp = (struct devfs_mount*) mp->mnt_data;
|
||||
error = devfs_root(mp, &rootvp);
|
||||
if (error)
|
||||
return (error);
|
||||
fmp = VFSTODEVFS(mp);
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
|
||||
/*
|
||||
* Clear out buffer cache. I don't think we
|
||||
* ever get anything cached at this level at the
|
||||
* moment, but who knows...
|
||||
*/
|
||||
if (rootvp->v_usecount > 2)
|
||||
return (EBUSY);
|
||||
devfs_purge(fmp->dm_rootdir);
|
||||
error = vflush(mp, rootvp, flags);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* Release reference on underlying root vnode
|
||||
*/
|
||||
vput(rootvp);
|
||||
vrele(rootvp);
|
||||
/*
|
||||
* And blow it away for future re-use
|
||||
*/
|
||||
vgone(rootvp);
|
||||
/*
|
||||
* Finally, throw away the devfs_mount structure
|
||||
*/
|
||||
free(mp->mnt_data, M_DEVFS);
|
||||
mp->mnt_data = 0;
|
||||
free(fmp, M_DEVFS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return locked reference to root. */
|
||||
|
||||
static int
|
||||
devfs_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct proc *p = curproc; /* XXX */
|
||||
int error;
|
||||
struct proc *p;
|
||||
struct vnode *vp;
|
||||
struct devfs_mount *dmp;
|
||||
|
||||
/*
|
||||
* Return locked reference to root.
|
||||
*/
|
||||
vp = VFSTODEVFS(mp)->dm_root;
|
||||
VREF(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
p = curproc; /* XXX */
|
||||
dmp = VFSTODEVFS(mp);
|
||||
error = devfs_allocv(dmp->dm_rootdir, mp, &vp, p);
|
||||
if (error)
|
||||
return (error);
|
||||
vp->v_flag |= VROOT;
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
}
|
||||
|
@ -67,16 +67,18 @@ static int devfs_setattr __P((struct vop_setattr_args *ap));
|
||||
static int devfs_symlink __P((struct vop_symlink_args *ap));
|
||||
|
||||
|
||||
static int
|
||||
int
|
||||
devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct proc *p)
|
||||
{
|
||||
int error;
|
||||
struct vnode *vp;
|
||||
|
||||
if (p == NULL)
|
||||
p = curproc; /* XXX */
|
||||
loop:
|
||||
vp = de->de_vnode;
|
||||
if (vp != NULL) {
|
||||
if (vget(vp, 0, p ? p : curproc))
|
||||
if (vget(vp, LK_EXCLUSIVE, p ? p : curproc))
|
||||
goto loop;
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
@ -101,148 +103,10 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, stru
|
||||
vp->v_data = de;
|
||||
de->de_vnode = vp;
|
||||
vhold(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* vp is the current namei directory
|
||||
* ndp is the name to locate in that directory...
|
||||
*/
|
||||
static int
|
||||
devfs_lookup(ap)
|
||||
struct vop_lookup_args /* {
|
||||
struct vnode * a_dvp;
|
||||
struct vnode ** a_vpp;
|
||||
struct componentname * a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
struct componentname *cnp = ap->a_cnp;
|
||||
struct vnode **vpp = ap->a_vpp;
|
||||
struct vnode *dvp = ap->a_dvp;
|
||||
char *pname = cnp->cn_nameptr;
|
||||
struct proc *p = cnp->cn_proc;
|
||||
struct devfs_dirent *dd;
|
||||
struct devfs_dirent *de;
|
||||
struct devfs_mount *dmp;
|
||||
dev_t cdev;
|
||||
int error, cloned, i;
|
||||
char specname[SPECNAMELEN + 1];
|
||||
|
||||
*vpp = NULLVP;
|
||||
|
||||
#if 0
|
||||
error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
|
||||
if (error)
|
||||
return (error);
|
||||
#endif
|
||||
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
if (cnp->cn_namelen == 1 && *pname == '.') {
|
||||
*vpp = dvp;
|
||||
VREF(dvp);
|
||||
vn_lock(dvp, LK_SHARED | LK_RETRY, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
cloned = 0;
|
||||
|
||||
dmp = VFSTODEVFS(dvp->v_mount);
|
||||
again:
|
||||
|
||||
devfs_populate(dmp);
|
||||
dd = dvp->v_data;
|
||||
TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
|
||||
if (cnp->cn_namelen != de->de_dirent->d_namlen)
|
||||
continue;
|
||||
if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name, de->de_dirent->d_namlen) != 0)
|
||||
continue;
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (!cloned) {
|
||||
/*
|
||||
* OK, we didn't have an entry for the name we were asked for
|
||||
* so we try to see if anybody can create it on demand.
|
||||
* We need to construct the full "devname" for this device
|
||||
* relative to "basedir" or the clone functions would not
|
||||
* be able to tell "/dev/foo" from "/dev/bar/foo"
|
||||
*/
|
||||
i = SPECNAMELEN;
|
||||
specname[i] = '\0';
|
||||
i -= cnp->cn_namelen;
|
||||
if (i < 0)
|
||||
goto noclone;
|
||||
bcopy(cnp->cn_nameptr, specname + i, cnp->cn_namelen);
|
||||
de = dd;
|
||||
while (de != dmp->dm_basedir) {
|
||||
i--;
|
||||
if (i < 0)
|
||||
goto noclone;
|
||||
specname[i] = '/';
|
||||
i -= de->de_dirent->d_namlen;
|
||||
if (i < 0)
|
||||
goto noclone;
|
||||
bcopy(de->de_dirent->d_name, specname + i,
|
||||
de->de_dirent->d_namlen);
|
||||
de = TAILQ_FIRST(&de->de_dlist); /* "." */
|
||||
de = TAILQ_NEXT(de, de_list); /* ".." */
|
||||
de = de->de_dir;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("Finished specname: %d \"%s\"\n", i, specname + i);
|
||||
#endif
|
||||
cdev = NODEV;
|
||||
EVENTHANDLER_INVOKE(devfs_clone, specname + i,
|
||||
strlen(specname + i), &cdev);
|
||||
#if 0
|
||||
printf("cloned %s -> %p %s\n", specname + i, cdev,
|
||||
cdev == NODEV ? "NODEV" : cdev->si_name);
|
||||
#endif
|
||||
if (cdev != NODEV) {
|
||||
cloned = 1;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
noclone:
|
||||
/* No luck, too bad. */
|
||||
|
||||
if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
|
||||
(cnp->cn_flags & ISLASTCN)) {
|
||||
cnp->cn_flags |= SAVENAME;
|
||||
if (!(cnp->cn_flags & LOCKPARENT))
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
return (EJUSTRETURN);
|
||||
} else {
|
||||
vn_lock(dvp, LK_SHARED | LK_RETRY, p);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
|
||||
found:
|
||||
|
||||
error = devfs_allocv(de, dvp->v_mount, vpp, p);
|
||||
if (error != 0) {
|
||||
vn_lock(dvp, LK_SHARED | LK_RETRY, p);
|
||||
return (error);
|
||||
}
|
||||
if ((cnp->cn_nameiop == DELETE) && (cnp->cn_flags & ISLASTCN)) {
|
||||
if (*vpp == dvp) {
|
||||
VREF(dvp);
|
||||
*vpp = dvp;
|
||||
return (0);
|
||||
}
|
||||
VREF(*vpp);
|
||||
if (!(cnp->cn_flags & LOCKPARENT))
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
return (0);
|
||||
}
|
||||
vn_lock(*vpp, LK_SHARED | LK_RETRY, p);
|
||||
if (!(cnp->cn_flags & LOCKPARENT))
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
devfs_access(ap)
|
||||
@ -323,43 +187,186 @@ devfs_getattr(ap)
|
||||
}
|
||||
|
||||
static int
|
||||
devfs_setattr(ap)
|
||||
struct vop_setattr_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct vattr *a_vap;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
devfs_lookup(ap)
|
||||
struct vop_lookup_args /* {
|
||||
struct vnode * a_dvp;
|
||||
struct vnode ** a_vpp;
|
||||
struct componentname * a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
struct devfs_dirent *de;
|
||||
int c;
|
||||
struct componentname *cnp;
|
||||
struct vnode *dvp, **vpp;
|
||||
struct proc *p;
|
||||
struct devfs_dirent *de, *dd;
|
||||
struct devfs_mount *dmp;
|
||||
dev_t cdev;
|
||||
int error, cloned, i, flags, nameiop;
|
||||
char specname[SPECNAMELEN + 1], *pname;
|
||||
|
||||
de = ap->a_vp->v_data;
|
||||
if (ap->a_vp->v_type == VDIR)
|
||||
de = de->de_dir;
|
||||
cnp = ap->a_cnp;
|
||||
vpp = ap->a_vpp;
|
||||
dvp = ap->a_dvp;
|
||||
pname = cnp->cn_nameptr;
|
||||
p = cnp->cn_proc;
|
||||
flags = cnp->cn_flags;
|
||||
nameiop = cnp->cn_nameiop;
|
||||
dmp = VFSTODEVFS(dvp->v_mount);
|
||||
cloned = 0;
|
||||
dd = dvp->v_data;
|
||||
|
||||
*vpp = NULLVP;
|
||||
|
||||
c = 0;
|
||||
if (ap->a_vap->va_flags != VNOVAL)
|
||||
if (nameiop == RENAME)
|
||||
return (EOPNOTSUPP);
|
||||
if (ap->a_vap->va_uid != (uid_t)VNOVAL) {
|
||||
de->de_uid = ap->a_vap->va_uid;
|
||||
c = 1;
|
||||
}
|
||||
if (ap->a_vap->va_gid != (gid_t)VNOVAL) {
|
||||
de->de_gid = ap->a_vap->va_gid;
|
||||
c = 1;
|
||||
}
|
||||
if (ap->a_vap->va_mode != (mode_t)VNOVAL) {
|
||||
de->de_mode = ap->a_vap->va_mode;
|
||||
c = 1;
|
||||
}
|
||||
if (ap->a_vap->va_atime.tv_sec != VNOVAL)
|
||||
de->de_atime = ap->a_vap->va_atime;
|
||||
if (ap->a_vap->va_mtime.tv_sec != VNOVAL)
|
||||
de->de_mtime = ap->a_vap->va_mtime;
|
||||
|
||||
if (c)
|
||||
getnanotime(&de->de_ctime);
|
||||
if (dvp->v_type != VDIR)
|
||||
return (ENOTDIR);
|
||||
|
||||
if ((flags & ISDOTDOT) && (dvp->v_flag & VROOT))
|
||||
return (EIO);
|
||||
|
||||
error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (cnp->cn_namelen == 1 && *pname == '.') {
|
||||
if (nameiop != LOOKUP)
|
||||
return (EINVAL);
|
||||
*vpp = dvp;
|
||||
VREF(dvp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (flags & ISDOTDOT) {
|
||||
if (nameiop != LOOKUP)
|
||||
return (EINVAL);
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
de = TAILQ_FIRST(&dd->de_dlist); /* "." */
|
||||
de = TAILQ_NEXT(de, de_list); /* ".." */
|
||||
de = de->de_dir;
|
||||
error = devfs_allocv(de, dvp->v_mount, vpp, p);
|
||||
if (error) {
|
||||
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
return (error);
|
||||
}
|
||||
if ((flags & LOCKPARENT) && (flags & ISLASTCN))
|
||||
error = vn_lock(dvp, LK_EXCLUSIVE, p);
|
||||
if (error)
|
||||
vput(*vpp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
devfs_populate(dmp);
|
||||
dd = dvp->v_data;
|
||||
TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
|
||||
if (cnp->cn_namelen != de->de_dirent->d_namlen)
|
||||
continue;
|
||||
if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name,
|
||||
de->de_dirent->d_namlen) != 0)
|
||||
continue;
|
||||
goto found;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, we didn't have an entry for the name we were asked for
|
||||
* so we try to see if anybody can create it on demand.
|
||||
* We need to construct the full "devname" for this device
|
||||
* relative to "basedir" or the clone functions would not
|
||||
* be able to tell "/dev/foo" from "/dev/bar/foo"
|
||||
*/
|
||||
i = SPECNAMELEN;
|
||||
specname[i] = '\0';
|
||||
i -= cnp->cn_namelen;
|
||||
if (i < 0)
|
||||
goto notfound;
|
||||
bcopy(cnp->cn_nameptr, specname + i, cnp->cn_namelen);
|
||||
de = dd;
|
||||
while (de != dmp->dm_basedir) {
|
||||
i--;
|
||||
if (i < 0)
|
||||
goto notfound;
|
||||
specname[i] = '/';
|
||||
i -= de->de_dirent->d_namlen;
|
||||
if (i < 0)
|
||||
goto notfound;
|
||||
bcopy(de->de_dirent->d_name, specname + i,
|
||||
de->de_dirent->d_namlen);
|
||||
de = TAILQ_FIRST(&de->de_dlist); /* "." */
|
||||
de = TAILQ_NEXT(de, de_list); /* ".." */
|
||||
de = de->de_dir;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("Finished specname: %d \"%s\"\n", i, specname + i);
|
||||
#endif
|
||||
cdev = NODEV;
|
||||
EVENTHANDLER_INVOKE(devfs_clone, specname + i,
|
||||
strlen(specname + i), &cdev);
|
||||
#if 0
|
||||
printf("cloned %s -> %p %s\n", specname + i, cdev,
|
||||
cdev == NODEV ? "NODEV" : cdev->si_name);
|
||||
#endif
|
||||
if (cdev == NODEV)
|
||||
goto notfound;
|
||||
|
||||
devfs_populate(dmp);
|
||||
dd = dvp->v_data;
|
||||
TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
|
||||
if (cnp->cn_namelen != de->de_dirent->d_namlen)
|
||||
continue;
|
||||
if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name,
|
||||
de->de_dirent->d_namlen) != 0)
|
||||
continue;
|
||||
goto found;
|
||||
}
|
||||
|
||||
notfound:
|
||||
|
||||
if ((nameiop == CREATE || nameiop == RENAME) &&
|
||||
(flags & (LOCKPARENT | WANTPARENT)) && (flags & ISLASTCN)) {
|
||||
cnp->cn_flags |= SAVENAME;
|
||||
if (!(flags & LOCKPARENT))
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
return (ENOENT);
|
||||
|
||||
|
||||
found:
|
||||
|
||||
if ((cnp->cn_nameiop == DELETE) && (flags & ISLASTCN)) {
|
||||
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, p);
|
||||
if (error)
|
||||
return (error);
|
||||
if (*vpp == dvp) {
|
||||
VREF(dvp);
|
||||
*vpp = dvp;
|
||||
return (0);
|
||||
}
|
||||
error = devfs_allocv(de, dvp->v_mount, vpp, p);
|
||||
if (error)
|
||||
return (error);
|
||||
if (!(flags & LOCKPARENT))
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
return (0);
|
||||
}
|
||||
error = devfs_allocv(de, dvp->v_mount, vpp, p);
|
||||
if (error)
|
||||
return (error);
|
||||
if (!(flags & LOCKPARENT) || !(flags & ISLASTCN))
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
devfs_print(ap)
|
||||
struct vop_print_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
printf("tag VT_DEVFS, devfs vnode\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -515,6 +522,47 @@ devfs_revoke(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
devfs_setattr(ap)
|
||||
struct vop_setattr_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct vattr *a_vap;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct devfs_dirent *de;
|
||||
int c;
|
||||
|
||||
de = ap->a_vp->v_data;
|
||||
if (ap->a_vp->v_type == VDIR)
|
||||
de = de->de_dir;
|
||||
|
||||
c = 0;
|
||||
if (ap->a_vap->va_flags != VNOVAL)
|
||||
return (EOPNOTSUPP);
|
||||
if (ap->a_vap->va_uid != (uid_t)VNOVAL) {
|
||||
de->de_uid = ap->a_vap->va_uid;
|
||||
c = 1;
|
||||
}
|
||||
if (ap->a_vap->va_gid != (gid_t)VNOVAL) {
|
||||
de->de_gid = ap->a_vap->va_gid;
|
||||
c = 1;
|
||||
}
|
||||
if (ap->a_vap->va_mode != (mode_t)VNOVAL) {
|
||||
de->de_mode = ap->a_vap->va_mode;
|
||||
c = 1;
|
||||
}
|
||||
if (ap->a_vap->va_atime.tv_sec != VNOVAL)
|
||||
de->de_atime = ap->a_vap->va_atime;
|
||||
if (ap->a_vap->va_mtime.tv_sec != VNOVAL)
|
||||
de->de_mtime = ap->a_vap->va_mtime;
|
||||
|
||||
if (c)
|
||||
getnanotime(&de->de_ctime);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
devfs_symlink(ap)
|
||||
struct vop_symlink_args /* {
|
||||
@ -530,7 +578,7 @@ devfs_symlink(ap)
|
||||
struct devfs_dirent *de;
|
||||
struct devfs_mount *dmp;
|
||||
|
||||
dmp = (struct devfs_mount *)ap->a_dvp->v_mount->mnt_data;
|
||||
dmp = VFSTODEVFS(ap->a_dvp->v_mount);
|
||||
dd = ap->a_dvp->v_data;
|
||||
de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen);
|
||||
de->de_uid = 0;
|
||||
@ -543,27 +591,11 @@ devfs_symlink(ap)
|
||||
bcopy(ap->a_target, de->de_symlink, i);
|
||||
TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
|
||||
devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, 0);
|
||||
VREF(*(ap->a_vpp));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print out the contents of a devfs vnode.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
devfs_print(ap)
|
||||
struct vop_print_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
printf("tag VT_DEVFS, devfs vnode\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Kernfs "should never get here" operation
|
||||
* DEVFS "should never get here" operation
|
||||
*/
|
||||
static int
|
||||
devfs_badop()
|
||||
|
Loading…
Reference in New Issue
Block a user