diff options
author | jdike <jdike> | 2003-12-19 20:42:42 +0000 |
---|---|---|
committer | jdike <jdike> | 2003-12-19 20:42:42 +0000 |
commit | 1cbc3105740ec0ab9fc59cbc237935d9b58ced61 (patch) | |
tree | 0bc10e64dc667cef612cd1dbcc6e00775d84d2d8 | |
parent | 496f1bd3879adf125ab7a1afd9638cd232ac365b (diff) | |
download | uml-history-1cbc3105740ec0ab9fc59cbc237935d9b58ced61.tar.gz |
Fixed the COW bitmap overrun error.
-rw-r--r-- | arch/um/drivers/ubd_kern.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 3167a9b..d82f409 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -859,7 +859,8 @@ static int ubd_release(struct inode * inode, struct file * file) static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, __u64 *cow_offset, unsigned long *bitmap, - __u64 bitmap_offset, unsigned long *bitmap_words) + __u64 bitmap_offset, unsigned long *bitmap_words, + __u64 bitmap_len) { __u64 sector = io_offset >> 9; int i, update_bitmap = 0; @@ -878,6 +879,16 @@ static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, return; *cow_offset = sector / (sizeof(unsigned long) * 8); + + /* This takes care of the case where we're exactly at the end of the + * device, and *cow_offset + 1 is off the end. So, just back it up + * by one word. Thanks to Lynn Kerby for the fix and James McMechan + * for the original diagnosis. + */ + if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) / + sizeof(unsigned long) - 1)) + (*cow_offset)--; + bitmap_words[0] = bitmap[*cow_offset]; bitmap_words[1] = bitmap[*cow_offset + 1]; @@ -886,7 +897,7 @@ static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, } static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, - __u64 bitmap_offset) + __u64 bitmap_offset, __u64 bitmap_len) { __u64 sector = req->offset >> 9; int i; @@ -904,7 +915,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, } else cowify_bitmap(req->offset, req->length, &req->sector_mask, &req->cow_offset, bitmap, bitmap_offset, - req->bitmap_words); + req->bitmap_words, bitmap_len); } static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset) @@ -962,7 +973,8 @@ static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset, cowify_bitmap(io_req->offset, io_req->length, &io_req->sector_mask, &io_req->cow_offset, dev->cow.bitmap, dev->cow.bitmap_offset, - io_req->bitmap_words); + io_req->bitmap_words, + dev->cow.bitmap_len); } else { int w; @@ -1046,7 +1058,8 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) io_req->sectorsize = 1 << 9; if(dev->cow.file != NULL) - cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset); + cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, + dev->cow.bitmap_len); return(0); } @@ -1297,7 +1310,7 @@ static int ubd_check_remapped(int fd, unsigned long address, int is_write, cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset, dev->cow.bitmap, dev->cow.bitmap_offset, - new_bitmap); + new_bitmap, dev->cow.bitmap_len); err = os_seek_file(dev->fd, bitmap_offset); if(err < 0) |