1/* 2 * Copyright (c) 2014, University of Washington. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdlib.h> 11#include <stdio.h> 12#include <assert.h> 13#include <unistd.h> 14#include <errno.h> 15#include <sys/types.h> 16#include <sys/stat.h> 17#include <fcntl.h> 18#include <aio.h> 19#include <string.h> 20#include <errors/errno.h> 21#include <storage/vsic.h> 22#include <storage/vsa.h> 23 24#define MAX_CBS 10 25 26struct file_vsic { 27 struct aiocb cb[MAX_CBS]; 28 const struct aiocb *cb_list[MAX_CBS]; 29}; 30 31static struct aiocb *get_aiocb(struct file_vsic *vsic) 32{ 33 for(int i = 0; i < MAX_CBS; i++) { 34 if(vsic->cb_list[i] == NULL) { 35 vsic->cb_list[i] = &vsic->cb[i]; 36 return &vsic->cb[i]; 37 } 38 } 39 40 return NULL; 41} 42 43static errval_t vsic_write(struct storage_vsic *vsic, struct storage_vsa *vsa, 44 off_t offset, size_t size, void *buffer) 45{ 46 assert(vsic != NULL); 47 assert(vsa != NULL); 48 assert(buffer != NULL); 49 struct file_vsic *mydata = vsic->data; 50 struct aiocb *cb = get_aiocb(mydata); 51 assert(cb != NULL); 52 53 cb->aio_fildes = vsa->fd; 54 cb->aio_offset = offset; 55 cb->aio_buf = buffer; 56 cb->aio_nbytes = size; 57 58 int r = aio_write(cb); 59 assert(r == 0); 60 61 return SYS_ERR_OK; 62} 63 64static errval_t vsic_read(struct storage_vsic *vsic, struct storage_vsa *vsa, 65 off_t offset, size_t size, void *buffer) 66{ 67 assert(vsic != NULL); 68 assert(vsa != NULL); 69 assert(buffer != NULL); 70 struct file_vsic *mydata = vsic->data; 71 struct aiocb *cb = get_aiocb(mydata); 72 assert(cb != NULL); 73 74 cb->aio_fildes = vsa->fd; 75 cb->aio_offset = offset; 76 cb->aio_buf = buffer; 77 cb->aio_nbytes = size; 78 79 int r = aio_read(cb); 80 assert(r == 0); 81 82 return SYS_ERR_OK; 83} 84 85static errval_t vsic_flush(struct storage_vsic *vsic, struct storage_vsa *vsa) 86{ 87 assert(vsic != NULL); 88 assert(vsa != NULL); 89 struct file_vsic *mydata = vsic->data; 90 struct aiocb *cb = get_aiocb(mydata); 91 assert(cb != NULL); 92 93 cb->aio_fildes = vsa->fd; 94 int r = aio_fsync(O_SYNC, cb); 95 assert(r == 0); 96 97 return SYS_ERR_OK; 98} 99 100static errval_t vsic_wait(struct storage_vsic *vsic) 101{ 102 assert(vsic != NULL); 103 struct file_vsic *mydata = vsic->data; 104 105 for(;;) { 106 int entries = 0; 107 108 for(int i = 0; i < MAX_CBS; i++) { 109 if(mydata->cb_list[i] != NULL) { 110 int err = aio_error(mydata->cb_list[i]); 111 112 if(err == 0) { 113 int status = aio_return((struct aiocb *)mydata->cb_list[i]); 114 /* printf("Status: %zd\n", status); */ 115 116 // Completed successfully 117 mydata->cb_list[i] = NULL; 118 119 if(status == 0) { 120 return VFS_ERR_EOF; 121 } 122 } else if(err == EINPROGRESS) { 123 entries++; 124 } else { 125 // Error! Report it. 126 printf("Error: %s\n", strerror(err)); 127 return VFS_ERR_IN_READ; 128 } 129 } 130 } 131 132 if(entries == 0) { 133 break; 134 } 135 136 int r = aio_suspend(mydata->cb_list, MAX_CBS, NULL); 137 assert(r == 0); 138 } 139 140 return SYS_ERR_OK; 141} 142 143static struct storage_vsic_ops file_ops = { 144 .write = vsic_write, 145 .read = vsic_read, 146 .flush = vsic_flush, 147 .wait = vsic_wait, 148}; 149 150static errval_t file_vsic_alloc(struct storage_vsic *vsic) 151{ 152 assert(vsic != NULL); 153 struct file_vsic *mydata = malloc(sizeof(struct file_vsic)); 154 assert(mydata != NULL); 155 memset(mydata, 0, sizeof(struct file_vsic)); 156 157 // Init VSIC data structures 158 vsic->ops = file_ops; 159 vsic->data = mydata; 160 vsic->blocksize = 512; // XXX: Determine from drive? 161 162 return SYS_ERR_OK; 163} 164 165errval_t storage_vsic_driver_init(int argc, const char **argv, 166 struct storage_vsic *vsic) 167{ 168 return file_vsic_alloc(vsic); 169} 170 171/* errval_t storage_vsa_alloc(struct storage_vsa *vsa, size_t size) */ 172/* { */ 173/* static int vsa_num = 0; */ 174/* char filename[32]; */ 175 176/* snprintf(filename, 32, "%u.vsa", vsa_num++); */ 177/* vsa->fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); */ 178/* assert(vsa->fd != -1); */ 179 180/* return SYS_ERR_OK; */ 181/* } */ 182 183errval_t storage_vsa_acquire(struct storage_vsa *vsa, const char *name, 184 size_t size) 185{ 186 char filename[32]; 187 188 snprintf(filename, 32, "%s.vsa", name); 189 vsa->fd = open(filename, O_RDWR | O_CREAT, 0644); 190 assert(vsa->fd != -1); 191 192 return SYS_ERR_OK; 193} 194 195errval_t storage_vsa_resize(struct storage_vsa *vsa, size_t size) 196{ 197 // No-op 198 return SYS_ERR_OK; 199} 200