device clone on open

Matthew Dillon dillon at
Sat Jan 14 16:37:24 PST 2006

:I'd like to implement device cloning on open, as that would be of great 
:use for pcm:
:We already have vchans, i.e. we can play multiple sound sources mixed at 
:the same time, but programs need to open /dev/dsp0.{0,1,2,3} to do this.
:It would be much more convenient if programs just could use /dev/dsp and 
:the pcm driver hands out virtual channels as long as they are available.
:For this to work, we'd have to change the vnode in the fp.  I'm a little 
:bit confused how complicated this devices stuff is in the kernel.  

    You don't actually have to change the vnode in the fp.  It should be
    possible to clone and route the correct device with the existing 
    infrastructure by fixing the VOP_OPEN/VOP_CLOSE code. 

    VOP_OPEN and VOP_CLOSE are a huge mess because they operate on
    vnodes that have already been created (as you probably noticed),
    and they are an even bigger mess when you open a device because
    now the code is trying to track an open count for shared access 
    in the vnode AND in the device structure.  

:Why do we need to route everything over vnodes anyways?  Whatever.
:Is there a way to accomplish this?  Anybody got some ideas?
:   simon

    Well, the crux of the problem are system calls like fchown() and
    fchmod(), expecting the access and modified times to be updated in
    the filesystem for device accesses, and system calls like
    read() and write() which you really want to have go direct to the

    In my opinion, the real problem is simply an overabundance of hacks.
    We have fileops as a hack to bypass the overhead of vnode operations
    which in turn are overloaded on top of other vnode functions (specfs)
    to convert the vnode I/O calls into device I/O calls due to the
    bad design decision of giving the two totally different I/O mechanisms
    (e.g. VOP_READ/VOP_WRITE vs VOP_STRATEGY).  We have huge hacks in

    It's a real mess.  If you want to go about solving it I have some

    * Make VOP_OPEN/VOP_CLOSE explicit operations and allow them to 
      return a different vnode then the one supplied. 

      The idea here is that namecache resolution can resolve to a vnode
      as it currently does, but that this is considered DIFFERENT from
      actually opening the file or device, and can be a DIFFERENT vnode
      from the one you get when you actually do an open().

    * The namecache remains unchanged.  The vnode stored in the namecache
      is, e.g. the vnode representing the device inode as it exists in the

    * Have room for both the namespace vnode and the actual openned vnode in
      the file descriptor (struct file in sys/file.h).

      This allows us to get rid of all the specfs hacks that each and every
      filesystem (such as UFS) have to do to merge filesystem operations
      with device operations.

    * Get rid of fileops.  Make everything go through the vnode subsystem.
      Sockets, pipes, devices, everything.  Have a temporary shim for
      devices so we don't have to rewrite all the device drivers as part
      of this stage of the work (i.e. keep specfs in some form or another).

      A file descriptor would represent a vnode, period.  Actually two vnodes:
      The namespace vnode (i.e. the file/device inode in the filesystem), and
      the operations vnode (i.e. the actual open file or device, which in
      your case could be a different vnode reprenting the 'clone').

      All operations would run through VOPs.  System calls and filesystem
      operations such as read or write would first through the operations
      vnode and if the operation is not supported wouuld then back-off to
      the namespace vnode.

      So, for example, if you open() a device and try to do a fchmod() of
      the resulting file descriptor, it would try to do the opration on
      the opened device vnode which would return ENOTSUP, then back-off
      and use the namespace vnode which of course would work.  If the two
      vnodes happen to be the same (such as for a normal file), it winds up
      being a simple degenerate case.

      Namespace-specific system calls such as chown() would only run through
      the namespace vnode since there would not be an operations vnode (or
      a file descriptor for that matter) for such operations.

      Would you like to take on such a project?  I believe it could be done
      in mid-sized committable pieces.

					Matthew Dillon 
					<dillon at xxxxxxxxxxxxx>

More information about the Kernel mailing list