Using the helper functions

The default functions make use of helper functions—these functions can't be placed directly into the connect or I/O jump tables, but they do perform the bulk of the work.

Here's the source for the two functions iofunc_chmod_default() and iofunc_stat_default():

int
iofunc_chmod_default (resmgr_context_t *ctp, io_chmod_t *msg,
                      iofunc_ocb_t *ocb)
{
    return (iofunc_chmod (ctp, msg, ocb, ocb -> attr));
}

int iofunc_stat_default( resmgr_context_t *ctp, io_stat_t *msg,
                         iofunc_ocb_t *ocb)
{
    int             status;

    /*  Update stale time fields (ctime, mtime, atime) this OCB.
    */
    (void)iofunc_time_update(ocb->attr);

    if ((status = iofunc_stat(ctp, ocb->attr, &msg->o)) != EOK)
        return(status);
    return _RESMGR_PTR(ctp, &msg->o, sizeof msg->o);
}

Notice how the iofunc_chmod() handler performs all the work for the iofunc_chmod_default() default handler. This is typical for the simple functions.

The more interesting case is the iofunc_stat_default() default handler, which calls two helper routines. First it calls iofunc_time_update() to ensure that all of the time fields (atime, ctime and mtime) are up to date. Then it calls iofunc_stat(), which builds the reply. Finally, the default function builds a pointer in the ctp structure and returns -1, to indicate to the resource manager library that it should return one part from the ctp->iov structure to the client.

The most complicated handling is done by the iofunc_open_default() handler:

int
iofunc_open_default (resmgr_context_t *ctp, io_open_t *msg,
                     iofunc_attr_t *attr, void *extra)
{
    int     status;

    iofunc_attr_lock (attr);

    if ((status = iofunc_open (ctp, msg, attr, 0, 0)) != EOK) {
        iofunc_attr_unlock (attr);
        return (status);
    }

    if ((status = iofunc_ocb_attach (ctp, msg, 0, attr, 0)) 
        != EOK) {
        iofunc_attr_unlock (attr);
        return (status);
    }

    iofunc_attr_unlock (attr);
    return (EOK);
}

This handler calls four helper functions:

  1. It calls iofunc_attr_lock() to lock the attribute structure so that it has exclusive access to it (it's going to be updating things like the counters, so we need to make sure no one else is doing that at the same time).
  2. It then calls the helper function iofunc_open(), which does the actual verification of the permissions.
  3. Next it calls iofunc_ocb_attach() to bind an OCB to this request, so that it will get automatically passed to all of the I/O functions later.
  4. Finally, it calls iofunc_attr_unlock() to release the lock on the attribute structure.