Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 26 Aug 2000 20:22:02 +0700 (ALMST)
From:      Boris Popov <bp@butya.kz>
To:        Poul-Henning Kamp <phk@freebsd.org>
Cc:        freebsd-current@freebsd.org
Subject:   devfs patch for review 
Message-ID:  <Pine.BSF.4.10.10008262000300.97704-200000@lion.butya.kz>

index | next in thread | raw e-mail

[-- Attachment #1 --]
	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/

[-- Attachment #2 --]
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 },
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.10.10008262000300.97704-200000>