1/* 2 Unix SMB/CIFS implementation. 3 4 POSIX NTVFS backend - Linux AIO calls 5 6 Copyright (C) Andrew Tridgell 2006 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include <tevent.h> 24#include "vfs_posix.h" 25#include "system/aio.h" 26 27struct pvfs_aio_read_state { 28 struct ntvfs_request *req; 29 union smb_read *rd; 30 struct pvfs_file *f; 31 struct tevent_aio *ae; 32}; 33 34struct pvfs_aio_write_state { 35 struct ntvfs_request *req; 36 union smb_write *wr; 37 struct pvfs_file *f; 38 struct tevent_aio *ae; 39}; 40 41/* 42 called when an aio read has finished 43*/ 44static void pvfs_aio_read_handler(struct tevent_context *ev, struct tevent_aio *ae, 45 int ret, void *private_data) 46{ 47 struct pvfs_aio_read_state *state = talloc_get_type(private_data, 48 struct pvfs_aio_read_state); 49 struct pvfs_file *f = state->f; 50 union smb_read *rd = state->rd; 51 52 if (ret < 0) { 53 /* errno is -ret on error */ 54 state->req->async_states->status = pvfs_map_errno(f->pvfs, -ret); 55 state->req->async_states->send_fn(state->req); 56 return; 57 } 58 59 f->handle->position = f->handle->seek_offset = rd->readx.in.offset + ret; 60 61 rd->readx.out.nread = ret; 62 rd->readx.out.remaining = 0xFFFF; 63 rd->readx.out.compaction_mode = 0; 64 65 talloc_steal(ev, state->ae); 66 67 state->req->async_states->status = NT_STATUS_OK; 68 state->req->async_states->send_fn(state->req); 69} 70 71 72/* 73 read from a file 74*/ 75NTSTATUS pvfs_aio_pread(struct ntvfs_request *req, union smb_read *rd, 76 struct pvfs_file *f, uint32_t maxcnt) 77{ 78 struct iocb iocb; 79 struct pvfs_aio_read_state *state; 80 81 state = talloc(req, struct pvfs_aio_read_state); 82 NT_STATUS_HAVE_NO_MEMORY(state); 83 84 io_prep_pread(&iocb, f->handle->fd, rd->readx.out.data, 85 maxcnt, rd->readx.in.offset); 86 state->ae = tevent_add_aio(req->ctx->event_ctx, req->ctx->event_ctx, &iocb, 87 pvfs_aio_read_handler, state); 88 if (state->ae == NULL) { 89 DEBUG(0,("Failed tevent_add_aio\n")); 90 talloc_free(state); 91 return NT_STATUS_NOT_IMPLEMENTED; 92 } 93 94 state->req = req; 95 state->rd = rd; 96 state->f = f; 97 98 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; 99 100 return NT_STATUS_OK; 101} 102 103 104 105 106/* 107 called when an aio write has finished 108*/ 109static void pvfs_aio_write_handler(struct tevent_context *ev, struct tevent_aio *ae, 110 int ret, void *private_data) 111{ 112 struct pvfs_aio_write_state *state = talloc_get_type(private_data, 113 struct pvfs_aio_write_state); 114 struct pvfs_file *f = state->f; 115 union smb_write *wr = state->wr; 116 117 if (ret < 0) { 118 /* errno is -ret on error */ 119 state->req->async_states->status = pvfs_map_errno(f->pvfs, -ret); 120 state->req->async_states->send_fn(state->req); 121 return; 122 } 123 124 f->handle->seek_offset = wr->writex.in.offset + ret; 125 126 wr->writex.out.nwritten = ret; 127 wr->writex.out.remaining = 0; 128 129 talloc_steal(ev, state->ae); 130 131 state->req->async_states->status = NT_STATUS_OK; 132 state->req->async_states->send_fn(state->req); 133} 134 135 136/* 137 write to a file 138*/ 139NTSTATUS pvfs_aio_pwrite(struct ntvfs_request *req, union smb_write *wr, 140 struct pvfs_file *f) 141{ 142 struct iocb iocb; 143 struct pvfs_aio_write_state *state; 144 145 state = talloc(req, struct pvfs_aio_write_state); 146 NT_STATUS_HAVE_NO_MEMORY(state); 147 148 io_prep_pwrite(&iocb, f->handle->fd, discard_const(wr->writex.in.data), 149 wr->writex.in.count, wr->writex.in.offset); 150 state->ae = tevent_add_aio(req->ctx->event_ctx, req->ctx->event_ctx, &iocb, 151 pvfs_aio_write_handler, state); 152 if (state->ae == NULL) { 153 DEBUG(0,("Failed tevent_add_aio\n")); 154 talloc_free(state); 155 return NT_STATUS_NOT_IMPLEMENTED; 156 } 157 158 state->req = req; 159 state->wr = wr; 160 state->f = f; 161 162 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; 163 164 return NT_STATUS_OK; 165} 166 167