Hello, I've made some fixes in the fs layer of new devfs. First version of this patch was passed via Poul and new version includes parts of his suggestions. Here is a brief decription of the patch: Rename de_dir to de_parent with appropritate code changes. Implement proper logic and locking in the devfs_lookup(). Fix behaviour for '.' and '..' directories with corresponding changes in the devfs_readdir(). Implement devfs_read() operation for directories. Return proper mount owner in the devfs_statfs(). Fix panic related to the incorrect handling of root vnode. Few cosmetic changes as well. Code is still not SMP safe. -- Boris Popov http://www.butya.kz/~bp/
Index: devfs.h =================================================================== RCS file: /home/ncvs/src/sys/fs/devfs/devfs.h,v retrieving revision 1.2 diff -u -r1.2 devfs.h --- devfs.h 2000/08/24 15:36:47 1.2 +++ devfs.h 2000/08/26 12:28:52 @@ -48,10 +48,12 @@ #define DE_ORPHAN 0x1 #define DE_DOT 0x2 #define DE_DOTDOT 0x4 - struct dirent *de_dirent; + int de_type; + char * de_name; + int de_namelen; TAILQ_ENTRY(devfs_dirent) de_list; TAILQ_HEAD(, devfs_dirent) de_dlist; - struct devfs_dirent *de_dir; + struct devfs_dirent *de_parent; int de_links; mode_t de_mode; uid_t de_uid; @@ -68,7 +70,6 @@ }; struct devfs_mount { - struct vnode *dm_root; /* Root node */ struct devfs_dirent *dm_rootdir; struct devfs_dirent *dm_basedir; unsigned dm_generation; @@ -84,6 +85,7 @@ #define VFSTODEVFS(mp) ((struct devfs_mount *)((mp)->mnt_data)) +#define VNTODEVFS(vp) ((struct devfs_dirent *)(vp)->v_data) extern vop_t **devfs_vnodeop_p; extern vop_t **devfs_specop_p; @@ -93,6 +95,9 @@ void devfs_purge __P((struct devfs_dirent *dd)); struct devfs_dirent * devfs_vmkdir __P((char *name, int namelen, struct devfs_dirent *dotdot)); +int devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, + struct proc *proc); + #endif /* DEVFS_INTERN */ typedef void (*devfs_clone_fn) __P((void *arg, char *name, int namelen, dev_t *result)); Index: devfs_devs.c =================================================================== RCS file: /home/ncvs/src/sys/fs/devfs/devfs_devs.c,v retrieving revision 1.3 diff -u -r1.3 devfs_devs.c --- devfs_devs.c 2000/08/24 15:36:47 1.3 +++ devfs_devs.c 2000/08/26 11:49:49 @@ -46,16 +46,13 @@ { int i; struct devfs_dirent *de; - struct dirent d; - d.d_namlen = namelen; - i = sizeof (*de) + GENERIC_DIRSIZ(&d); + i = sizeof (*de) + namelen + 1; MALLOC(de, struct devfs_dirent *, i, M_DEVFS, M_WAITOK); bzero(de, i); - de->de_dirent = (struct dirent *)(de + 1); - de->de_dirent->d_namlen = namelen; - de->de_dirent->d_reclen = GENERIC_DIRSIZ(&d); - bcopy(name, de->de_dirent->d_name, namelen + 1); + de->de_name = (char *)(de + 1); + de->de_namelen = namelen; + bcopy(name, de->de_name, namelen); nanotime(&de->de_ctime); de->de_mtime = de->de_atime = de->de_ctime; de->de_links = 1; @@ -63,36 +60,23 @@ } struct devfs_dirent * -devfs_vmkdir(char *name, int namelen, struct devfs_dirent *dotdot) +devfs_vmkdir(char *name, int namelen, struct devfs_dirent *parent) { - struct devfs_dirent *dd; struct devfs_dirent *de; - dd = devfs_newdirent(name, namelen); + de = devfs_newdirent(name, namelen); - TAILQ_INIT(&dd->de_dlist); + TAILQ_INIT(&de->de_dlist); - dd->de_dirent->d_type = DT_DIR; - dd->de_mode = 0755; - dd->de_links = 2; - dd->de_dir = dd; - - de = devfs_newdirent(".", 1); - de->de_dirent->d_type = DT_DIR; - de->de_dir = dd; - de->de_flags |= DE_DOT; - TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); - - de = devfs_newdirent("..", 2); - de->de_dirent->d_type = DT_DIR; - if (dotdot == NULL) - de->de_dir = dd; - else - de->de_dir = dotdot; - de->de_flags |= DE_DOTDOT; - TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); + de->de_type = DT_DIR; + de->de_mode = 0755; + de->de_links = 2; - return (dd); + if (parent) { + de->de_parent = parent; + TAILQ_INSERT_TAIL(&parent->de_dlist, de, de_list); + } + return (de); } static void @@ -125,7 +109,6 @@ FREE(dd, M_DEVFS); } - int devfs_populate(struct devfs_mount *dm) { @@ -145,7 +128,7 @@ continue; } if (dev == NULL && de != NULL) { - dd = de->de_dir; + dd = de->de_parent; dm->dm_dirent[i] = NULL; TAILQ_REMOVE(&dd->de_dlist, de, de_list); if (de->de_vnode) { @@ -166,9 +149,9 @@ continue; if (*q == '/') { TAILQ_FOREACH(de, &dd->de_dlist, de_list) { - if (de->de_dirent->d_namlen != q - s) + if (de->de_namelen != q - s) continue; - if (bcmp(de->de_dirent->d_name, s, q - s)) + if (bcmp(de->de_name, s, q - s)) continue; goto fdir; } @@ -187,7 +170,7 @@ de->de_uid = 0; de->de_gid = 0; de->de_mode = 0666; - de->de_dirent->d_type = DT_LNK; + de->de_type = DT_LNK; pdev = dev->si_drv1; j = strlen(pdev->si_name) + 1; MALLOC(de->de_symlink, char *, j, M_DEVFS, M_WAITOK); @@ -197,7 +180,7 @@ de->de_uid = dev->si_uid; de->de_gid = dev->si_gid; de->de_mode = dev->si_mode; - de->de_dirent->d_type = DT_CHR; + de->de_type = DT_CHR; } dm->dm_dirent[i] = de; TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); Index: devfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/devfs/devfs_vfsops.c,v retrieving revision 1.3 diff -u -r1.3 devfs_vfsops.c --- devfs_vfsops.c 2000/08/24 15:36:47 1.3 +++ devfs_vfsops.c 2000/08/26 11:49:49 @@ -79,30 +79,23 @@ return (EOPNOTSUPP); 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); @@ -127,13 +120,15 @@ { int error; int flags = 0; - struct vnode *rootvp = VFSTODEVFS(mp)->dm_root; - struct devfs_mount *fmp; + struct devfs_mount *fmp = VFSTODEVFS(mp); + struct vnode *rootvp; - fmp = (struct devfs_mount*) mp->mnt_data; if (mntflags & MNT_FORCE) flags |= FORCECLOSE; + error = VFS_ROOT(mp, &rootvp); + if (error) + return (error); /* * Clear out buffer cache. I don't think we * ever get anything cached at this level at the @@ -146,6 +141,7 @@ if (error) return (error); + vput(rootvp); /* * Release reference on underlying root vnode */ @@ -157,8 +153,8 @@ /* * Finally, throw away the devfs_mount structure */ - free(mp->mnt_data, M_DEVFS); - mp->mnt_data = 0; + mp->mnt_data = (qaddr_t)0; + free(fmp, M_DEVFS); return 0; } @@ -167,15 +163,18 @@ struct mount *mp; struct vnode **vpp; { + struct devfs_mount *dmp = VFSTODEVFS(mp); struct proc *p = curproc; /* XXX */ struct vnode *vp; + int error; /* * Return locked reference to root. */ - vp = VFSTODEVFS(mp)->dm_root; - VREF(vp); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + error = devfs_allocv(dmp->dm_rootdir, mp, &vp, p); + if (error) + return error; + vp->v_flag |= VROOT; *vpp = vp; return (0); } @@ -197,6 +196,7 @@ sbp->f_ffree = 0; if (sbp != &mp->mnt_stat) { sbp->f_type = mp->mnt_vfc->vfc_typenum; + sbp->f_owner = mp->mnt_stat.f_owner; /* user that mounted the +filesystem */ bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); Index: devfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/devfs/devfs_vnops.c,v retrieving revision 1.3 diff -u -r1.3 devfs_vnops.c --- devfs_vnops.c 2000/08/24 15:36:47 1.3 +++ devfs_vnops.c 2000/08/26 12:29:22 @@ -53,7 +53,7 @@ #include <fs/devfs/devfs.h> #define KSTRING 256 /* Largest I/O available via this filesystem */ -#define UIO_MX 32 +#define DE_SIZE (sizeof(struct dirent)) static int devfs_access __P((struct vop_access_args *ap)); static int devfs_badop __P((void)); @@ -69,16 +69,18 @@ static int devfs_symlink __P((struct vop_symlink_args *ap)); -static int -devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct proc *p) +int +devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, + struct proc *proc) { - int error; + struct proc *p = proc ? proc : curproc; /* XXX */ struct vnode *vp; + int error; loop: vp = de->de_vnode; if (vp != NULL) { - if (vget(vp, 0, p ? p : curproc)) + if (vget(vp, LK_EXCLUSIVE, p)) goto loop; *vpp = vp; return (0); @@ -89,13 +91,13 @@ return (error); } - if (de->de_dirent->d_type == DT_CHR) { + if (de->de_type == DT_CHR) { vp->v_type = VCHR; vp = addaliasu(vp, devfs_inot[de->de_inode]->si_udev); vp->v_op = devfs_specop_p; - } else if (de->de_dirent->d_type == DT_DIR) { + } else if (de->de_type == DT_DIR) { vp->v_type = VDIR; - } else if (de->de_dirent->d_type == DT_LNK) { + } else if (de->de_type == DT_LNK) { vp->v_type = VLNK; } else { vp->v_type = VBAD; @@ -103,9 +105,29 @@ vp->v_data = de; de->de_vnode = vp; vhold(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); *vpp = vp; return (0); } + +static int +devfs_de_lookup(struct vnode *dvp, const char *name, int namelen, + struct devfs_dirent **depp) +{ + struct devfs_dirent *dd, *de; + + devfs_populate(VFSTODEVFS(dvp->v_mount)); + dd = VNTODEVFS(dvp); + TAILQ_FOREACH(de, &dd->de_dlist, de_list) { + if (namelen != de->de_namelen || + bcmp(name, de->de_name, namelen) != 0) + continue; + *depp = de; + return 0; + } + return ENOENT; +} + /* * vp is the current namei directory * ndp is the name to locate in that directory... @@ -121,47 +143,67 @@ struct componentname *cnp = ap->a_cnp; struct vnode **vpp = ap->a_vpp; struct vnode *dvp = ap->a_dvp; - char *pname = cnp->cn_nameptr; + char *name = 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]; + int flags = cnp->cn_flags; + int isdotdot = flags & ISDOTDOT; + int namelen = cnp->cn_namelen; + int nameiop = cnp->cn_nameiop; + int lockparent, wantparent, error, islastcn, i; *vpp = NULLVP; -#if 0 - error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc); + if (dvp->v_type != VDIR) + return ENOTDIR; + + if (isdotdot && (dvp->v_flag & VROOT)) + return EIO; + + error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc); if (error) return (error); -#endif + + if (nameiop == RENAME) + return EOPNOTSUPP; - VOP_UNLOCK(dvp, 0, p); - if (cnp->cn_namelen == 1 && *pname == '.') { + if (namelen == 1 && name[0] == '.') { + if (nameiop != LOOKUP) + return EINVAL; *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; + dd = VNTODEVFS(dvp); + islastcn = flags & ISLASTCN; + lockparent = flags & LOCKPARENT; + wantparent = flags & (LOCKPARENT | WANTPARENT); + + if (isdotdot) { + if (nameiop != LOOKUP) + return EINVAL; + VOP_UNLOCK(dvp, 0, p); + de = dd->de_parent; + error = devfs_allocv(de, dvp->v_mount, vpp, p); + if (error) { + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); + return error; + } + if (lockparent && islastcn && + (error = vn_lock(dvp, LK_EXCLUSIVE, p))) { + vput(*vpp); + return error; + } + return 0; } - if (!cloned) { + dmp = VFSTODEVFS(dvp->v_mount); + error = devfs_de_lookup(dvp, name, namelen, &de); + if (error) { /* * 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. @@ -171,24 +213,21 @@ */ i = SPECNAMELEN; specname[i] = '\0'; - i -= cnp->cn_namelen; + i -= namelen; if (i < 0) goto noclone; - bcopy(cnp->cn_nameptr, specname + i, cnp->cn_namelen); + bcopy(name, specname + i, namelen); de = dd; - while (de != dmp->dm_basedir) { + while (de->de_parent) { i--; if (i < 0) goto noclone; specname[i] = '/'; - i -= de->de_dirent->d_namlen; + i -= de->de_namelen; 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; + bcopy(de->de_name, specname + i, de->de_namelen); + de = de->de_parent; } #if 0 @@ -201,47 +240,44 @@ printf("cloned %s -> %p %s\n", specname + i, cdev, cdev == NODEV ? "NODEV" : cdev->si_name); #endif - if (cdev != NODEV) { - cloned = 1; - goto again; - } + if (cdev != NODEV) + error = devfs_de_lookup(dvp, name, namelen, &de); } - 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); + if (error) { + /* + * No valid entry was found + */ + if ((nameiop == CREATE || nameiop == RENAME) && + wantparent && islastcn) { + cnp->cn_flags |= SAVENAME; + if (!lockparent) + VOP_UNLOCK(dvp, 0, p); + return (EJUSTRETURN); + } 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 (nameiop == DELETE && islastcn) { + error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, p); + if (error) + return (error); if (*vpp == dvp) { VREF(dvp); *vpp = dvp; return (0); } - VREF(*vpp); - if (!(cnp->cn_flags & LOCKPARENT)) + error = devfs_allocv(de, dvp->v_mount, vpp, p); + if (error) + return (error); + if (!lockparent) VOP_UNLOCK(dvp, 0, p); return (0); } - vn_lock(*vpp, LK_SHARED | LK_RETRY, p); - if (!(cnp->cn_flags & LOCKPARENT)) + error = devfs_allocv(de, dvp->v_mount, vpp, p); + if (error) + return error; + if (!lockparent || !islastcn) VOP_UNLOCK(dvp, 0, p); return (0); } @@ -256,11 +292,7 @@ } */ *ap; { struct vnode *vp = ap->a_vp; - struct devfs_dirent *de; - - de = vp->v_data; - if (vp->v_type == VDIR) - de = de->de_dir; + struct devfs_dirent *de = VNTODEVFS(vp); return (vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid, ap->a_mode, ap->a_cred)); @@ -277,13 +309,10 @@ { struct vnode *vp = ap->a_vp; struct vattr *vap = ap->a_vap; + struct devfs_dirent *de = VNTODEVFS(vp); int error = 0; - struct devfs_dirent *de; dev_t dev; - de = vp->v_data; - if (vp->v_type == VDIR) - de = de->de_dir; bzero((caddr_t) vap, sizeof(*vap)); vattr_null(vap); vap->va_uid = de->de_uid; @@ -308,11 +337,12 @@ vap->va_nlink = de->de_links; vap->va_fileid = de->de_inode; - if (de->de_dirent->d_type == DT_DIR) { + if (de->de_type == DT_DIR) { vap->va_type = VDIR; - } else if (de->de_dirent->d_type == DT_LNK) { + vap->va_size = 512; /* any non-zero value */ + } else if (de->de_type == DT_LNK) { vap->va_type = VLNK; - } else if (de->de_dirent->d_type == DT_CHR) { + } else if (de->de_type == DT_CHR) { vap->va_type = VCHR; vap->va_rdev = devfs_inot[de->de_inode]->si_udev; } @@ -334,31 +364,30 @@ } */ *ap; { struct devfs_dirent *de; + struct vattr *vap = ap->a_vap; int c; - de = ap->a_vp->v_data; - if (ap->a_vp->v_type == VDIR) - de = de->de_dir; + de = VNTODEVFS(ap->a_vp); c = 0; - if (ap->a_vap->va_flags != VNOVAL) + if (vap->va_flags != VNOVAL) return (EOPNOTSUPP); - if (ap->a_vap->va_uid != (uid_t)VNOVAL) { - de->de_uid = ap->a_vap->va_uid; + if (vap->va_uid != (uid_t)VNOVAL) { + de->de_uid = vap->va_uid; c = 1; } - if (ap->a_vap->va_gid != (gid_t)VNOVAL) { - de->de_gid = ap->a_vap->va_gid; + if (vap->va_gid != (gid_t)VNOVAL) { + de->de_gid = vap->va_gid; c = 1; } - if (ap->a_vap->va_mode != (mode_t)VNOVAL) { - de->de_mode = ap->a_vap->va_mode; + if (vap->va_mode != (mode_t)VNOVAL) { + de->de_mode = 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 (vap->va_atime.tv_sec != VNOVAL) + de->de_atime = vap->va_atime; + if (vap->va_mtime.tv_sec != VNOVAL) + de->de_mtime = vap->va_mtime; if (c) getnanotime(&de->de_ctime); @@ -366,6 +395,22 @@ } static int +devfs_read(struct vop_read_args *ap) + /*struct vop_read_args { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; + } */ +{ + struct vnode *vp = ap->a_vp; + + if (vp->v_type != VDIR) + return (EINVAL); + return (VOP_READDIR(vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL)); +} + +static int devfs_readdir(ap) struct vop_readdir_args /* { struct vnode *a_vp; @@ -376,40 +421,64 @@ u_long **a_cookies; } */ *ap; { - int error, i; + struct vnode *vp = ap->a_vp; struct uio *uio = ap->a_uio; - struct dirent *dp; - struct devfs_dirent *dd; - struct devfs_dirent *de; + struct dirent *dp, dirent; + struct devfs_dirent *dd, *de; struct devfs_mount *dmp; off_t off; + int error, entryid, i; if (ap->a_vp->v_type != VDIR) return (ENOTDIR); + + if (ap->a_ncookies) { + printf("devfs_readdir: cookies not supported\n"); + return EOPNOTSUPP; + } - dmp = VFSTODEVFS(ap->a_vp->v_mount); + if (uio->uio_resid < DE_SIZE || uio->uio_offset < 0) + return EINVAL; + + dmp = VFSTODEVFS(vp->v_mount); devfs_populate(dmp); - i = (u_int)off / UIO_MX; + + off = uio->uio_offset; + entryid = off / DE_SIZE; error = 0; - de = ap->a_vp->v_data; - dd = TAILQ_FIRST(&de->de_dlist); - off = 0; - while (uio->uio_resid >= UIO_MX && dd != NULL) { - if (dd->de_dirent->d_type == DT_DIR) - de = dd->de_dir; - else - de = dd; - dp = dd->de_dirent; - dp->d_fileno = de->de_inode; - if (off >= uio->uio_offset) - if ((error = uiomove((caddr_t)dp, dp->d_reclen, uio)) != 0) - break; + dd = VNTODEVFS(vp); + + de = TAILQ_FIRST(&dd->de_dlist); + for (i = entryid - 2; de && i > 0; i--) + de = TAILQ_NEXT(de, de_list); + + dp = &dirent; + while (uio->uio_resid >= DE_SIZE && de != NULL) { + bzero(dp, DE_SIZE); + dp->d_reclen = DE_SIZE; + switch (entryid) { + case 0: + case 1: + dp->d_name[0] = dp->d_name[1] = '.'; + dp->d_fileno = (entryid == 0) ? dd->de_inode : + (dd->de_parent ? dd->de_parent->de_inode : 1); + dp->d_namlen = entryid + 1; + dp->d_name[entryid + 1] = '\0'; + dp->d_type = DT_DIR; + break; + default: + dp->d_fileno = de->de_inode; + dp->d_namlen = de->de_namelen; + dp->d_type = de->de_type; + bcopy(de->de_name, dp->d_name, de->de_namelen + 1); + de = TAILQ_NEXT(de, de_list); + } + if ((error = uiomove((caddr_t)dp, dp->d_reclen, uio)) != 0) + break; off += dp->d_reclen; - dd = TAILQ_NEXT(dd, de_list); + entryid++; } - uio->uio_offset = off; - return (error); } @@ -424,7 +493,7 @@ int error; struct devfs_dirent *de; - de = ap->a_vp->v_data; + de = VNTODEVFS(ap->a_vp); error = uiomove(de->de_symlink, strlen(de->de_symlink) + 1, ap->a_uio); return (error); } @@ -504,26 +573,24 @@ char *a_target; } */ *ap; { - int i; - struct devfs_dirent *dd; + struct vnode *dvp = ap->a_dvp; + struct devfs_mount *dmp = VFSTODEVFS(dvp->v_mount); + struct devfs_dirent *dd = VNTODEVFS(dvp); struct devfs_dirent *de; - struct devfs_mount *dmp; + char *target = ap->a_target; + int i; - dmp = (struct devfs_mount *)ap->a_dvp->v_mount->mnt_data; - dd = ap->a_dvp->v_data; de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen); de->de_uid = 0; de->de_gid = 0; de->de_mode = 0642; de->de_inode = dmp->dm_inode++; - de->de_dirent->d_type = DT_LNK; - i = strlen(ap->a_target) + 1; + de->de_type = DT_LNK; + i = strlen(target) + 1; MALLOC(de->de_symlink, char *, i, M_DEVFS, M_WAITOK); - bcopy(ap->a_target, de->de_symlink, i); + bcopy(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); + return devfs_allocv(de, dvp->v_mount, ap->a_vpp, 0); } /* @@ -542,7 +609,7 @@ } /* - * Kernfs "should never get here" operation + * devfs "should never get here" operation */ static int devfs_badop() @@ -559,6 +626,7 @@ { &vop_lookup_desc, (vop_t *) devfs_lookup }, { &vop_pathconf_desc, (vop_t *) vop_stdpathconf }, { &vop_print_desc, (vop_t *) devfs_print }, + { &vop_read_desc, (vop_t *) devfs_read }, { &vop_readdir_desc, (vop_t *) devfs_readdir }, { &vop_readlink_desc, (vop_t *) devfs_readlink }, { &vop_reclaim_desc, (vop_t *) devfs_reclaim },