Subject: Re: devfs, was Re: ptyfs fully working now...
To: Bill Studenmund <wrstuden@netbsd.org>
From: Christos Zoulas <christos@zoulas.com>
List: tech-kern
Date: 11/12/2004 21:08:24
On Nov 12,  4:13pm, wrstuden@netbsd.org (Bill Studenmund) wrote:
-- Subject: devfs, was Re: ptyfs fully working now...

| What do you have against devfs? Are your objections against devfs in
| general, or against a specific implementation (or implementations :-) ?
| 
| I ask as I really want us to have a devfs, however I've had a HUGE
| objection over time, and that is that the permissions on nodes need to
| persist across reboot. I suspect that this is your objection, however I'm=
| 
| not a mind reader and thus I'm not sure. :-)
| 
| My concern has been that we want device permissions to persist across
| reboot, and preferably across variations in configuration order. Jason's
| work on wedges has been one step in this direction, in that certain
| partitioning schemes name partitions. If we bind the device partitions to=
| 
| the name, then we do not need to worry as much about device config order,=
| 
| and devfs seems much safer. We can extend this pattern to bind to other
| devices too, though some devices may be more problematic than others.

Here's what I've been thinking. At boot time, you pass the mount struct
of devfs a filename which contains a list of commands to be applied to
it before it gets mounted. These have plain unix syntax and they can be

chown id:id name	# change ownership to a configured node
chmod mode name		# change permissions to a configured node
rm name			# whiteout a configured node
ln -s name		# make a symlink to an configured node if it exists
mkdir name		# create a directory
mknod name [b|c M M] [p]# create a node, for sockets we just create them.


This file gets loaded at mount time by the kernel into an internal hash table
that contains:
        LIST_ENTRY(devfsnode) hash;     /* hash chain */
	struct vnode    *vnode;   	/* vnode associated with this entry
	devfstype        type;     	/* type of devfs node */
	u_long          ptyfs_fileno;   /* unique file id */ 
	char		name[16];
	uid_t		uid;
	gid_t		gid;
	mode_t		mode;
	int		flags;		/* immutable etc */
	dev_t		dev;		/* if device, device info */
	/* the timestamps for the node */
	struct timespec	mtime;
	struct timespec	ctime;
	struct timespec	atime;
	struct timespec	birthtime;

	int		flag;		/* below */
#define DEVFS_OVERRIDE_MODE	0x01
#define DEVFS_OVERRIDE_UID	0x02
#define DEVFS_OVERRIDE_GID	0x04
#define DEVFS_WHITEOUT		0x08
#define DEVFS_MKDIR		0x10
#define DEVFS_SYMLINK		0x20	/* target to be looked up in a different
					 * table */
#define	DEVFS_MKNOD		0x40	

#define	DEVFS_ACCESSED		0x1000	/* Node was accessed */
#define	DEVFS_MODIFIED		0x2000	/* Node was written */
#define	DEVFS_CHANGED		0x4000	/* Node was changed perm/ownership */
#define	DEVFS_DIRTY		0x8000	/* Changes not reflected to the file */

This is the same struct used internally for book-keeping. When an mkdir,
chmod, chown, rm, ln -s operation is done on devfs, the change is reflected
on the internal memory table, and the DIRTY flag is set. Occasionally [once
a minute if flag is DIRTY, the file we loaded get written with the updated
permissions. Or if it is DIRTY it is written on unmount. The file can live
under the mount if we don't want it accessible. We also provide a simple
character device that when we cat it, it provides a textual description of
the current set of commands.

christos