Fernando Santos <[email protected]> wrote:
> Is there a way I can trace the original nfs file from the cache file?
The path can be decoded. Note that for the purposes of this, the base64
encoding I used is as follows:
"0123456789" /* 0 - 9 */
"abcdefghijklmnopqrstuvwxyz" /* 10 - 35 */
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 36 - 61 */
"_-" /* 62 - 63 */
not the traditional one as the traditional one includes the path separator
char '/' as one of the values.
> For example I have a cache file:
>
> /cache/fscache/cache/
We can ignore this.
> @4a/
256-bit hash/checksum of the index key. This is rendered as hex.
> I03nfs/
The initial 'I' indicates this is an index object. The remaining chars are:
(1) a length rendered as two base64-encoded chars, followed by
(2) the ASCII-encoded index key. The index key may be divided up into a
number of path segments if it would exceed 250 characters. Each segment
is a directory name. Segments after the first have a name prefixed with
a '+' character.
This is an entry in the first index and represents the network filesystem
name, in this case NFS.
> @6c/
256-bit hash...
> Jc000000000000Eg14Q40/
The initial 'J' indicates this is an index object that can't be represented as
straight ASCII. The remaining chars are:
(1) the base64-encoded index key. There is no length and the key is
zero-padded out to a multiple of 3 bytes (each group rendered as 4
chars). This may be split into names of 252 characters, with second and
subsequent names prefixed with a '+'.
In this case, the NFS second-level index is laid out as this.
struct nfs_server_key {
uint16_t nfsversion;
uint16_t family;
uint16_t port;
union {
struct in_addr ipv4_addr;
struct in6_addr ipv6_addr;
} addr[0];
};
Just remember, that the first three numbers are in host order. So the first 8
chars represent the three uint16_t values.
> @c8/
256-bit hash...
> J1100000000000g-x2E10000000000000000M20300080000w000Kb000wFe000jt000oG3000000040000g000000000/
Another 'J' index object.
In this case, the NFS third-level index represents the superblock key:
struct nfs_fscache_key {
...
struct {
struct {
unsigned long s_flags;
} super;
struct {
struct nfs_fsid fsid;
int flags;
unsigned int rsize;
unsigned int wsize;
unsigned int acregmin;
unsigned int acregmax;
unsigned int acdirmin;
unsigned int acdirmax;
} nfs_server;
struct {
rpc_authflavor_t au_flavor;
} rpc_auth;
u8 uniq_len;
char uniquifier[0];
} key;
};
The uniquifier at the end is optional and variable length.
> @97/
256-bit hash...
> Ew00g0000fBBvp1200000nYnCY_n3Ag-x2E1g0000fBBv0000
'D' and 'E' are data objects. The 'D' object has its index key encoded as for
'I' and 'E' as for 'J'.
This starting with an 'E' is base64-encoded after the 'E'.
This being the NFS fourth-level index is the NFS inode key. It encodes the
NFS inode file handle. The above is 48 chars. That would represent 48/4*3
or 36 bytes - or, more accurately, 34-36 bytes.
So you can recover the NFS FH from the above. Chop the 'E' off of the front.
Decode each group of 4 chars to into 3 bytes. Given that it's 36 bytes and
XDR likes 4-byte multiples, I would guess that the original handle was 36
bytes.
You may also need to decode the superblock key and extract the FSID.
David
--
Linux-cachefs mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/linux-cachefs