aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2005-05-20 16:59:11 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-20 18:48:18 -0400
commit7b9014c1da380384efe7752db38a0253a74d0238 (patch)
tree5120dc5b523664068b2fa2bdfa153db71d5a37a9
parent9b67a3c4cd380968bffe8efb681470acda42b441 (diff)
[PATCH] uml: Remove ubd-mmap support
Finally rip out the ubd-mmap code, which turned out to be broken by design. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: <viro@parcelfarce.linux.theplanet.co.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/um/drivers/ubd_kern.c296
-rw-r--r--arch/um/kernel/trap_kern.c29
2 files changed, 3 insertions, 322 deletions
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 9a56ff94308d..88f956c34fed 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -55,7 +55,7 @@
55#include "mem_kern.h" 55#include "mem_kern.h"
56#include "cow.h" 56#include "cow.h"
57 57
58enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP }; 58enum ubd_req { UBD_READ, UBD_WRITE };
59 59
60struct io_thread_req { 60struct io_thread_req {
61 enum ubd_req op; 61 enum ubd_req op;
@@ -68,8 +68,6 @@ struct io_thread_req {
68 unsigned long sector_mask; 68 unsigned long sector_mask;
69 unsigned long long cow_offset; 69 unsigned long long cow_offset;
70 unsigned long bitmap_words[2]; 70 unsigned long bitmap_words[2];
71 int map_fd;
72 unsigned long long map_offset;
73 int error; 71 int error;
74}; 72};
75 73
@@ -122,10 +120,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
122 120
123#define MAX_DEV (8) 121#define MAX_DEV (8)
124 122
125/* Changed in early boot */
126static int ubd_do_mmap = 0;
127#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
128
129static struct block_device_operations ubd_blops = { 123static struct block_device_operations ubd_blops = {
130 .owner = THIS_MODULE, 124 .owner = THIS_MODULE,
131 .open = ubd_open, 125 .open = ubd_open,
@@ -175,12 +169,6 @@ struct ubd {
175 int no_cow; 169 int no_cow;
176 struct cow cow; 170 struct cow cow;
177 struct platform_device pdev; 171 struct platform_device pdev;
178
179 int map_writes;
180 int map_reads;
181 int nomap_writes;
182 int nomap_reads;
183 int write_maps;
184}; 172};
185 173
186#define DEFAULT_COW { \ 174#define DEFAULT_COW { \
@@ -200,11 +188,6 @@ struct ubd {
200 .openflags = OPEN_FLAGS, \ 188 .openflags = OPEN_FLAGS, \
201 .no_cow = 0, \ 189 .no_cow = 0, \
202 .cow = DEFAULT_COW, \ 190 .cow = DEFAULT_COW, \
203 .map_writes = 0, \
204 .map_reads = 0, \
205 .nomap_writes = 0, \
206 .nomap_reads = 0, \
207 .write_maps = 0, \
208} 191}
209 192
210struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; 193struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
@@ -314,13 +297,6 @@ static int ubd_setup_common(char *str, int *index_out)
314 int major; 297 int major;
315 298
316 str++; 299 str++;
317 if(!strcmp(str, "mmap")){
318 CHOOSE_MODE(printk("mmap not supported by the ubd "
319 "driver in tt mode\n"),
320 ubd_do_mmap = 1);
321 return(0);
322 }
323
324 if(!strcmp(str, "sync")){ 300 if(!strcmp(str, "sync")){
325 global_openflags = of_sync(global_openflags); 301 global_openflags = of_sync(global_openflags);
326 return(0); 302 return(0);
@@ -524,7 +500,7 @@ static void ubd_handler(void)
524{ 500{
525 struct io_thread_req req; 501 struct io_thread_req req;
526 struct request *rq = elv_next_request(ubd_queue); 502 struct request *rq = elv_next_request(ubd_queue);
527 int n, err; 503 int n;
528 504
529 do_ubd = NULL; 505 do_ubd = NULL;
530 intr_count++; 506 intr_count++;
@@ -538,19 +514,6 @@ static void ubd_handler(void)
538 return; 514 return;
539 } 515 }
540 516
541 if((req.op != UBD_MMAP) &&
542 ((req.offset != ((__u64) (rq->sector)) << 9) ||
543 (req.length != (rq->current_nr_sectors) << 9)))
544 panic("I/O op mismatch");
545
546 if(req.map_fd != -1){
547 err = physmem_subst_mapping(req.buffer, req.map_fd,
548 req.map_offset, 1);
549 if(err)
550 printk("ubd_handler - physmem_subst_mapping failed, "
551 "err = %d\n", -err);
552 }
553
554 ubd_finish(rq, req.error); 517 ubd_finish(rq, req.error);
555 reactivate_fd(thread_fd, UBD_IRQ); 518 reactivate_fd(thread_fd, UBD_IRQ);
556 do_ubd_request(ubd_queue); 519 do_ubd_request(ubd_queue);
@@ -583,14 +546,10 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
583 546
584static void ubd_close(struct ubd *dev) 547static void ubd_close(struct ubd *dev)
585{ 548{
586 if(ubd_do_mmap)
587 physmem_forget_descriptor(dev->fd);
588 os_close_file(dev->fd); 549 os_close_file(dev->fd);
589 if(dev->cow.file == NULL) 550 if(dev->cow.file == NULL)
590 return; 551 return;
591 552
592 if(ubd_do_mmap)
593 physmem_forget_descriptor(dev->cow.fd);
594 os_close_file(dev->cow.fd); 553 os_close_file(dev->cow.fd);
595 vfree(dev->cow.bitmap); 554 vfree(dev->cow.bitmap);
596 dev->cow.bitmap = NULL; 555 dev->cow.bitmap = NULL;
@@ -1010,94 +969,13 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1010 req->bitmap_words, bitmap_len); 969 req->bitmap_words, bitmap_len);
1011} 970}
1012 971
1013static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
1014{
1015 __u64 sector;
1016 unsigned char *bitmap;
1017 int bit, i;
1018
1019 /* mmap must have been requested on the command line */
1020 if(!ubd_do_mmap)
1021 return(-1);
1022
1023 /* The buffer must be page aligned */
1024 if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
1025 return(-1);
1026
1027 /* The request must be a page long */
1028 if((req->current_nr_sectors << 9) != PAGE_SIZE)
1029 return(-1);
1030
1031 if(dev->cow.file == NULL)
1032 return(dev->fd);
1033
1034 sector = offset >> 9;
1035 bitmap = (unsigned char *) dev->cow.bitmap;
1036 bit = ubd_test_bit(sector, bitmap);
1037
1038 for(i = 1; i < req->current_nr_sectors; i++){
1039 if(ubd_test_bit(sector + i, bitmap) != bit)
1040 return(-1);
1041 }
1042
1043 if(bit || (rq_data_dir(req) == WRITE))
1044 offset += dev->cow.data_offset;
1045
1046 /* The data on disk must be page aligned */
1047 if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
1048 return(-1);
1049
1050 return(bit ? dev->fd : dev->cow.fd);
1051}
1052
1053static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
1054 struct request *req,
1055 struct io_thread_req *io_req)
1056{
1057 int err;
1058
1059 if(rq_data_dir(req) == WRITE){
1060 /* Writes are almost no-ops since the new data is already in the
1061 * host page cache
1062 */
1063 dev->map_writes++;
1064 if(dev->cow.file != NULL)
1065 cowify_bitmap(io_req->offset, io_req->length,
1066 &io_req->sector_mask, &io_req->cow_offset,
1067 dev->cow.bitmap, dev->cow.bitmap_offset,
1068 io_req->bitmap_words,
1069 dev->cow.bitmap_len);
1070 }
1071 else {
1072 int w;
1073
1074 if((dev->cow.file != NULL) && (fd == dev->cow.fd))
1075 w = 0;
1076 else w = dev->openflags.w;
1077
1078 if((dev->cow.file != NULL) && (fd == dev->fd))
1079 offset += dev->cow.data_offset;
1080
1081 err = physmem_subst_mapping(req->buffer, fd, offset, w);
1082 if(err){
1083 printk("physmem_subst_mapping failed, err = %d\n",
1084 -err);
1085 return(1);
1086 }
1087 dev->map_reads++;
1088 }
1089 io_req->op = UBD_MMAP;
1090 io_req->buffer = req->buffer;
1091 return(0);
1092}
1093
1094/* Called with ubd_io_lock held */ 972/* Called with ubd_io_lock held */
1095static int prepare_request(struct request *req, struct io_thread_req *io_req) 973static int prepare_request(struct request *req, struct io_thread_req *io_req)
1096{ 974{
1097 struct gendisk *disk = req->rq_disk; 975 struct gendisk *disk = req->rq_disk;
1098 struct ubd *dev = disk->private_data; 976 struct ubd *dev = disk->private_data;
1099 __u64 offset; 977 __u64 offset;
1100 int len, fd; 978 int len;
1101 979
1102 if(req->rq_status == RQ_INACTIVE) return(1); 980 if(req->rq_status == RQ_INACTIVE) return(1);
1103 981
@@ -1114,34 +992,12 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
1114 992
1115 io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; 993 io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
1116 io_req->fds[1] = dev->fd; 994 io_req->fds[1] = dev->fd;
1117 io_req->map_fd = -1;
1118 io_req->cow_offset = -1; 995 io_req->cow_offset = -1;
1119 io_req->offset = offset; 996 io_req->offset = offset;
1120 io_req->length = len; 997 io_req->length = len;
1121 io_req->error = 0; 998 io_req->error = 0;
1122 io_req->sector_mask = 0; 999 io_req->sector_mask = 0;
1123 1000
1124 fd = mmap_fd(req, dev, io_req->offset);
1125 if(fd > 0){
1126 /* If mmapping is otherwise OK, but the first access to the
1127 * page is a write, then it's not mapped in yet. So we have
1128 * to write the data to disk first, then we can map the disk
1129 * page in and continue normally from there.
1130 */
1131 if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
1132 io_req->map_fd = dev->fd;
1133 io_req->map_offset = io_req->offset +
1134 dev->cow.data_offset;
1135 dev->write_maps++;
1136 }
1137 else return(prepare_mmap_request(dev, fd, io_req->offset, req,
1138 io_req));
1139 }
1140
1141 if(rq_data_dir(req) == READ)
1142 dev->nomap_reads++;
1143 else dev->nomap_writes++;
1144
1145 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; 1001 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
1146 io_req->offsets[0] = 0; 1002 io_req->offsets[0] = 0;
1147 io_req->offsets[1] = dev->cow.data_offset; 1003 io_req->offsets[1] = dev->cow.data_offset;
@@ -1229,143 +1085,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1229 return(-EINVAL); 1085 return(-EINVAL);
1230} 1086}
1231 1087
1232static int ubd_check_remapped(int fd, unsigned long address, int is_write,
1233 __u64 offset)
1234{
1235 __u64 bitmap_offset;
1236 unsigned long new_bitmap[2];
1237 int i, err, n;
1238
1239 /* If it's not a write access, we can't do anything about it */
1240 if(!is_write)
1241 return(0);
1242
1243 /* We have a write */
1244 for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
1245 struct ubd *dev = &ubd_dev[i];
1246
1247 if((dev->fd != fd) && (dev->cow.fd != fd))
1248 continue;
1249
1250 /* It's a write to a ubd device */
1251
1252 /* This should be impossible now */
1253 if(!dev->openflags.w){
1254 /* It's a write access on a read-only device - probably
1255 * shouldn't happen. If the kernel is trying to change
1256 * something with no intention of writing it back out,
1257 * then this message will clue us in that this needs
1258 * fixing
1259 */
1260 printk("Write access to mapped page from readonly ubd "
1261 "device %d\n", i);
1262 return(0);
1263 }
1264
1265 /* It's a write to a writeable ubd device - it must be COWed
1266 * because, otherwise, the page would have been mapped in
1267 * writeable
1268 */
1269
1270 if(!dev->cow.file)
1271 panic("Write fault on writeable non-COW ubd device %d",
1272 i);
1273
1274 /* It should also be an access to the backing file since the
1275 * COW pages should be mapped in read-write
1276 */
1277
1278 if(fd == dev->fd)
1279 panic("Write fault on a backing page of ubd "
1280 "device %d\n", i);
1281
1282 /* So, we do the write, copying the backing data to the COW
1283 * file...
1284 */
1285
1286 err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
1287 if(err < 0)
1288 panic("Couldn't seek to %lld in COW file of ubd "
1289 "device %d, err = %d",
1290 offset + dev->cow.data_offset, i, -err);
1291
1292 n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
1293 if(n != PAGE_SIZE)
1294 panic("Couldn't copy data to COW file of ubd "
1295 "device %d, err = %d", i, -n);
1296
1297 /* ... updating the COW bitmap... */
1298
1299 cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
1300 dev->cow.bitmap, dev->cow.bitmap_offset,
1301 new_bitmap, dev->cow.bitmap_len);
1302
1303 err = os_seek_file(dev->fd, bitmap_offset);
1304 if(err < 0)
1305 panic("Couldn't seek to %lld in COW file of ubd "
1306 "device %d, err = %d", bitmap_offset, i, -err);
1307
1308 n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
1309 if(n != sizeof(new_bitmap))
1310 panic("Couldn't update bitmap of ubd device %d, "
1311 "err = %d", i, -n);
1312
1313 /* Maybe we can map the COW page in, and maybe we can't. If
1314 * it is a pre-V3 COW file, we can't, since the alignment will
1315 * be wrong. If it is a V3 or later COW file which has been
1316 * moved to a system with a larger page size, then maybe we
1317 * can't, depending on the exact location of the page.
1318 */
1319
1320 offset += dev->cow.data_offset;
1321
1322 /* Remove the remapping, putting the original anonymous page
1323 * back. If the COW file can be mapped in, that is done.
1324 * Otherwise, the COW page is read in.
1325 */
1326
1327 if(!physmem_remove_mapping((void *) address))
1328 panic("Address 0x%lx not remapped by ubd device %d",
1329 address, i);
1330 if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
1331 physmem_subst_mapping((void *) address, dev->fd,
1332 offset, 1);
1333 else {
1334 err = os_seek_file(dev->fd, offset);
1335 if(err < 0)
1336 panic("Couldn't seek to %lld in COW file of "
1337 "ubd device %d, err = %d", offset, i,
1338 -err);
1339
1340 n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
1341 if(n != PAGE_SIZE)
1342 panic("Failed to read page from offset %llx of "
1343 "COW file of ubd device %d, err = %d",
1344 offset, i, -n);
1345 }
1346
1347 return(1);
1348 }
1349
1350 /* It's not a write on a ubd device */
1351 return(0);
1352}
1353
1354static struct remapper ubd_remapper = {
1355 .list = LIST_HEAD_INIT(ubd_remapper.list),
1356 .proc = ubd_check_remapped,
1357};
1358
1359static int ubd_remapper_setup(void)
1360{
1361 if(ubd_do_mmap)
1362 register_remapper(&ubd_remapper);
1363
1364 return(0);
1365}
1366
1367__initcall(ubd_remapper_setup);
1368
1369static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) 1088static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
1370{ 1089{
1371 struct uml_stat buf1, buf2; 1090 struct uml_stat buf1, buf2;
@@ -1568,15 +1287,6 @@ void do_io(struct io_thread_req *req)
1568 int err; 1287 int err;
1569 __u64 off; 1288 __u64 off;
1570 1289
1571 if(req->op == UBD_MMAP){
1572 /* Touch the page to force the host to do any necessary IO to
1573 * get it into memory
1574 */
1575 n = *((volatile int *) req->buffer);
1576 req->error = update_bitmap(req);
1577 return;
1578 }
1579
1580 nsectors = req->length / req->sectorsize; 1290 nsectors = req->length / req->sectorsize;
1581 start = 0; 1291 start = 0;
1582 do { 1292 do {
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 9ae2eff0d8f3..1de22d8a313a 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -107,33 +107,6 @@ out_of_memory:
107 goto out; 107 goto out;
108} 108}
109 109
110LIST_HEAD(physmem_remappers);
111
112void register_remapper(struct remapper *info)
113{
114 list_add(&info->list, &physmem_remappers);
115}
116
117static int check_remapped_addr(unsigned long address, int is_write)
118{
119 struct remapper *remapper;
120 struct list_head *ele;
121 __u64 offset;
122 int fd;
123
124 fd = phys_mapping(__pa(address), &offset);
125 if(fd == -1)
126 return(0);
127
128 list_for_each(ele, &physmem_remappers){
129 remapper = list_entry(ele, struct remapper, list);
130 if((*remapper->proc)(fd, address, is_write, offset))
131 return(1);
132 }
133
134 return(0);
135}
136
137/* 110/*
138 * We give a *copy* of the faultinfo in the regs to segv. 111 * We give a *copy* of the faultinfo in the regs to segv.
139 * This must be done, since nesting SEGVs could overwrite 112 * This must be done, since nesting SEGVs could overwrite
@@ -152,8 +125,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
152 flush_tlb_kernel_vm(); 125 flush_tlb_kernel_vm();
153 return(0); 126 return(0);
154 } 127 }
155 else if(check_remapped_addr(address & PAGE_MASK, is_write))
156 return(0);
157 else if(current->mm == NULL) 128 else if(current->mm == NULL)
158 panic("Segfault with no mm"); 129 panic("Segfault with no mm");
159 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); 130 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);