# 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 buffers are protected by flags which # are set when they are currently in use. The use of these flags is # protected by the queue lock, which is held for the duration of the # do_ubd_request call. # # 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-27 12:02:00.000000000 -0400 +++ test/arch/um/drivers/ubd_kern.c 2005-09-27 12:02:19.000000000 -0400 @@ -518,6 +518,73 @@ void *bitmap_buf; }; +static int allocations; +static int fail_start, fail_end; + +static struct bitmap_io emergency_bitmap_io; +static int bitmap_io_taken = 0; + +static struct bitmap_io *alloc_bitmap_io(void) +{ + struct bitmap_io *ret; + + allocations++; + ret = kmalloc(sizeof(*ret), GFP_ATOMIC); + + if((allocations >= fail_start) && (allocations < fail_end)){ + kfree(ret); + ret = NULL; + } + + if(ret != NULL) + return ret; + + if(bitmap_io_taken) + return ERR_PTR(-EAGAIN); + + bitmap_io_taken = 1; + return(&emergency_bitmap_io); +} + +static void free_bitmap_io(struct bitmap_io *io) +{ + if(io == &emergency_bitmap_io) + bitmap_io_taken = 0; + else kfree(io); +} + +static struct ubd_aio emergency_aio; +static int aio_taken = 0; + +static struct ubd_aio *alloc_ubd_aio(void) +{ + struct ubd_aio *ret; + + allocations++; + ret = kmalloc(sizeof(*ret), GFP_ATOMIC); + + if((allocations >= fail_start) && (allocations < fail_end)){ + kfree(ret); + ret = NULL; + } + + if(ret != NULL) + return ret; + + if(aio_taken) + return ERR_PTR(-EAGAIN); + + aio_taken = 1; + return(&emergency_aio); +} + +static void free_ubd_aio(struct ubd_aio *aio) +{ + if(aio == &emergency_aio) + aio_taken = 0; + else kfree(aio); +} + static int ubd_reply_fd = -1; static struct list_head restart = LIST_HEAD_INIT(restart); @@ -552,7 +619,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); } @@ -565,16 +632,16 @@ if(aio->bitmap_buf != NULL) kfree(aio->bitmap_buf); - kfree(aio); + free_ubd_aio(aio); } } else if(n < 0){ ubd_finish(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); } } list_for_each_safe(list, next, &restart){ @@ -1274,6 +1341,10 @@ if(req->bitmap_start != -1){ /* Round up to the nearest word */ int round = sizeof(unsigned long); + bitmap_io = alloc_bitmap_io(); + if(IS_ERR(bitmap_io)) + return PTR_ERR(bitmap_io); + len = (req->bitmap_end - req->bitmap_start + round * 8 - 1) / (round * 8); len *= round; @@ -1281,18 +1352,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 -ENOMEM; - } - 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 -ENOMEM; } @@ -1325,11 +1389,9 @@ len = (end - start) * req->sectorsize; buf = &req->buffer[start * req->sectorsize]; - aio = kmalloc(sizeof(*aio), GFP_KERNEL); - if(aio == NULL){ - req->error = 1; - return -ENOMEM; - } + aio = alloc_ubd_aio(); + if(IS_ERR(aio)) + return PTR_ERR(aio); *aio = ((struct ubd_aio) { .aio = INIT_AIO(req->op, req->fds[bit], buf,