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 },