Better read-ahead management and other file-open issues

NFS (prior to V4) does not have a concept of opening and closing a file. The Linux VFS does include that concept. So the NFS server has to open the file before a READ or WRITE operation, and close it afterwards.

Some funcitonality in filesystems and in the VFS assumes that the open/close requests that are passed down correspond to opens and closes by the application, and that a particular "file" structure belongs to a particular application (possibly a group of processes). Thus he current open/IO/close approach does not give good information to filesystems

One particular example is READ-AHEAD. The VFS layer does read-ahead when it detects that an application is sequentially accessing a file. Having the NFS server benefit from this improves read speed.

As the read-ahead state information is stored in the struct file, and as we only have a struct file for a short period of time, the READ-AHEAD does not automatically work.

Currently, we take a copy of read-ahead information into a fixed-size cache, and re-insert it into a newly openned struct file if that seems to be appropriate (same file, same offset).

This seems to be a reasonable solution for read-ahead (as long as the cache is big enough) but doesn't allow for any other state the a filesystem might store in the struct file.

It would seem to be a good idea to allow the NFS server to cache struct files rather than just read-ahead information.

Doing this would still not be a perfect solution as multiple applications on one client that access the one file could not be differentiated. However it should be better.

The main problem with caching struct files is the absense of CLOSE. Holding some read-ahead state in a cache does not affect the file or old it open. However caching a struct file will hold the file open and so it will be not be deleted on the last unlink. This is a real problem.

In order to be able to cache struct files we would need to know when the last handle other than this struct file on the inode was released (i.e. the file has no more links and no more opens) and this should trigger closing the struct file.

It is probably sufficient to just know when any unlink on the dentry happens. Closing the struct file on any unlink (or if nlink == 0 and we have finished an IO) is close enough to give reasonable performance.

This could almost be achieved with some sort of dnotify magic. However that has to be applied to the directory, and we don't know which directory is the parent if we have a DISCONNECTED dentry.

Possibly we could set a "SOFTOPEN" flag on the dentry, and whenever such a dentry is unlinked, a special NFSD call-back is called. That call-back would close any struct file that was open on a file with zero links.

However this approach feels quite hackish.

It is just possible that we could use dnotify to find out when a file is unlinked. We would need to define a new DN_UNLINKFILE and allow it to be set on files (fcntl_dirnotify currently requires a directory). Then in vfs_unlink we could notify the file as well as the directory.

Making sure the SIGIO got the the right place would be a bit fiddley. As nfsd threads can spawn and die, we would need to have one distinguished thread that never died (or was the last to die and closed all files on the way out). We would then need to make sure that it became the owned of the dnotify requests.


Home
Contact
Up



[æ]