# To ensure that I/O can always make progress, even when there is no # memory, we provide static buffers which are to be used when dynamic # ones can't be allocated. These are protected by a semaphore when in # use. When one is freed, the semaphore is released, and one of the # waiters gets to use it. There is an allocation failure emulation # mechanism here - setting fail_start and fail_end will cause # allocations in that range (fail_start <= allocations < fail_end) to # fail, invoking the emergency mechanism. # When this is happening, I/O requests proceed one at a time, # essentially synchronously, until allocations start succeeding again. # # This currently doesn't handle the bitmap array, since that can be of # any length, so we can't have a static version of it at this point. Index: test/arch/um/drivers/ubd_kern.c =================================================================== --- test.orig/arch/um/drivers/ubd_kern.c 2005-09-17 17:40:08.000000000 -0400 +++ test/arch/um/drivers/ubd_kern.c 2005-09-17 17:40:34.000000000 -0400 @@ -511,6 +511,67 @@ void *bitmap_buf; }; +static int allocations; +static int fail_start, fail_end; + +static struct bitmap_io emergency_bitmap_io; +DECLARE_MUTEX(bitmap_io_sem); + +static struct bitmap_io *alloc_bitmap_io(void) +{ + struct bitmap_io *ret; + + allocations++; + ret = kmalloc(sizeof(*ret), GFP_KERNEL | GFP_ATOMIC); + + if((allocations >= fail_start) && (allocations < fail_end)){ + kfree(ret); + ret = NULL; + } + + if(ret != NULL) + return ret; + + down(&bitmap_io_sem); + return(&emergency_bitmap_io); +} + +static void free_bitmap_io(struct bitmap_io *io) +{ + if(io == &emergency_bitmap_io) + up(&bitmap_io_sem); + else kfree(io); +} + +static struct ubd_aio emergency_aio; +DECLARE_MUTEX(aio_sem); + +static struct ubd_aio *alloc_ubd_aio(void) +{ + struct ubd_aio *ret; + + allocations++; + ret = kmalloc(sizeof(*ret), GFP_KERNEL | GFP_ATOMIC); + + if((allocations >= fail_start) && (allocations < fail_end)){ + kfree(ret); + ret = NULL; + } + + if(ret != NULL) + return ret; + + down(&aio_sem); + return(&emergency_aio); +} + +static void free_ubd_aio(struct ubd_aio *aio) +{ + if(aio == &emergency_aio) + up(&aio_sem); + else kfree(aio); +} + static int ubd_reply_fd = -1; static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused) @@ -541,7 +602,7 @@ (atomic_dec_and_test(&aio->bitmap->count))){ aio->aio = aio->bitmap->aio; aio->len = 0; - kfree(aio->bitmap); + free_bitmap_io(aio->bitmap); aio->bitmap = NULL; submit_aio(&aio->aio); } @@ -554,16 +615,16 @@ if(aio->bitmap_buf != NULL) kfree(aio->bitmap_buf); - kfree(aio); + free_ubd_aio(aio); } } else if(n < 0){ ubd_finish(aio->req, n); if(aio->bitmap != NULL) - kfree(aio->bitmap); + free_bitmap_io(aio->bitmap); if(aio->bitmap_buf != NULL) kfree(aio->bitmap_buf); - kfree(aio); + free_ubd_aio(aio); } } reactivate_fd(fd, UBD_IRQ); @@ -1247,6 +1308,8 @@ __u64 off; if(req->bitmap_start != -1){ + bitmap_io = alloc_bitmap_io(); + /* Round up to the nearest word */ int round = sizeof(unsigned long); len = (req->bitmap_end - req->bitmap_start + @@ -1256,18 +1319,11 @@ off = req->bitmap_start / (8 * round); off *= round; - bitmap_io = kmalloc(sizeof(*bitmap_io), GFP_KERNEL); - if(bitmap_io == NULL){ - printk("Failed to kmalloc bitmap IO\n"); - req->error = 1; - return; - } - bitmap_buf = kmalloc(len, GFP_KERNEL); if(bitmap_buf == NULL){ printk("do_io : kmalloc of bitmap chunk " "failed\n"); - kfree(bitmap_io); + free_bitmap_io(bitmap_io); req->error = 1; return; } @@ -1300,12 +1356,7 @@ len = (end - start) * req->sectorsize; buf = &req->buffer[start * req->sectorsize]; - aio = kmalloc(sizeof(*aio), GFP_KERNEL); - if(aio == NULL){ - req->error = 1; - return; - } - + aio = alloc_ubd_aio(); *aio = ((struct ubd_aio) { .aio = INIT_AIO(req->op, req->fds[bit], buf, len, off, ubd_reply_fd),