Ion and I ported our stacking templates to the last few releases, including
2.3.99-pre9.  We had to create a fake struct file inside our ->truncate
method so we can pass it to some as-ops methods.  We believe that sooner or
later, truncate (and notify_change and friends) may need to have a struct
file passed to them.  This has become more evident since the recent cleanup
of the as-ops.

Some background: our stacking templates support file systems that change
data size, and we used that in our compression f/s, gzipfs.  When data is
written in the middle of a compressed file, the new sequence may be shorter
or longer than the previous sequence, so we handle it by shifting the data
in the compressed file inward/outward as needed.  Truncate() can be used to
shrink a file or extend it.  When truncate is called to shrink a file, we
first check if the truncation occurs in the middle of a compressed sequence
and we re-compress the remaining bytes to ensure data validity.  When
truncate is used to enlarge a file, we often have to compress a "chunk" of
data that contains some bytes at the previous end of the file, and now with
zeros afterwards.  A truncation that increases the file's size may also
result in multiple holes created.

Anyway, there are lots more details to our stacking support for
size-changing file systems, all of which we've outlined in a paper if anyone
is interested.  The key point for this message is that our code has to
perform data and page operations on a file from inside the ->truncate
method.  But truncate doesn't have a struct file.  It has a dentry (and
hence an inode), but that's not enough because the new address ops require
passing a struct file to them.

We've managed to hack around this by creating a fake struct file, stuffing
the dentry that we get in ->truncate, and pass that file around.  It seems
to work so far, but it's an ugly solution that may not work in the long run.
Having to create fake objects is a possible indication that something is
missing from an API.

For now we're ok, but I think we should consider passing a struct file to
->truncate, and maybe even move ->truncate from inode ops to as-ops.  Here
are a brief list of reasons:

(1) truncate is fundamentally an operation that is asked to operate on a
    file without being given a file to operate on.  Truncating or enlarging
    a file implies munging data pages.

(2) ftruncate(2) takes an open fd, meaning that a struct file must already
    exist in the kernel b/c a user process opened it.  truncate(2) takes a
    pathname, which the kernel must translate somehow into a file and/or a
    dentry.  This is further reason that the two syscalls are probably
    implemented in the kernel using a struct file, so it should be possible
    to pass that struct file further down.

(3) if we pass a struct file to ->truncate instead of a dentry, very little
    change will be required to actual file systems.  The changes to the VFS
    may not be simple however.  My quick inspections showed that
    notify_change and friends don't have an easy access to a struct file.

(4) our stacking code can certainly use a struct file passed to ->truncate,
    and that would help us get rid of the ugly fake file we have to create
    now.  If at any point in the future someone (NFS?) may need to put
    something inside the private data of struct file, then it would be
    necessary to pass a struct file to ->truncate.

Comments?

Thanks,
Erez.

Reply via email to