static int mtask_received(struct mgmt_task *mtask, int fd) { tgtadm_err adm_err; int err; adm_err = mtask_execute(mtask); set_mtask_result(mtask, adm_err); /* whatever the result of mtask execution, a response is sent */ mtask->mtask_state = MTASK_STATE_HDR_SEND; mtask->done = 0; err = tgt_event_modify(fd, EPOLLOUT); if (err) eprintf("failed to modify mgmt task event out\n"); return err; }
static void mtask_handler(int fd, int events, void *data) { int err, len; char *p; struct mgmt_task *mtask = data; struct tgtadm_req *req = &mtask->req; struct tgtadm_rsp *rsp = &mtask->rsp; switch (mtask->mtask_state) { case MTASK_STATE_HDR_RECV: len = sizeof(*req) - mtask->done; err = read(fd, (char *)req + mtask->done, len); if (err > 0) { mtask->done += err; if (mtask->done == sizeof(*req)) { if (req->len == sizeof(*req)) { tgt_mgmt(mtask); mtask->mtask_state = MTASK_STATE_RSP_SEND; if (tgt_event_modify(fd, EPOLLOUT)) eprintf("failed to modify\n"); mtask->done = 0; } else { /* the pdu exists */ mtask->done = 0; mtask->mtask_state = MTASK_STATE_PDU_RECV; if (mtask->bsize < req->len) { eprintf("FIXME: %d\n", req->len); goto out; } } } } else if (errno != EAGAIN) goto out; break; case MTASK_STATE_PDU_RECV: len = req->len - (sizeof(*req) + mtask->done); err = read(fd, mtask->buf + mtask->done, len); if (err > 0) { mtask->done += err; if (mtask->done == req->len - (sizeof(*req))) { tgt_mgmt(mtask); mtask->mtask_state = MTASK_STATE_RSP_SEND; if (tgt_event_modify(fd, EPOLLOUT)) eprintf("failed to modify\n"); mtask->done = 0; } } else if (errno != EAGAIN) goto out; break; case MTASK_STATE_RSP_SEND: if (mtask->done < sizeof(*rsp)) { p = (char *)rsp + mtask->done; len = sizeof(*rsp) - mtask->done; } else { p = mtask->buf + (mtask->done - sizeof(*rsp)); len = rsp->len - mtask->done; } err = write(fd, p, len); if (err > 0) { mtask->done += err; if (mtask->done == rsp->len) { if (req->mode == MODE_SYSTEM && req->op == OP_DELETE && !rsp->err) system_active = 0; goto out; } } else if (errno != EAGAIN) goto out; break; default: eprintf("unknown state %d\n", mtask->mtask_state); } return; out: tgt_event_del(fd); free(mtask->buf); free(mtask); close(fd); }