Writing Filesystems - Opening/Closing files

From Genunix

Jump to: navigation, search
Image:Info.gif This article has been identified as a draft. It is currently undergoing a community review. Please add your comments to the discussion page.

Do not quote any text on this page! It is still a draft!


Unlike character/block device drivers, where the open(9e) entry point is responsible for setting up a new "connection" to the device, vnodes are already accessible at the time VOP_OPEN() is called - they have been created by VFS_VGET(), usually as a consequence of a filename lookup via VOP_LOOKUP(). See Livecycle of a vnode for details on that.

So what is the task of VOP_OPEN() then ? Well - simple: To succeed. Most filesystems will get away having just a routine like this:

/* ARGSUSED */
static int
fat_open(struct vnode **vpp, int flag, struct cred *cr)
{
	return (0);
}

Don't you believe it ? Well, if not, check zfs_open(), ufs_open(), hsfs_open(), or pcfs_open(). It's indeed somewhat surprising that the fs_subr.c "glue code" does not provide a function fs_open() which would be the default if a filesystem wouldn't register a vnode op for VOP_OPEN().

Who needs a nontrivial VOP_OPEN() ? Only implementations that need to keep more complex state for an "open file" than the framework guaranteeing existance of a vnode for it. NFS is the prime example of that in OpenSolaris, see nfs3_open() and nfs4_open(), but lofs, cachefs or autofs also do have a non-empty routine there.

Now since VOP_OPEN() is so simple, it's not surprising that VOP_CLOSE() is trivial as well:

/* ARGSUSED1 */
static int
fat_close(struct vnode *vp, int flag, int count, offset_t offset,
	struct cred *cr)
{
	/*
	 * dump locking state still associated with this process/file.
	 */
	cleanlocks(vp, ddi_get_pid(), 0);
	cleanshares(vp, ddi_get_pid());

	return (0);
}

Not completely empty but simple enough - it dumps advisory/mandatory file locks and shares (as set on the file via fcntl(2) calls of F_SETLK of F_SHARE type). Again, only filesystems like NFS need to perform more complicated cleanup here.

You can also see another characteristic difference between filesystem drivers' VOP_OPEN()/VOP_CLOSE() and character/block device drivers' open(9e) and close(9e) entry points. VOP_OPEN()/VOP_CLOSE() is strictly paired, i.e. there'll be one VOP_CLOSE() for every call to VOP_OPEN(), while for character/block drivers, close(9e) is only called on the last close of the device, after a possibly-long sequence of calls to this driver's open(9e).

Next: Writing Filesystems - Reading/Writing files
Personal tools