There are three aspects of the I/O daemons operations: general I/O, error handling, and log handling. These will be discussed seperately.
I/O handling is achieved by an ioctl command that doesn't return, but instead calls the vxiod routine to wait for errors or I/O requests and process them. When an error occurs, if there are no I/O daemons active, then the I/O simply turns into a failure on that plex. If a general I/O request is queued up when no daemons exist, then the I/O will hang forever until a daemon process is created. If I/O daemons are active, then the I/O is put on a work queue and the daemons get a wakeup. A daemon takes an error request and tries to read other plexes until a read succeeds or all plexes have been tried. Then, if the writeback facility is enabled, the daemon tries to write the good data to each plex that failed on the read. If the write is successful, the read error is nullified. An I/O request is handled in a similar manner.
Logging is handled in a similiar manner. An ioctl command, which does not return, is issued to create a daemon for each volume which has logging enabled. This daemon monitors two queues: one queue of I/O which was started while the log was busy (the ``log'' queue), and another queue of requests which have been logged and now need to be started (the ``ready'' queue). I/O requests are taken from the log queue when the log is no longer busy, and another log write is started. Completion of a log write results in all I/O requests which have just been logged being placed on the I/O daemon's ready queue, where they are immediately started.
One mechanism finds out how many I/O error daemons are running, and another mechanism allows a process to become an I/O daemon. Before a process becomes an I/O daemon, it should close all open files and detach from the controlling tty. An I/O or logging daemon cannot be killed except through an explicit ioctl.
#include <sys/types.h> #include <sys/vol.h> struct tag arg; int ioctl (int fd, int cmd, struct tag arg);The value of cmd is the ioctl command code, and arg is usually a pointer to a structure containing the arguments that need to be passed to the kernel.
The return value for all these ioctls is 0 if the command was successful, and -1 if it was rejected. If the return value is -1, then errno is set to indicate the cause of the error.
The following ioctl commands are supported:
long version; /* kernel version number */ long voldinfo_sz; /* size of voldinfo area */ major_t volbmajor; /* volume blk dev major number */ major_t volcmajor; /* volume char dev major number */ major_t plexmajor; /* plex device major number */ long maxvol; /* max # of volumes supported */ long maxplex; /* max # of associated plexes */ long plexnum; /* max plexes per volume */ long sdnum; /* max subdisks per plex */ long max_ioctl; /* max size of ioctl data */ long max_specio; /* max size of ioctl I/O op */ long max_io; /* max size of I/O operation */ long max_ilocksleep; /* max sleeps on ilock */ long dflt_iodelay; /* default I /O delay for utils */ long max_freebuf; /* max number of volbufs to keep */ long max_freevcb; /* max number of volcbs to keep */ long max_parallelio; /* max # voldios allowed */