static void io_blk_free(ZDB_IO_BLK *blk) { const char *myname = "io_blk_free"; int ret; if ((blk->flag & BLK_F_DIRTY)) { ZDB_IO *io = blk->io; avl_remove(&io->blk_tree, blk); #ifdef PWRITE ret = PWRITE(IO_HANDLE(io), blk->dat, blk->dlen, blk->off); if (ret != (int) blk->dlen) { acl_msg_error("%s(%d): pwrite to %s error(%s)," " ret(%d) != len(%d), off: " ACL_FMT_I64D, myname, __LINE__, PATH(IO_STREAM(io)), acl_last_serror(), ret, (int) blk->dlen, blk->off); } #else if (acl_vstream_fseek(IO_STREAM(io), blk->off, SEEK_SET) < 0) { acl_msg_error("%s(%d): fseek %s error(%s), off: " ACL_FMT_I64D, myname, __LINE__, IO_PATH(io), acl_last_serror(), blk->off); } else if ((ret = acl_vstream_writen(IO_STREAM(io), blk->dat, blk->dlen)) == ACL_VSTREAM_EOF) { acl_msg_error("%s(%d): readn from %s, ret(%d) != size(%d)," " off(" ACL_FMT_I64D "), error(%s)", myname, __LINE__, IO_PATH(io), ret, (int) blk->dlen, blk->off, acl_last_serror()); } #endif } if (blk->io->dat_slice) acl_slice_free2(blk->io->dat_slice, blk->dat); else acl_myfree(blk->dat); if (blk->io->blk_slice) acl_slice_free2(blk->io->blk_slice, blk); else acl_myfree(blk); __n--; }
/* ---------------------------------- Server side IO implementation ---- */ PUBLIC void IOThread(disk_t *disk) { stream_t *stream; QoSEntry_clp qosentry = disk->qosentry; Time_T pre,post; IO_clp io; IO_Rec recs[2]; uint32_t nrecs; word_t value; uint32_t offset; Time_ns cost; uint32_t notify; USD_Extent ext; FileIO_Request copyreq; FileIO_Request *req; while (True) { TRC(printf(__FUNCTION__": about to Rendezvous...\n")); io = IOEntry$Rendezvous((IOEntry_clp)qosentry, FOREVER); /* ** Account the time we're about to spend processing this packet ** to the QosEntry: for now, we just are sych. and so can ** actually count the amount of time. XXX no overhead accounted. */ pre = NOW(); TRC(printf(__FUNCTION__": back from Rdzvs, io at %p\n", io)); /* Find out whose IO it is */ stream = (stream_t *)IO_HANDLE(io); offset = stream->usd->partition->p_offset; TRC(printf("(It's stream %d)\n",stream->sid)); /* XXX SMH: nasty hardwired request/buffer IO_Rec pair */ if (IO$GetPkt(io, 2, recs, 0, &nrecs, &value)) { FTRC("got packet.\n"); req = (FileIO_Request *)recs[0].base; copyreq = *req; IOTRC(printf("req=%p\n",req)); IOTRC(printf("%qx:(%qd,%d)\n", stream->sid, copyreq.blockno, copyreq.nblocks)); /* Translate the addresses in the request */ if(!USDCallback$Translate(stream->usd->callbacks, stream->sid, stream->cid, ©req, &ext, ¬ify)) { TRC(printf("denied %qx:(%qd,%x)\n", stream->sid, copyreq.blockno, copyreq.nblocks)); req->rc = FileIO_RC_DENIED; goto denied; } /* Actually do the transaction */ switch(copyreq.op) { case FileIO_Op_Read: FTRC("trying to read.\n"); MU_LOCK(&disk->mu); if (BlockDev$Read((BlockDev_clp)disk->device, ext.base + offset, ext.len, recs[1].base)) { req->rc = FileIO_RC_OK; FTRC("done.\n"); } else { req->rc = FileIO_RC_FAILURE; FTRC("failure trying to read.\n"); } MU_RELEASE(&disk->mu); break; case FileIO_Op_Write: FTRC("trying to write.\n"); MU_LOCK(&disk->mu); if (BlockDev$Write((BlockDev_clp)disk->device, ext.base + offset, ext.len, recs[1].base)) { req->rc = FileIO_RC_OK; FTRC("done.\n"); } else { req->rc = FileIO_RC_FAILURE; FTRC("failure trying to write.\n"); } MU_RELEASE(&disk->mu); break; case FileIO_Op_Sync: FTRC("trying to sync.\n"); printf(__FUNCTION__": FileIO_Op_Sync unimplemented.\n"); FTRC("done.\n"); break; default: printf(__FUNCTION__": bad FileIO_Op %x\n", copyreq.op); ntsc_dbgstop(); } USDCallback$Notify(stream->usd->callbacks, stream->sid, stream->cid, ©req, &ext, notify, recs[1].base); denied: post = NOW(); cost = post - pre; QoSEntry$Charge(qosentry, io, cost); /* Return the IO_Rec vector */ TRC(printf("USD$IOThread: returning IOs.\n")); IO$PutPkt(io, nrecs, &recs[0], cost, 0); } } /* while true */ printf("USD$IOThread: BAD NEWS. Exiting (?)\n"); }