$Id: filehandles.txt,v 1.2 2001/05/17 13:48:37 mbp Exp $ What should we put into our NFS filehandles? version 2 fixed 32 bytes version 3 up to 64 bytes version 4 up to 128 bytes Most access to a file is going to happen over the same socket on which it was opened. So, the process on that socket can simply keep the filehandle open, and use {pid}.{fd} as the filehandle. The server can only allow a relatively small number of files to be open at any time across the whole system in any case (say 1024), so we will need to handle some files being closed and re-opened later. Simply having the FD is possibly not enough, since in some cases (e.g. LINK) we need to pass the name of the file We have some ability to pass filehandles between processes, either using Unix-domain messages, or opening /proc/{pid}/fd/{fd}. NFS2 and NFS3 filehandles have to be more persistent, so we possibly have to use a tdb to map from filehandles to names, or use a single process holding all the files open. We probably need to check access on every single request, whereas Unix only does access checks when the file is opened. "NFS Illustrated" gives these criteria for filehandles (at least for v2 and v3): 1. Persistence. Clients assume they are valid until the file or directory is removed from the server. 2. Pathname independence. Tries to implement UNIX semantics of files being renamed or unlinked while open. Callaghan observes this is a problem for servers implemented as a userspace process. unfsd (says Callaghan) stores a compresed pathname, with each pathname component hashed into an 8-bit quantity, and the file inode number included as a check. The filehandle becomes invalid if the file is renamed. READDIRPLUS in v3 returns a filehandle for each directory entry. So, we have to allow filehandles for files that are not open. Doing this in v2 and v3 is just too horrible -- this section of the unfsd code also has to worry about squashing (fs,inode) into a 32-bit inode, which is handled much better in v4. So, I'm inclined to start with just storing the whole path in the filehandle, and later on worrying about what we will do with files that are longer than 128 bytes. Oh, alternatively: when we get close to 128 bytes of filename, we could fold the first part into a shorter constant stored at the beginning, and then store the rest. So, we'd only need to write this out to stable storage when we discovered a filename which was very long, and didn't have a common prefix with any other existing file. Note from RFC3010: FH4_VOL_MIGRATION The filehandle will expire during file system migration. May only be set if FH4_VOLATILE_ANY is not set. FH4_VOL_RENAME The filehandle may expire due to a rename. This includes a rename by the requesting client or a rename by another client. May only be set if FH4_VOLATILE_ANY is not set. Realistically, we probably need FH4_VOL_RENAME and FH4_VOL_MIGRATION. Servers which provide volatile filehandles should deny a RENAME or REMOVE that would affect an OPEN file or any of the components leading to the OPEN file. In addition, the server should deny all RENAME or REMOVE requests during the grace or lease period upon server restart. This would be hard to enforce on Unix. On the other hand, it's only a `should'. If the server can definitively determine that a volatile filehandle refers to an object that has been removed, the server should return NFS4ERR_STALE to the client (as is the case for persistent filehandles). In all other cases where the server determines that a volatile filehandle can no longer be used, it should return an error of NFS4ERR_FHEXPIRED. On the question of handles to removed files, 3010 says: The concept of last reference is server specific. However, if the numlinks field in the previous attributes of the object had the value 1, the client should not rely on referring to the object via a file handle. Likewise, the client should not rely on the resources (disk space, directory entry, and so on) formerly associated with the object becoming immediately available. Thus, if a client needs to be able to continue to access a file after using REMOVE to remove it, the client should take steps to make sure that the file will still be accessible. The usual mechanism used is to RENAME the file from its old name to a new hidden name. So the responsibility is with the client, which is good. The client can get the new name, and recover a handle to that if necessary.