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

VFS Proposal



Hi All.

I spent a little while today thinking over how to layout the VFS, and
this is what I have right now.  Keep in mind that this was hashed out
before we had the ok on the existing code, so everything is called
something different.  On the bright side, structurally it is very
similar (the underlying file-system abstraction is handled a little
differently).

Also keep in mind this is far from complete, and is intended only as a
proof of concept.

We start by maintaining a top-level abstraction very similar to the
current one.  I'll call it a "protocol" abstraction for want of a better
term.

The idea is that for each protocol (where protocol is something along
the lines of "file", "tftp", "http", ...), we maintain a structure of
protocol ops viz:

struct __proto_ops {
  int (*verify)(char *filename);   // Determine if we can handle it
  int (*open)(...);
  int (*close)(...);
  int (*read)(...);
  int (*seek)(...);
  int (*tell)(...);
  int (*opendir)(...);
  int (*readdir)(...);
  int (*closedir)(...);
};

I'll also present an additional structure here, to aid the explanation
below.

struct __fd {
  int fd;
  struct __proto_ops *ops;
  void *protodata;
};

Now consider a call to generic open().  It needs to take the following
actions:

(1) - Parse the filename
(2) - Determine the correct protocol (call "verify" until one is happy?)
(3) - Allocate an underlying file descriptor (which is managed within
      the generic functions), and a corresponding __fd structure.
(4) - Fill in __fd.ops with the appropriate protocol
(5) - Call __fd.ops->open(...)
(6) - Massage the return value, and clean up appropriately

Handling things in this manner, we can drop in new protocols without
trouble... we need only ensure that their verify functions don't overlap
on the range of acceptable names.

Now consider the file protocol (since this is where we're starting).

At the file level, we require a similar level of abstraction.  For each
filesystem type known to the system, we have a structure like the
following:

struct __fileops {
  int verify(...);
  int open(...);
  int close(...);
  int read(...);
  int seek(...);
  int tell(...);
  int opendir(...);
  int readdir(...);
  int closedir(...);
};

And also consider:

struct __filedata {
  struct __fileops fops;
  ??
};

When the generic open ends up calling the file open, we have the
following sequence of events:

(1) - Parse the filename (if necessary)
(2) - Determine the correct filesystem type (through verify?)
(3) - Allocate the necessary private structure (__filedata... this will
      be returned and stored as the parent's "protodata", and passed
      into each subsequent call).
(4) - Call the file system driver open
(5) - Massage results
(6) - Cleanup and return

And that's the general idea... almost all other operations are analogous
(yeah yeah, I'm skipping over a lot of detail here).

Random thoughts:

- Do we want to allow a device level abstraction, whereby the top level
  protocol determines the device and passes a device object down to all
  lower protocols (ie typically it'd just be an OF block device,
  but...)?

- If not, who is responsible for determining the appropriate device?

- Should things like file position (tell et al), be left to the
  low-level drivers (where possible), or kept at higher layers.

Obviously, the amount of state data kept in the various places will need
to change (as implementation problems are discovered).  But this is a
first pass.  It's quite similar to what we currently have.

Anyway, this is rather haphazard (loooooong day today), but I'll try to
think things through a bit better tomorrow, and see if I can spot any
holes.  I'll also take a closer look at the existing VFS stuff.

Flame away,
--Andrew