Let's look at the io_write() function first, and then we'll discuss the code:
static int
io_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb)
{
int nroom;
int nbytes;
// 1) we don't do any xtypes here...
if ((msg -> i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
return (ENOSYS);
}
// standard helper function
if ((sts = iofunc_write_verify (ctp, msg, &ocb -> base, NULL)) != EOK) {
return (sts);
}
// 2) figure out how many bytes we can accept in total
nroom = sizeof (ocb -> wbuf) - 1 - ocb -> base.offset;
// 3) and how many we can accept from the client
nbytes = min (nroom, msg -> i.nbytes);
if (nbytes) {
// 4) grab the bytes from the client
memcpy (ocb -> wbuf + ocb -> base.offset, &msg -> i + 1, nbytes);
// 5) update flags and offset
ocb -> base.attr -> base.flags |=
IOFUNC_ATTR_MTIME | IOFUNC_ATTR_DIRTY_TIME;
ocb -> base.offset += nbytes;
} else {
// 6) we're full, tell them
if (!nroom) {
return (ENOSPC);
}
}
// 7) set the number of returning bytes
_IO_SET_WRITE_NBYTES (ctp, nbytes);
return (EOK);
}
The io_write() function performs the following steps:
- Just like in the io_read() handler, we fail the attempt to perform any XTYPE operations.
- We determine how much room we have available in the buffer by subtracting the current offset from its size.
- Next, we determine how many bytes we can accept from the client.
This is going to be the smaller of the two numbers representing how much
room we have, and how many bytes the client wants to transfer.
- If we are transferring any bytes from the client, we do that via memcpy().
(See note after step 7 below!)
- POSIX says that the MTIME time field must be updated if transferring
more than zero bytes, so we set the MTIME is dirty flag.
- If we can't transfer any bytes, and it's because we have no room, we give the client an error indication.
- Finally, we tell the resource manager framework that we've processed nbytes
worth of data, and that the status was EOK.
Note:
In step 4, we
assume that we have all of the data!
Remember that the resource manager framework doesn't necessarily read in all of the bytes
from the client—it reads in only as many bytes as you've specified in your
resmgr_attr.msg_max_size parameter to the
resmgr_attach()
function (and in the network case it may read in less than that).
However, we are dealing with
tiny amounts of data—ten or so bytes at
the most, so we are safe in simply
assuming that the data is present.
For details on how this is done
correctly, take a look at the
RAM-disk Filesystem
chapter.