[RFC 18/32] mars: add new module xio_sio
Signed-off-by: Thomas Schoebel-Theuer--- drivers/staging/mars/xio_bricks/xio_sio.c | 578 ++ include/linux/xio/xio_sio.h | 68 2 files changed, 646 insertions(+) create mode 100644 drivers/staging/mars/xio_bricks/xio_sio.c create mode 100644 include/linux/xio/xio_sio.h diff --git a/drivers/staging/mars/xio_bricks/xio_sio.c b/drivers/staging/mars/xio_bricks/xio_sio.c new file mode 100644 index ..c910cbda2ae5 --- /dev/null +++ b/drivers/staging/mars/xio_bricks/xio_sio.c @@ -0,0 +1,578 @@ +/* + * MARS Long Distance Replication Software + * + * Copyright (C) 2010-2014 Thomas Schoebel-Theuer + * Copyright (C) 2011-2014 1&1 Internet AG + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/ own type definitions ***/ + +#include + +/* own brick * input * output operations */ + +static int sio_io_get(struct sio_output *output, struct aio_object *aio) +{ + struct file *file; + + if (unlikely(!output->brick->power.on_led)) + return -EBADFD; + + if (aio->obj_initialized) { + obj_get(aio); + return aio->io_len; + } + + file = output->mf->mf_filp; + if (file) { + loff_t total_size = i_size_read(file->f_mapping->host); + + aio->io_total_size = total_size; + /* Only check reads. +* Writes behind EOF are always allowed (sparse files) +*/ + if (!aio->io_may_write) { + loff_t len = total_size - aio->io_pos; + + if (unlikely(len <= 0)) { + /* Special case: allow reads starting _exactly_ at EOF when a timeout is specified. +*/ + if (len < 0 || aio->io_timeout <= 0) { + XIO_DBG("ENODATA %lld\n", len); + return -ENODATA; + } + } + /* Shorten below EOF, but allow special case */ + if (aio->io_len > len && len > 0) + aio->io_len = len; + } + } + + /* Buffered IO. +*/ + if (!aio->io_data) { + struct sio_aio_aspect *aio_a = sio_aio_get_aspect(output->brick, aio); + + if (unlikely(!aio_a)) + return -EILSEQ; + if (unlikely(aio->io_len <= 0)) { + XIO_ERR("bad io_len = %d\n", aio->io_len); + return -ENOMEM; + } + aio->io_data = brick_block_alloc(aio->io_pos, (aio_a->alloc_len = aio->io_len)); + aio_a->do_dealloc = true; + /* atomic_inc(>total_alloc_count); */ + /* atomic_inc(>alloc_count); */ + } + + obj_get_first(aio); + return aio->io_len; +} + +static void sio_io_put(struct sio_output *output, struct aio_object *aio) +{ + struct file *file; + struct sio_aio_aspect *aio_a; + + if (!obj_put(aio)) + goto out_return; + file = output->mf->mf_filp; + aio->io_total_size = i_size_read(file->f_mapping->host); + + aio_a = sio_aio_get_aspect(output->brick, aio); + if (aio_a && aio_a->do_dealloc) { + brick_block_free(aio->io_data, aio_a->alloc_len); + /* atomic_dec(>alloc_count); */ + } + + obj_free(aio); +out_return:; +} + +static +int write_aops(struct sio_output *output, struct aio_object *aio) +{ + struct file *file = output->mf->mf_filp; + loff_t pos = aio->io_pos; + void *data = aio->io_data; + int len = aio->io_len; + int ret = 0; + + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(get_ds()); + ret = vfs_write(file, data, len, ); + set_fs(oldfs); + return ret; +} + +static +int read_aops(struct sio_output *output, struct aio_object *aio) +{ + loff_t pos = aio->io_pos; + int len = aio->io_len; + int ret; + + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(get_ds()); + ret = vfs_read(output->mf->mf_filp, aio->io_data, len, ); + set_fs(oldfs); + +
[RFC 18/32] mars: add new module xio_sio
Signed-off-by: Thomas Schoebel-Theuer --- drivers/staging/mars/xio_bricks/xio_sio.c | 578 ++ include/linux/xio/xio_sio.h | 68 2 files changed, 646 insertions(+) create mode 100644 drivers/staging/mars/xio_bricks/xio_sio.c create mode 100644 include/linux/xio/xio_sio.h diff --git a/drivers/staging/mars/xio_bricks/xio_sio.c b/drivers/staging/mars/xio_bricks/xio_sio.c new file mode 100644 index ..c910cbda2ae5 --- /dev/null +++ b/drivers/staging/mars/xio_bricks/xio_sio.c @@ -0,0 +1,578 @@ +/* + * MARS Long Distance Replication Software + * + * Copyright (C) 2010-2014 Thomas Schoebel-Theuer + * Copyright (C) 2011-2014 1&1 Internet AG + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/ own type definitions ***/ + +#include + +/* own brick * input * output operations */ + +static int sio_io_get(struct sio_output *output, struct aio_object *aio) +{ + struct file *file; + + if (unlikely(!output->brick->power.on_led)) + return -EBADFD; + + if (aio->obj_initialized) { + obj_get(aio); + return aio->io_len; + } + + file = output->mf->mf_filp; + if (file) { + loff_t total_size = i_size_read(file->f_mapping->host); + + aio->io_total_size = total_size; + /* Only check reads. +* Writes behind EOF are always allowed (sparse files) +*/ + if (!aio->io_may_write) { + loff_t len = total_size - aio->io_pos; + + if (unlikely(len <= 0)) { + /* Special case: allow reads starting _exactly_ at EOF when a timeout is specified. +*/ + if (len < 0 || aio->io_timeout <= 0) { + XIO_DBG("ENODATA %lld\n", len); + return -ENODATA; + } + } + /* Shorten below EOF, but allow special case */ + if (aio->io_len > len && len > 0) + aio->io_len = len; + } + } + + /* Buffered IO. +*/ + if (!aio->io_data) { + struct sio_aio_aspect *aio_a = sio_aio_get_aspect(output->brick, aio); + + if (unlikely(!aio_a)) + return -EILSEQ; + if (unlikely(aio->io_len <= 0)) { + XIO_ERR("bad io_len = %d\n", aio->io_len); + return -ENOMEM; + } + aio->io_data = brick_block_alloc(aio->io_pos, (aio_a->alloc_len = aio->io_len)); + aio_a->do_dealloc = true; + /* atomic_inc(>total_alloc_count); */ + /* atomic_inc(>alloc_count); */ + } + + obj_get_first(aio); + return aio->io_len; +} + +static void sio_io_put(struct sio_output *output, struct aio_object *aio) +{ + struct file *file; + struct sio_aio_aspect *aio_a; + + if (!obj_put(aio)) + goto out_return; + file = output->mf->mf_filp; + aio->io_total_size = i_size_read(file->f_mapping->host); + + aio_a = sio_aio_get_aspect(output->brick, aio); + if (aio_a && aio_a->do_dealloc) { + brick_block_free(aio->io_data, aio_a->alloc_len); + /* atomic_dec(>alloc_count); */ + } + + obj_free(aio); +out_return:; +} + +static +int write_aops(struct sio_output *output, struct aio_object *aio) +{ + struct file *file = output->mf->mf_filp; + loff_t pos = aio->io_pos; + void *data = aio->io_data; + int len = aio->io_len; + int ret = 0; + + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(get_ds()); + ret = vfs_write(file, data, len, ); + set_fs(oldfs); + return ret; +} + +static +int read_aops(struct sio_output *output, struct aio_object *aio) +{ + loff_t pos = aio->io_pos; + int len = aio->io_len; + int ret; + + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(get_ds()); + ret = vfs_read(output->mf->mf_filp, aio->io_data, len, ); + set_fs(oldfs); + + if (unlikely(ret <