# It is important that I/O requests be submitted to the host in the # order that they are received by the driver, especially since the # driver can sleep. This patch adds two atomic counters, one for # requests started and one for requests submitted to the host. A new # request can proceed when started (after being incremented) is one # more than submitted. submitted is incremented after all pieces of # the request have been sent to the host. # When a request is proceeding out of order, it will sleep on a wait # queue until its number comes up. # # Interaction between this wait_queue and the emergency allocation # semaphore - a request will only try to allocate data when it is # its turn to go. The wait_queue is finished before the semaphore is # acquired, so there can't be a deadlock between one process holding # the allocation semaphore and sleeping because it's out of order and # one proceeding in order and sleeping on the allocation semaphore. # # This currently doesn't correctly handle the bitmap, which must be # written after the data has been finished. These must be sequenced # in the same way as the data. Index: test/arch/um/drivers/ubd_kern.c =================================================================== --- test.orig/arch/um/drivers/ubd_kern.c 2005-09-17 17:40:34.000000000 -0400 +++ test/arch/um/drivers/ubd_kern.c 2005-09-17 17:40:53.000000000 -0400 @@ -1297,6 +1297,10 @@ return(err); } +static atomic_t started = ATOMIC_INIT(0); +static atomic_t submitted = ATOMIC_INIT(0); +DECLARE_WAIT_QUEUE_HEAD(sequence_queue); + void do_io(struct io_thread_req *req, struct request *r, unsigned long *bitmap) { struct ubd_aio *aio; @@ -1304,14 +1308,18 @@ char *buf; void *bitmap_buf = NULL; unsigned long len, sector; - int nsectors, start, end, bit, err; + int nsectors, start, end, bit, err, want; __u64 off; - if(req->bitmap_start != -1){ - bitmap_io = alloc_bitmap_io(); + want = atomic_add_return(1, &started); + wait_event(sequence_queue, want - 1 == atomic_read(&submitted)); + if(req->bitmap_start != -1){ /* Round up to the nearest word */ int round = sizeof(unsigned long); + + bitmap_io = alloc_bitmap_io(); + len = (req->bitmap_end - req->bitmap_start + round * 8 - 1) / (round * 8); len *= round; @@ -1378,4 +1386,7 @@ start = end; } while(start < nsectors); + + atomic_inc(&submitted); + wake_up(&sequence_queue); }