summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2000-08-27 14:46:36 +0000
committerphk <phk@FreeBSD.org>2000-08-27 14:46:36 +0000
commit1109c8321563e16ebc0b1632cb2e954971f036c3 (patch)
treec9f1839b54d0723eb8e61972f56384a6e231f8dd /sys/fs
parent7173fac52902acf879b833b7ade03cd2c55aa45a (diff)
downloadFreeBSD-src-1109c8321563e16ebc0b1632cb2e954971f036c3.zip
FreeBSD-src-1109c8321563e16ebc0b1632cb2e954971f036c3.tar.gz
Reorder vop's alphabetically.
Smarter use of devfs_allocv() (from bp@) Introduce devfs_find() ".." fixes to devfs_lookup (from bp@)
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/devfs/devfs.h2
-rw-r--r--sys/fs/devfs/devfs_devs.c43
-rw-r--r--sys/fs/devfs/devfs_vfsops.c72
-rw-r--r--sys/fs/devfs/devfs_vnops.c406
4 files changed, 278 insertions, 245 deletions
diff --git a/sys/fs/devfs/devfs.h b/sys/fs/devfs/devfs.h
index e144a4b..c959e53 100644
--- a/sys/fs/devfs/devfs.h
+++ b/sys/fs/devfs/devfs.h
@@ -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));
diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
index 8b301c9..c3eb101 100644
--- a/sys/fs/devfs/devfs_devs.c
+++ b/sys/fs/devfs/devfs_devs.c
@@ -42,6 +42,21 @@
#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)
{
int i;
@@ -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);
diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c
index b5ccac4..d2fdda7 100644
--- a/sys/fs/devfs/devfs_vfsops.c
+++ b/sys/fs/devfs/devfs_vfsops.c
@@ -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);
}
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index e094589..86444ec 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -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 @@ loop:
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;
+
+ 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;
- de = ap->a_vp->v_data;
- if (ap->a_vp->v_type == VDIR)
+ if (nameiop == RENAME)
+ return (EOPNOTSUPP);
+
+ 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);
+ }
- 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;
+ 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 (ap->a_vap->va_gid != (gid_t)VNOVAL) {
- de->de_gid = ap->a_vap->va_gid;
- c = 1;
+
+ /*
+ * 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 (ap->a_vap->va_mode != (mode_t)VNOVAL) {
- de->de_mode = ap->a_vap->va_mode;
- c = 1;
+
+#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;
}
- 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);
+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);
}
@@ -516,6 +523,47 @@ devfs_revoke(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;
+ } */ *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 /* {
struct vnode *a_dvp;
@@ -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()
OpenPOWER on IntegriCloud