tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

mjf-devfs2 branch

Hash: SHA1

As some of you may know I've been working devfs support for NetBSD as
part of a project for my final year at the University of Leeds.

The project exists on the mjf-devfs2 branch in cvs and is at the point
now where I need some testing from people other than myself. However,
I must warn you that this branch is still highly experimental and many
device drivers have not been converted to the new world order of
device node registration, which means that if you mount a devfs over
/dev (which happens by default unless you turn off devfs support at
boot with the -n option) some device nodes that you may need, will
not appear. I intend to continue converting device drivers on this
branch and if anyone wants to write patches for device drivers and
send them to me, I'd really appreciate it.

To test you can either build a distribution from the mjf-devfs2 branch
and do a fresh install, which is the recommended way, or drop the userland 
applications (devfsd, mount_devfs) onto a current userland and run a 
devfs-kernel. The problem with the second approach is that you can't replace
/sbin/init with the patched version on the mjf-devfs2 branch and so, if
you ever need to do any maintenance work in single-user mode whilst running
your devfs kernel, you will have to manually run devfsd -s, otherwise
/dev will not be populated with device nodes.

In the kernel config you must add some options,

file-system     DEVFS
pseudo-device   dctl

Now, onto the design. My devfs implementation consists of 3 parts,
        * devfsd: the userland daemon that controls the naming policy
                  of devfs.
        * devfs: the file system code for the device file system.
        * dctl: the devfs control device node that allows devfsd to
                communicate with and manipulate devfs mounts. This
                device node is also responsible for notifying devfsd of
                new devices being attached to the system.

devfsd reads a configuration file when it starts up and this config file 
contains rules that govern the attributes of device nodes. These rules
dictate everything about a device node, including:
        * filename
        * mode
        * owner/group
        * visibility

See etc/devfsd.conf on the mjf-devfs2 branch for examples of some rules.
Filename, mode and owner/group should be fairly obvious attributes. 
Visibility specifies whether a device node is visible to userland. This
can be useful for chroot jails where you only want a limited number
of device nodes to be available in /dev (despite the fact that other
devices are in fact attached to the system). You can have multiple
devfs mounts on a system at one time and each mount can have a different
default visibility.

Now, in order to be able to apply a rule to a device node we need to
have some means of "matching". This part of the system is not currently
implemented fully and the best way to match a device is by specifying
a kernel driver name. This will be extended in the future to allow you
to match a rule by other attributes of a device, UUID, manufacturer,
model, etc.

Now, for people who are unfamiliar with devfs, this is the really cool
thing about the rules approach. You can write a rule that gives the
device node a specific name (matching the device by some unique attribute)
so that you can be sure that, regardless of where the device is attached
in the bus topology, the same device node can be used to access the same
device every time. An example of this is if you have a USB pen which has
an FFS partition on it and you have a rule that matches any sd(4) device
that contains an FFS partition with a filename attribute of "my_usb_pen",
then pluggin in the pen will result in a /dev/my_usb_pen device node, 
regardless of which USB port you plug the pen in to.

There are obviously more details of this project, but I don't think
there's much point including them here as the post is pretty long anyway.
The details of this implementation are in the code on the mjf-devfs2 branch
and will be in the final report that I write as part of my university project.
This report will be finished by the end of April and I'll follow up to this
post with a link when it's complete.

With a devfs-enabled kernel a devfs file system is mounted over /dev
during the boot process, after all devices have been found and before
/sbin/init runs. We do it at this time so that init has access to a
console device node in /dev. When init runs it will spawn a devfsd
process with the -s option. The -s option tells devfsd to run, gather
information about all devices on the system, push nodes into any devfs
mounts and exit. When moving from single-user to multi-user mode, devfsd
is the first daemon to run (this time it runs in the background).

Now, for device driver conversion. I've provided an API that device drivers
can use when they need device nodes,

int device_register_name(dev_t, device_t, boolean_t, enum devtype, 
        const char *, ...);

'devtype' specifies the type of device which will be used for matching rules.
See sys/sys/conf.h for details.

int device_unregister_name(dev_t, const char *, ...);

We maintain a TAILQ of structs which is appended with the register function
and has entries removed with the unregister function. When a new struct is
added to this queue dctl(4) creates a message and places it on an internal
queue which is picked up by devfsd(8).

Now, an example of how to convert a device driver,

mydriver_attach(struct device *parent, struct device *self, void *aux)
        int major = cdevsw_lookup_major(&mydriver_cdevsw);
        int unit = device_unit(self);

        device_register_name(makedev(major, unit), self, true, 
            DEV_OTHER, "mydriver%d", unit);

mydriver_detach(struct device *self, int flags)
        int major = cdevsw_lookup_major(&mydriver_cdevsw);
        int unit = device_unit(self);

        device_unregister_name(makedev(major, unit), "mydriver%d", unit);
        return 0;

I'm going to keep a list of things that need to be done (and things that
are finished) on,

If you'd like further explanation about any of the points, just shout.

Further Work:
        - Continue converting device drivers to new world order
        - Manipulating device nodes with chmod(1)/chgrp(1) needs to update
          the rules in devfsd accordingly. These rules will be written to
          the configuration file to allow them to persist across reboots.
        - Extend the "matching" code of the rules framework to allow us
          to match by different attributes of devices
        - Once device drivers are all converted, move to dynamic major
        - Provide an "upgrade path" to make it easy for people to move into
          the new devfs world

- --mjf
Version: GnuPG v1.4.8 (NetBSD)


Home | Main Index | Thread Index | Old Index