/*---------------------------------------------------------------------------*/ char *pack_iocb(struct raio_iocb *iocb, char *buffer) { pack_u64((uint64_t *)&iocb->u.c.offset, pack_u64((uint64_t *)&iocb->u.c.nbytes, pack_u32((uint32_t *)&iocb->raio_lio_opcode, pack_u32((uint32_t *)&iocb->raio_fildes, buffer)))); return buffer + SUBMIT_BLOCK_SIZE; }
/*---------------------------------------------------------------------------*/ void pack_destroy_command(void *buf, size_t *len) { char *buffer = buf; unsigned int overall_size = 0; struct raio_command cmd = { RAIO_CMD_IO_DESTROY, overall_size }; pack_u32(&cmd.data_len, pack_u32(&cmd.command, buffer)); *len = sizeof(cmd) + overall_size; }
/*---------------------------------------------------------------------------*/ void pack_fstat_command(int fd, void *buf, size_t *len) { char *buffer = buf; unsigned int overall_size = sizeof(fd); struct raio_command cmd = { RAIO_CMD_FSTAT, overall_size }; pack_u32((uint32_t *)&fd, pack_u32(&cmd.data_len, pack_u32(&cmd.command, buffer))); *len = sizeof(cmd) + overall_size; }
/*---------------------------------------------------------------------------*/ void pack_setup_command(int maxevents, void *buf, size_t *len) { char *buffer = buf; unsigned int overall_size = sizeof(maxevents); struct raio_command cmd = { RAIO_CMD_IO_SETUP, overall_size }; pack_u32((uint32_t *)&maxevents, pack_u32(&cmd.data_len, pack_u32(&cmd.command, buffer))); *len = sizeof(cmd) + overall_size; }
/*---------------------------------------------------------------------------*/ void pack_setup_command(int queues, int qdepth, void *buf, size_t *len) { char *buffer = buf; unsigned int overall_size = sizeof(queues) + sizeof(qdepth); struct raio_command cmd = { RAIO_CMD_IO_SETUP, overall_size }; pack_u32((uint32_t *)&queues, pack_u32((uint32_t *)&qdepth, pack_u32(&cmd.data_len, pack_u32(&cmd.command, buffer)))); *len = sizeof(cmd) + overall_size; }
/*---------------------------------------------------------------------------*/ void pack_open_command(const char *pathname, int flags, void *buf, size_t *len) { unsigned int path_len = strlen(pathname) + 1; char *buffer = buf; unsigned int overall_size = sizeof(flags) + path_len; struct raio_command cmd = { RAIO_CMD_OPEN, overall_size }; pack_mem(pathname, path_len, pack_u32((uint32_t *)&flags, pack_u32(&cmd.data_len, pack_u32(&cmd.command, buffer)))); *len = sizeof(cmd) + overall_size; }
void pack_submit_command(struct raio_iocb *iocb, int is_last_in_batch, void *buf, size_t *len) { char *buffer = buf; unsigned overall_size = SUBMIT_BLOCK_SIZE + sizeof(uint32_t); struct raio_command cmd = { RAIO_CMD_IO_SUBMIT, overall_size }; pack_iocb(iocb, pack_u32((uint32_t *)&is_last_in_batch, pack_u32(&cmd.data_len, pack_u32(&cmd.command, buffer)))); *len = sizeof(cmd) + overall_size; }
/*---------------------------------------------------------------------------*/ static int raio_handle_close(void *prv_session_data, void *prv_portal_data, struct raio_command *cmd, char *cmd_data, struct xio_msg *req) { struct raio_io_session_data *sd = prv_session_data; struct raio_io_portal_data *pd = prv_portal_data; int fd; int retval = 0; unpack_u32((uint32_t *)&fd, cmd_data); if (sizeof(fd) != cmd->data_len) { retval = -1; errno = EINVAL; printf("open request rejected\n"); goto reject; } if (!sd->is_null) retval = close(fd); reject: if (retval != 0) { struct raio_answer ans = { RAIO_CMD_CLOSE, 0, -1, errno }; pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr)))); } else { struct raio_answer ans = { RAIO_CMD_CLOSE, 0, 0, 0 }; pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr)))); } pd->close_rsp.out.header.iov_len = sizeof(struct raio_answer); pd->close_rsp.out.header.iov_base = pd->rsp_hdr; pd->close_rsp.out.data_iovlen = 0; pd->close_rsp.request = req; xio_send_response(&pd->close_rsp); return 0; }
/*---------------------------------------------------------------------------*/ static int on_cmd_submit_comp(struct raio_io_cmd *iocmd) { struct raio_io_u *io_u = iocmd->user_context; struct raio_answer ans = { RAIO_CMD_IO_SUBMIT, 0, 0, 0 }; pack_u32((uint32_t *)&iocmd->res2, pack_u32((uint32_t *)&iocmd->res, pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, io_u->rsp->out.header.iov_base)))))); io_u->rsp->out.header.iov_len = sizeof(struct raio_answer) + 2*sizeof(uint32_t); if (iocmd->res != iocmd->bcount) { if (iocmd->res < iocmd->bcount) { io_u->rsp->out.data_iov[0].iov_len = iocmd->res; } else { io_u->rsp->out.data_iovlen = 0; io_u->rsp->out.data_iov[0].iov_len = iocmd->res; } } else { io_u->rsp->out.data_iov[0].iov_len = iocmd->bcount; } xio_send_response(io_u->rsp); return 0; }
/*---------------------------------------------------------------------------*/ int raio_reject_request(void *prv_session_data, void *prv_portal_data, struct raio_command *cmd, char *cmd_data, struct xio_msg *req) { struct raio_io_portal_data *pd = prv_portal_data; struct raio_answer ans = { RAIO_CMD_UNKNOWN, 0, -1, errno }; pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr)))); pd->rsp.out.header.iov_len = sizeof(struct raio_answer); pd->rsp.out.data_iovlen = 0; pd->rsp.request = req; xio_send_response(&pd->rsp); return 0; }
/*---------------------------------------------------------------------------*/ static int raio_handle_submit(void *prv_session_data, void *prv_portal_data, struct raio_command *cmd, char *cmd_data, struct xio_msg *req) { struct raio_io_portal_data *pd = prv_portal_data; struct raio_io_session_data *sd = prv_session_data; struct raio_io_u *io_u; struct raio_iocb iocb; struct raio_answer ans; int retval; uint32_t is_last_in_batch; uint32_t msg_sz = SUBMIT_BLOCK_SIZE + sizeof(uint32_t); io_u = TAILQ_FIRST(&pd->io_u_free_list); if (!io_u) { printf("io_u_free_list empty\n"); errno = ENOSR; return -1; } TAILQ_REMOVE(&pd->io_u_free_list, io_u, io_u_list); msg_reset(io_u->rsp); pd->io_u_free_nr--; if (msg_sz != cmd->data_len) { retval = EINVAL; printf("io submit request rejected\n"); goto reject; } unpack_iocb(&iocb, unpack_u32(&is_last_in_batch, cmd_data)); io_u->iocmd.fd = iocb.raio_fildes; io_u->iocmd.op = iocb.raio_lio_opcode; io_u->iocmd.bcount = iocb.u.c.nbytes; io_u->iocmd.buf = io_u->rsp->out.data_iov[0].iov_base; io_u->iocmd.mr = io_u->rsp->out.data_iov[0].mr; io_u->iocmd.fsize = sd->fsize; io_u->iocmd.offset = iocb.u.c.offset; io_u->iocmd.is_last_in_batch = is_last_in_batch; io_u->iocmd.res = 0; io_u->iocmd.res2 = 0; io_u->iocmd.user_context = io_u; io_u->iocmd.comp_cb = on_cmd_submit_comp; io_u->rsp->request = req; io_u->rsp->user_context = io_u; io_u->rsp->out.data_iovlen = 1; /* issues request to bs */ retval = -raio_bs_cmd_submit(pd->bs_dev, &io_u->iocmd); if (retval) goto reject; return 0; reject: TAILQ_INSERT_TAIL(&pd->io_u_free_list, io_u, io_u_list); pd->io_u_free_nr++; msg_reset(&pd->rsp); ans.command = RAIO_CMD_IO_SUBMIT; ans.data_len = 0; ans.ret = -1; ans.ret_errno = retval; pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr)))); pd->rsp.out.header.iov_len = sizeof(struct raio_answer); pd->rsp.request = req; xio_send_response(&pd->rsp); return 0; }
/*---------------------------------------------------------------------------*/ static int raio_handle_setup(void *prv_session_data, void *prv_portal_data, struct raio_command *cmd, char *cmd_data, struct xio_msg *req) { int fd, j; struct raio_io_session_data *sd = prv_session_data; struct raio_io_portal_data *pd = prv_portal_data; if (3*sizeof(int) != cmd->data_len) { errno = EINVAL; printf("io setup request rejected\n"); goto reject; } unpack_u32((uint32_t *)&pd->iodepth, unpack_u32((uint32_t *)&fd, cmd_data)); pd->io_u_free_nr = pd->iodepth + EXTRA_MSGS; pd->io_us_free = calloc(pd->io_u_free_nr, sizeof(struct raio_io_u)); pd->rsp_pool = msg_pool_create(512, MAXBLOCKSIZE, pd->io_u_free_nr); TAILQ_INIT(&pd->io_u_free_list); /* register each io_u in the free list */ for (j = 0; j < pd->io_u_free_nr; j++) { pd->io_us_free[j].rsp = msg_pool_get(pd->rsp_pool); TAILQ_INSERT_TAIL(&pd->io_u_free_list, &pd->io_us_free[j], io_u_list); } if (sd->is_null) pd->bs_dev = raio_bs_init(pd->ctx, "null"); else pd->bs_dev = raio_bs_init(pd->ctx, "aio"); errno = -raio_bs_open(pd->bs_dev, fd); reject: if (errno) { struct raio_answer ans = { RAIO_CMD_IO_SETUP, 0, -1, errno }; pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr)))); } else { struct raio_answer ans = { RAIO_CMD_IO_SETUP, 0, 0, 0 }; pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr)))); } pd->rsp.out.header.iov_len = sizeof(struct raio_answer); pd->rsp.request = req; xio_send_response(&pd->rsp); return 0; }
/*---------------------------------------------------------------------------*/ static int raio_handle_fstat(void *prv_session_data, void *prv_portal_data, struct raio_command *cmd, char *cmd_data, struct xio_msg *req) { struct raio_io_session_data *sd = prv_session_data; struct raio_io_portal_data *pd = prv_portal_data; int fd; int retval = 0; struct stat64 stbuf; unpack_u32((uint32_t *)&fd, cmd_data); if (sizeof(fd) != cmd->data_len) { retval = -1; errno = EINVAL; printf("open request rejected\n"); goto reject; } if (sd->is_null) { stbuf.st_size = NULL_BS_DEV_SIZE; sd->fsize = stbuf.st_size; } else { retval = fstat64(fd, &stbuf); if (retval == 0) { if (S_ISBLK(stbuf.st_mode)) { retval = ioctl(fd, BLKGETSIZE64, &stbuf.st_size); if (retval < 0) fprintf(stderr, "Cannot get size %m\n"); } sd->fsize = stbuf.st_size; } } reject: if (retval != 0) { struct raio_answer ans = { RAIO_CMD_FSTAT, 0, -1, errno }; pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr)))); } else { struct raio_answer ans = {RAIO_CMD_FSTAT, STAT_BLOCK_SIZE, 0, 0}; pack_stat64(&stbuf, pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr))))); } pd->rsp.out.header.iov_len = sizeof(struct raio_answer) + STAT_BLOCK_SIZE; pd->rsp.request = req; xio_send_response(&pd->rsp); return 0; }
/*---------------------------------------------------------------------------*/ static int raio_handle_open(void *prv_session_data, void *prv_portal_data, struct raio_command *cmd, char *cmd_data, struct xio_msg *req) { struct raio_io_session_data *sd = prv_session_data; struct raio_io_portal_data *pd = prv_portal_data; const char *pathname; uint32_t flags = 0; unsigned overall_size; int fd; int retval; struct stat64 stbuf; overall_size = sizeof(fd); pathname = unpack_u32(&flags, cmd_data); if (sizeof(flags) + strlen(pathname) + 1 != cmd->data_len) { fd = -1; errno = EINVAL; printf("open request rejected\n"); goto reject; } if (strcmp(pathname, "/dev/null")) { fd = open(pathname, flags); if (fd == -1) goto reject; } else { sd->is_null = 1; fd = 0; } /* get file size */ if (sd->is_null) { sd->fsize = NULL_BS_DEV_SIZE; } else { retval = fstat64(fd, &stbuf); if (retval == 0) { if (S_ISBLK(stbuf.st_mode)) { retval = ioctl(fd, BLKGETSIZE64, &stbuf.st_size); if (retval < 0) fprintf(stderr, "Cannot get size, %m\n"); } sd->fsize = stbuf.st_size; } } reject: if (fd == -1) { struct raio_answer ans = {RAIO_CMD_OPEN, 0, -1, errno}; pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr)))); fprintf(stderr, "open %s failed %m\n", pathname); } else { unsigned overall_size = sizeof(fd); struct raio_answer ans = {RAIO_CMD_OPEN, overall_size, 0, 0}; pack_u32((uint32_t *)&fd, pack_u32((uint32_t *)&ans.ret_errno, pack_u32((uint32_t *)&ans.ret, pack_u32(&ans.data_len, pack_u32(&ans.command, pd->rsp_hdr))))); } pd->rsp.out.header.iov_len = (sizeof(struct raio_answer) + overall_size); pd->rsp.request = req; xio_send_response(&pd->rsp); return 0; }
inline void packet(char* buff, size_t* buff_n, bool pack) { pack_u32(&version, buff, buff_n, pack); }
inline void packet(char* buff, size_t* buff_n, bool pack) { pack_u32(&ticks, buff, buff_n, pack); }