]> xenbits.xensource.com Git - people/dstodden/blktap.git/commitdiff
CA-44322: Restrict I/O request merging on filesystems.
authorDaniel Stodden <daniel.stodden@citrix.com>
Thu, 30 Sep 2010 21:01:47 +0000 (14:01 -0700)
committerDaniel Stodden <daniel.stodden@citrix.com>
Thu, 30 Sep 2010 21:01:47 +0000 (14:01 -0700)
Ensure that every single iocb can be issued with only the memory
reserves held in kernel space. Main resource prone to congestion are
bio structs.

For I/O continguous in physical storage, such as bare LUN mappings, a
single bio will hold up to 256 pages. To accomodate block mappings on
file systems, we reserve a more than 1 bio, but cannot submit iocbs of
arbitrary length without risking to stall once the reserve is
exhausted.

Limits the iocb size on ext. Assumes 4k blocks for now.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
drivers/block-aio.c
drivers/block-vhd.c
drivers/block-vindex.c
drivers/io-optimize.c
drivers/tapdisk-interface.c
drivers/tapdisk-interface.h
drivers/tapdisk-queue.c
drivers/tapdisk-queue.h
include/blktap2.h

index 1dda2ed21bc3ed77e6f6162dab620ec61a224d1a..751df444e078727eeb5db9803f720d0c27b49f4b 100644 (file)
@@ -40,6 +40,7 @@
 #include "tapdisk.h"
 #include "tapdisk-driver.h"
 #include "tapdisk-interface.h"
+#include "tapdisk-storage.h"
 
 #define MAX_AIO_REQS         TAPDISK_DATA_REQUESTS
 
@@ -169,6 +170,8 @@ int tdaio_open(td_driver_t *driver, const char *name, td_flag_t flags)
                goto done;
        }
 
+       driver->storage = tapdisk_storage_type(name);
+
         prv->fd = fd;
 
 done:
@@ -202,7 +205,7 @@ void tdaio_queue_read(td_driver_t *driver, td_request_t treq)
        aio->treq  = treq;
        aio->state = prv;
 
-       td_prep_read(&aio->tiocb, prv->fd, treq.buf,
+       td_prep_read(driver, &aio->tiocb, prv->fd, treq.buf,
                     size, offset, tdaio_complete, aio);
        td_queue_tiocb(driver, &aio->tiocb);
 
@@ -230,7 +233,7 @@ void tdaio_queue_write(td_driver_t *driver, td_request_t treq)
        aio->treq  = treq;
        aio->state = prv;
 
-       td_prep_write(&aio->tiocb, prv->fd, treq.buf,
+       td_prep_write(driver, &aio->tiocb, prv->fd, treq.buf,
                      size, offset, tdaio_complete, aio);
        td_queue_tiocb(driver, &aio->tiocb);
 
index 59fa5ea8e8775daf2798a6e66e6e7afeb8b578a4..0054633d289f4b83d7d28fe9fc37989208b23478 100644 (file)
@@ -1278,7 +1278,7 @@ aio_read(struct vhd_state *s, struct vhd_request *req, uint64_t offset)
 {
        struct tiocb *tiocb = &req->tiocb;
 
-       td_prep_read(tiocb, s->vhd.fd, req->treq.buf,
+       td_prep_read(s->driver, tiocb, s->vhd.fd, req->treq.buf,
                     vhd_sectors_to_bytes(req->treq.secs),
                     offset, vhd_complete, req);
        td_queue_tiocb(s->driver, tiocb);
@@ -1294,7 +1294,7 @@ aio_write(struct vhd_state *s, struct vhd_request *req, uint64_t offset)
 {
        struct tiocb *tiocb = &req->tiocb;
 
-       td_prep_write(tiocb, s->vhd.fd, req->treq.buf,
+       td_prep_write(s->driver, tiocb, s->vhd.fd, req->treq.buf,
                      vhd_sectors_to_bytes(req->treq.secs),
                      offset, vhd_complete, req);
        td_queue_tiocb(s->driver, tiocb);
index a37b6a0ad805f025e8416d9d87344bc0089fda17..6fe798571a96a6e27fc401d1b00396990a675962 100644 (file)
@@ -627,7 +627,8 @@ vhd_index_schedule_meta_read(vhd_index_t *index, uint32_t blk)
        req->treq.sec  = blk * index->vhdi.spb;
        req->treq.secs = block->table_size >> VHD_SECTOR_SHIFT;
 
-       td_prep_read(&req->tiocb, index->vhdi.fd,
+       td_prep_read(index->driver,
+                    &req->tiocb, index->vhdi.fd,
                     (char *)block->vhdi_block.table, block->table_size,
                     offset, vhd_index_complete_meta_read, req);
        td_queue_tiocb(index->driver, &req->tiocb);
@@ -677,7 +678,8 @@ vhd_index_schedule_data_read(vhd_index_t *index, td_request_t treq)
        req->index = index;
        req->off   = offset;
 
-       td_prep_read(&req->tiocb, file->fd, treq.buf, size, offset,
+       td_prep_read(index->driver,
+                    &req->tiocb, file->fd, treq.buf, size, offset,
                     vhd_index_complete_data_read, req);
        td_queue_tiocb(index->driver, &req->tiocb);
 
index 9af8f6d1183d651a98ded5d526a98a22316a96fc..60927d4d65822c95f083360f64b59087279deef7 100644 (file)
@@ -36,6 +36,7 @@
 #include <inttypes.h>
 
 #include "io-optimize.h"
+#include "tapdisk-queue.h"
 #include "tapdisk-log.h"
 
 #if (!defined(TEST) && defined(DEBUG))
@@ -207,12 +208,18 @@ merge_tail(struct opioctx *ctx, struct iocb *head, struct iocb *io)
 static int
 merge(struct opioctx *ctx, struct iocb *head, struct iocb *io)
 {
+       struct tiocb *tiocb = head->data;
+       size_t limit = tiocb->merge_limit;
+
        if (head->aio_lio_opcode != io->aio_lio_opcode)
                return -EINVAL;
 
        if (!contiguous_iocbs(head, io))
                return -EINVAL;
 
+       if (head->u.c.nbytes + io->u.c.nbytes > limit)
+               return -EINVAL;
+
        return merge_tail(ctx, head, io);               
 }
 
index af3c3150265a86743d5b50449c2b1633c5d076c2..0503c75d9dc7e8e4176595c26f24689033826ee2 100644 (file)
@@ -235,17 +235,21 @@ td_queue_tiocb(td_driver_t *driver, struct tiocb *tiocb)
 }
 
 void
-td_prep_read(struct tiocb *tiocb, int fd, char *buf, size_t bytes,
+td_prep_read(td_driver_t *driver,
+            struct tiocb *tiocb, int fd, char *buf, size_t bytes,
             long long offset, td_queue_callback_t cb, void *arg)
 {
-       tapdisk_prep_tiocb(tiocb, fd, 0, buf, bytes, offset, cb, arg);
+       tapdisk_prep_tiocb(tiocb, fd, 0, buf, bytes, offset, driver->storage,
+                          cb, arg);
 }
 
 void
-td_prep_write(struct tiocb *tiocb, int fd, char *buf, size_t bytes,
+td_prep_write(td_driver_t *driver,
+             struct tiocb *tiocb, int fd, char *buf, size_t bytes,
              long long offset, td_queue_callback_t cb, void *arg)
 {
-       tapdisk_prep_tiocb(tiocb, fd, 1, buf, bytes, offset, cb, arg);
+       tapdisk_prep_tiocb(tiocb, fd, 1, buf, bytes, offset, driver->storage,
+                          cb, arg);
 }
 
 void
index 4ee5424d2ceb8594392bd638dba83cce45a15bfc..7ee72d817fd20bba4a0b220c414f5d61d32727d3 100644 (file)
@@ -46,9 +46,9 @@ void td_complete_request(td_request_t, int);
 void td_debug(td_image_t *);
 
 void td_queue_tiocb(td_driver_t *, struct tiocb *);
-void td_prep_read(struct tiocb *, int, char *, size_t,
+void td_prep_read(td_driver_t *, struct tiocb *, int, char *, size_t,
                  long long, td_queue_callback_t, void *);
-void td_prep_write(struct tiocb *, int, char *, size_t,
+void td_prep_write(td_driver_t *, struct tiocb *, int, char *, size_t,
                   long long, td_queue_callback_t, void *);
 void td_panic(void) __attribute__((noreturn));
 
index 9d5a2c8d16b84a0343b4ad663e84ef6ae30845cd..89874726b7d1f831ca6e12e5f7c7e709f93db45d 100644 (file)
@@ -44,6 +44,8 @@
 #include "tapdisk-utils.h"
 
 #include "libaio-compat.h"
+#include "blktap2.h"
+#include "tapdisk-storage.h"
 #include "atomicio.h"
 
 #define WARN(_f, _a...) tlog_write(TLOG_WARN, _f, ##_a)
@@ -755,7 +757,7 @@ tapdisk_debug_queue(struct tqueue *queue)
 
 void
 tapdisk_prep_tiocb(struct tiocb *tiocb, int fd, int rw, char *buf, size_t size,
-                  long long offset, td_queue_callback_t cb, void *arg)
+                  long long offset, int storage, td_queue_callback_t cb, void *arg)
 {
        struct iocb *iocb = &tiocb->iocb;
 
@@ -767,6 +769,14 @@ tapdisk_prep_tiocb(struct tiocb *tiocb, int fd, int rw, char *buf, size_t size,
        iocb->data  = tiocb;
        tiocb->cb   = cb;
        tiocb->arg  = arg;
+
+       if (storage == TAPDISK_STORAGE_TYPE_EXT) {
+               size_t block_size = 4<<10; /* should query the fs */
+               tiocb->merge_limit = BLKTAP2_BIO_POOL_SIZE * block_size;
+       } else
+               /* contiguous storage:
+                  BLKTAP2_BIO_POOL_SIZE * BIO_MAX_PAGES * PAGE_SIZE */
+               tiocb->merge_limit = SIZE_MAX;
 }
 
 void
index ef386b2f7c70ec6755ee5a9d3b2dccd1b64171fa..dfb69d1e40eeb84ef84cef67f470245d26e28694 100644 (file)
@@ -21,6 +21,8 @@ struct tiocb {
        void                 *arg;
 
        struct iocb           iocb;
+       size_t                merge_limit;
+
        struct list_head      entry;
 };
 
@@ -84,6 +86,6 @@ void tapdisk_submit_all_tiocbs(struct tqueue *);
 int tapdisk_cancel_tiocbs(struct tqueue *);
 int tapdisk_cancel_all_tiocbs(struct tqueue *);
 void tapdisk_prep_tiocb(struct tiocb *, int, int, char *, size_t,
-                       long long, td_queue_callback_t, void *);
+                       long long, int, td_queue_callback_t, void *);
 
 #endif
index 3756e44a5b2c3f6e053f5b05bb369ede2aefe1e3..4d6375d5ea8af849afa4694902bb55075698e1ba 100644 (file)
@@ -56,6 +56,8 @@
 #define BLKTAP2_IO_DEVICE              BLKTAP2_DIRECTORY"/tapdev"
 #define BLKTAP2_ENOSPC_SIGNAL_FILE     "/var/run/tapdisk-enospc"
 
+#define BLKTAP2_BIO_POOL_SIZE          12
+
 struct blktap2_handle {
        unsigned int                   ring;
        unsigned int                   device;