An instance of the vnode operations structure (struct vnodeops, listed in Figure fig-vnodeops-h) exists for each different type of file system. For each vnode, the vnode field v_op is set to the pointer of the operations vector of the underlying file system.
4.5in
typedef struct vnodeops {
int (*vop_open)();
int (*vop_close)();
int (*vop_read)();
int (*vop_write)();
int (*vop_ioctl)();
int (*vop_setfl)();
int (*vop_getattr)();
int (*vop_setattr)();
int (*vop_access)();
int (*vop_lookup)();
int (*vop_create)();
int (*vop_remove)();
int (*vop_link)();
int (*vop_rename)();
int (*vop_mkdir)();
int (*vop_rmdir)();
int (*vop_readdir)();
int (*vop_symlink)();
int (*vop_readlink)();
int (*vop_fsync)();
void (*vop_inactive)();
int (*vop_fid)();
void (*vop_rwlock)();
void (*vop_rwunlock)();
int (*vop_seek)();
int (*vop_cmp)();
int (*vop_frlock)();
int (*vop_space)();
int (*vop_realvp)();
int (*vop_getpage)();
int (*vop_putpage)();
int (*vop_map)();
int (*vop_addmap)();
int (*vop_delmap)();
int (*vop_poll)();
int (*vop_dump)();
int (*vop_pathconf)();
int (*vop_pageio)();
int (*vop_dumpctl)();
void (*vop_dispose)();
int (*vop_setsecattr)();
int (*vop_getsecattr)();
} vnodeops_t;
|
Each field of the structure is assigned a pointer to a function that implements a particular operation on the file system in question:
Vnode operations get invoked transparently via macros that dereference the operations vector's field for that operation, and pass along the vnode and the arguments it needs. Each vnode operation has a macro associated with it, located in <sys/vnode.h>. Figure fig-vnode-mac shows as an example, the definitions for some of these calls.
6.3in
#define VOP_OPEN(vpp, mode, cr) (*(*(vpp))->v_op->vop_open)(vpp, mode, cr)
#define VOP_CLOSE(vp, f, c, o, cr) (*(vp)->v_op->vop_close)(vp, f, c, o, cr)
#define VOP_READ(vp, uiop, iof, cr) (*(vp)->v_op->vop_read)(vp, uiop, iof, cr)
#define VOP_MKDIR(dp, p, vap, vpp, cr) (*(dp)->v_op->vop_mkdir)(dp, p, vap, vpp, cr)
#define VOP_GETATTR(vp, vap, f, cr) (*(vp)->v_op->vop_getattr)(vp, vap, f, cr)
#define VOP_LOOKUP(vp, cp, vpp, pnp, f, rdir, cr) \
(*(vp)->v_op->vop_lookup)(vp, cp, vpp, pnp, f, rdir, cr)
#define VOP_CREATE(dvp, p, vap, ex, mode, vpp, cr) \
(*(dvp)->v_op->vop_create)(dvp, p, vap, ex, mode, vpp, cr)
|
When any piece of file system code, that has a handle on a vnode, wants to call a vnode operation on it, it simply dereferences the macro, as depicted in Figure fig-vnode-mac-ex.
3.5in
int foo(vnode_t *dp, char *name,
vattr_t *vap, vnode_t **vpp, cred_t *cr)
{
int error;
error = VOP_MKDIR(dp, name, vap, vpp, cr);
if (error)
return (error);
}
|