resmgr_io_funcs_t I/O table
The I/O table is very similar in spirit to the connect functions table shown above.
typedef struct _resmgr_io_funcs {
unsigned nfuncs;
int (*read) (ctp, io_read_t *msg, ocb);
int (*write) (ctp, io_write_t *msg, ocb);
int (*close_ocb) (ctp, void *reserved, ocb);
int (*stat) (ctp, io_stat_t *msg, ocb);
int (*notify) (ctp, io_notify_t *msg, ocb);
int (*devctl) (ctp, io_devctl_t *msg, ocb);
int (*unblock) (ctp, io_pulse_t *msg, ocb);
int (*pathconf) (ctp, io_pathconf_t *msg, ocb);
int (*lseek) (ctp, io_lseek_t *msg, ocb);
int (*chmod) (ctp, io_chmod_t *msg, ocb);
int (*chown) (ctp, io_chown_t *msg, ocb);
int (*utime) (ctp, io_utime_t *msg, ocb);
int (*openfd) (ctp, io_openfd_t *msg, ocb);
int (*fdinfo) (ctp, io_fdinfo_t *msg, ocb);
int (*lock) (ctp, io_lock_t *msg, ocb);
int (*space) (ctp, io_space_t *msg, ocb);
int (*shutdown) (ctp, io_shutdown_t *msg, ocb);
int (*mmap) (ctp, io_mmap_t *msg, ocb);
int (*msg) (ctp, io_msg_t *msg, ocb);
int (*reserved) (ctp, void *msg, ocb);
int (*dup) (ctp, io_dup_t *msg, ocb);
int (*close_dup) (ctp, io_close_t *msg, ocb);
int (*lock_ocb) (ctp, void *reserved, ocb);
int (*unlock_ocb) (ctp, void *reserved, ocb);
int (*sync) (ctp, io_sync_t *msg, ocb);
int (*power) (ctp, io_power_t *msg, ocb);
int (*acl) (ctp, io_acl_t *msg, ocb);
int (*pause) (ctp, void *reserved, ocb);
int (*unpause) (ctp, io_pulse_t *msg, ocb);
int (*read64) (ctp, io_read_t *msg, ocb);
int (*write64) (ctp, io_write_t *msg, ocb);
int (*notify64) (ctp, io_notify_t *msg, ocb);
int (*utime64) (ctp, io_utime_t *msg, ocb);
} resmgr_io_funcs_t;
int (*read) (resmgr_context_t *ctp,
io_read_t *msg,
RESMGR_OCB_T *ocb);
#include
<sys/iofunc.h> before <sys/resmgr.h>.
The very first member of the structure (nfuncs) indicates how big the structure is (how many members it contains). The proper manifest constant for initialization is _RESMGR_IO_NFUNCS.
Note that the parameter list in the I/O table is also very regular. The first parameter is the ctp, and the second parameter is the msg, just as they were in the connect table handlers.
The third parameter is different, however.
It's an ocb, which stands
for Open Context Block.
It holds the context that was bound by the connect message handler (e.g.,
as a result of the client's open() call), and is available to the I/O functions.
As discussed above, when it comes
time to fill in the two tables, we recommend
that you use the
iofunc_func_init()
function to load up the
tables with the POSIX-layer default handler routines.
Then, if you need to override some of the functionality of particular
message handlers, you'd simply assign your own handler function instead
of the default routine.
We'll see this in the section
Putting in your own functions.