summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjdike <jdike>2003-12-19 20:42:42 +0000
committerjdike <jdike>2003-12-19 20:42:42 +0000
commit1cbc3105740ec0ab9fc59cbc237935d9b58ced61 (patch)
tree0bc10e64dc667cef612cd1dbcc6e00775d84d2d8
parent496f1bd3879adf125ab7a1afd9638cd232ac365b (diff)
downloaduml-history-1cbc3105740ec0ab9fc59cbc237935d9b58ced61.tar.gz
Fixed the COW bitmap overrun error.
-rw-r--r--arch/um/drivers/ubd_kern.c25
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)