afs: [DON'T MERGE] Do content encryption with an in-file trailer

To do content encryption, the data at the end of the file needs padding out
to crypto block size (e.g. 16 or 32 bytes for AES types), but that means we
need somewhere to store the actual file length with the padding removed.
Typically, this is stored in an xattr, though it could also be stored in
the file as an additional block at the front or end of the file.

With AFS, there are no xattrs and nowhere to store additional metadata, so
this information must be stored in the file.  Now, padding out the last
block to the fscrypt block size (4KiB, say) and then sticking a trailer
after it with the real size recorded therein is a problem for stat().  We
have to be able to read the file to be able to return the correct value in
st_size; further, if the trailer is at the end of the file rather than the
beginning, we can't guess where real size is recorded and speculatively use
the FetchData RPC rather than the FetchStatus RPC as we need to know
i_size.  Yet further, this doesn't work for bulk status fetch.

However, lacking a vectored StoreData RPC, we really want to store extra
metadata at the end of the file as StoreData "atomically" combines a
truncate and a data write which would allow us to update the metadata too.

With this in mind, implement another alternative:

 (1) Store zero-length files as zero-length on the server.  These are
     hereafter ignored in this description.

 (2) Place zeroed padding of one crypto block size (typically 16 or 32
     bytes) after the real EOF and always constant size for any particular
     file.  No information is stored here, though it may get partially
     encrypted.

 (3) Simply subtract the crypto block size from the server's file size to
     derive i_size.  This can be done when initialising/updating the inode
     and will work with bulk status fetch.

 (4) When encrypting the EOF block in a file, if partial, encrypt into the
     padding.

 (5) When decrypting the EOF block in a file, if partial, decrypt part of
     the padding.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: netfs@lists.linux.dev
13 files changed