[RFC 18/32] mars: add new module xio_sio

2016-12-30 Thread Thomas Schoebel-Theuer
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

2016-12-30 Thread Thomas Schoebel-Theuer
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 <