5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/lib/src/blockserver_io.c Wed Feb 06 17:56:51 2019 +0100
5.3 @@ -0,0 +1,241 @@
5.4 +/*
5.5 + * blockserver_io.c --- L4Re block server I/O manager.
5.6 + *
5.7 + * Copyright (C) 2019 Paul Boddie
5.8 + *
5.9 + * %Begin-Header%
5.10 + * This file may be redistributed under the terms of the GNU Library
5.11 + * General Public License, version 2.
5.12 + * %End-Header%
5.13 + */
5.14 +
5.15 +#include <stdio.h>
5.16 +#include <stdlib.h>
5.17 +
5.18 +#include <ext2fs/ext2fs.h>
5.19 +#include <fsclient/client.h>
5.20 +
5.21 +#include <l4/re/env.h>
5.22 +
5.23 +
5.24 +
5.25 +/* Specific data for interacting with block devices. */
5.26 +
5.27 +struct blockserver_private_data
5.28 +{
5.29 + int magic;
5.30 + int flags;
5.31 + file_descriptor_t *desc;
5.32 +};
5.33 +
5.34 +io_manager blockserver_io_manager; /* defined below */
5.35 +
5.36 +
5.37 +
5.38 +/* Allocate and initialise a channel for the indicated block device. */
5.39 +
5.40 +static errcode_t blockserver_open_channel(const char *name,
5.41 + file_descriptor_t *desc, int flags,
5.42 + io_channel *channel,
5.43 + io_manager io_mgr)
5.44 +{
5.45 + io_channel io = NULL;
5.46 + struct blockserver_private_data *data = NULL;
5.47 + errcode_t retval;
5.48 +
5.49 + /* Allocate memory for the channel. */
5.50 +
5.51 + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
5.52 + if (retval)
5.53 + goto free_io;
5.54 +
5.55 + /* Initialise the channel. */
5.56 +
5.57 + memset(io, 0, sizeof(struct struct_io_channel));
5.58 +
5.59 + io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
5.60 + io->manager = io_mgr;
5.61 + io->block_size = 1024;
5.62 + io->read_error = 0;
5.63 + io->write_error = 0;
5.64 + io->refcount = 1;
5.65 +
5.66 + /* Allocate memory for the name and store it. */
5.67 +
5.68 + retval = ext2fs_get_mem(strlen(name)+1, &io->name);
5.69 + if (retval)
5.70 + goto free_io;
5.71 +
5.72 + strcpy(io->name, name);
5.73 +
5.74 + /* Allocate memory for the private data. */
5.75 +
5.76 + retval = ext2fs_get_mem(sizeof(struct blockserver_private_data), &data);
5.77 + if (retval)
5.78 + goto free_data;
5.79 +
5.80 + /* Initialise the private data. */
5.81 +
5.82 + io->private_data = data;
5.83 +
5.84 + memset(data, 0, sizeof(struct blockserver_private_data));
5.85 +
5.86 + data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
5.87 + data->flags = flags;
5.88 + data->desc = desc;
5.89 +
5.90 + /* Return the allocated channel. */
5.91 +
5.92 + *channel = io;
5.93 + return 0;
5.94 +
5.95 + /* Deallocation upon failure. */
5.96 +
5.97 +free_data:
5.98 + if (data)
5.99 + ext2fs_free_mem(&data);
5.100 +
5.101 +free_io:
5.102 + if (io)
5.103 + {
5.104 + if (io->name)
5.105 + ext2fs_free_mem(&io->name);
5.106 + ext2fs_free_mem(&io);
5.107 + }
5.108 +
5.109 + return retval;
5.110 +}
5.111 +
5.112 +
5.113 +
5.114 +/* Open a block device using the named capability. */
5.115 +
5.116 +static errcode_t blockserver_open(const char *name, int flags, io_channel *channel)
5.117 +{
5.118 + file_descriptor_t *desc;
5.119 +
5.120 + /* Open a device via the named capability or via a filesystem object. */
5.121 +
5.122 + if (l4_is_invalid_cap(l4re_env_get_cap("fs")))
5.123 + desc = client_open_device(name);
5.124 + else
5.125 + desc = client_open(name, 0);
5.126 +
5.127 + /* NOTE: May want a more appropriate error code. */
5.128 +
5.129 + if (desc == NULL)
5.130 + return EXT2_ET_BAD_DEVICE_NAME;
5.131 +
5.132 + return blockserver_open_channel(name, desc, flags, channel, blockserver_io_manager);
5.133 +}
5.134 +
5.135 +
5.136 +
5.137 +/* Close the block device associated with the given channel. */
5.138 +
5.139 +static errcode_t blockserver_close(io_channel channel)
5.140 +{
5.141 + struct blockserver_private_data *data;
5.142 +
5.143 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
5.144 + data = (struct blockserver_private_data *) channel->private_data;
5.145 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
5.146 +
5.147 + client_close(data->desc);
5.148 + return 0;
5.149 +}
5.150 +
5.151 +static errcode_t blockserver_set_blksize(io_channel channel, int blksize)
5.152 +{
5.153 + struct blockserver_private_data *data;
5.154 +
5.155 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
5.156 + data = (struct blockserver_private_data *) channel->private_data;
5.157 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
5.158 +
5.159 + if (channel->block_size != blksize)
5.160 + channel->block_size = blksize;
5.161 +
5.162 + return 0;
5.163 +}
5.164 +
5.165 +static errcode_t blockserver_flush(io_channel channel)
5.166 +{
5.167 + return 0;
5.168 +}
5.169 +
5.170 +static errcode_t blockserver_write_byte(io_channel channel, unsigned long offset, int size, const void *buf)
5.171 +{
5.172 + return 0;
5.173 +}
5.174 +
5.175 +static errcode_t blockserver_set_option(io_channel channel, const char *option, const char *arg)
5.176 +{
5.177 + return 0;
5.178 +}
5.179 +
5.180 +static errcode_t blockserver_get_stats(io_channel channel, io_stats *stats)
5.181 +{
5.182 + return 0;
5.183 +}
5.184 +
5.185 +static errcode_t blockserver_read_blk64(io_channel channel, unsigned long long block, int count, void *buf)
5.186 +{
5.187 + struct blockserver_private_data *data;
5.188 + int i;
5.189 +
5.190 + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
5.191 + data = (struct blockserver_private_data *) channel->private_data;
5.192 + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
5.193 +
5.194 + /* Negative count values indicate a precise amount to read. */
5.195 +
5.196 + client_seek(data->desc, block * channel->block_size, SEEK_SET);
5.197 + client_read(data->desc, buf, count < 0 ? -count : count * channel->block_size);
5.198 +
5.199 + return 0;
5.200 +}
5.201 +
5.202 +static errcode_t blockserver_write_blk64(io_channel channel, unsigned long long block, int count, const void *buf)
5.203 +{
5.204 + return 0;
5.205 +}
5.206 +
5.207 +static errcode_t blockserver_read_blk(io_channel channel, unsigned long block, int count, void *buf)
5.208 +{
5.209 + return blockserver_read_blk64(channel, block, count, buf);
5.210 +}
5.211 +
5.212 +static errcode_t blockserver_write_blk(io_channel channel, unsigned long block, int count, const void *buf)
5.213 +{
5.214 + return blockserver_write_blk64(channel, block, count, buf);
5.215 +}
5.216 +
5.217 +static errcode_t blockserver_discard(io_channel channel, unsigned long long block, unsigned long long count)
5.218 +{
5.219 + return 0;
5.220 +}
5.221 +
5.222 +/* Unsupported operations are omitted: see io_manager.c for optional operation
5.223 + details. */
5.224 +
5.225 +static struct struct_io_manager struct_blockserver_manager = {
5.226 + .magic = EXT2_ET_MAGIC_IO_MANAGER,
5.227 + .name = "L4Re blockserver I/O Manager",
5.228 + .open = blockserver_open,
5.229 + .close = blockserver_close,
5.230 + .set_blksize = blockserver_set_blksize,
5.231 + .read_blk = blockserver_read_blk,
5.232 + .write_blk = blockserver_write_blk,
5.233 + .flush = blockserver_flush,
5.234 + .write_byte = 0,
5.235 + .set_option = blockserver_set_option,
5.236 + .get_stats = blockserver_get_stats,
5.237 + .read_blk64 = blockserver_read_blk64,
5.238 + .write_blk64 = blockserver_write_blk64,
5.239 + .discard = 0,
5.240 + .cache_readahead = 0,
5.241 + .zeroout = 0,
5.242 +};
5.243 +
5.244 +io_manager blockserver_io_manager = &struct_blockserver_manager;