Fixes probably to the ubd-mmap code, and especially for the fault-handling code. Catch the fault for mmaped ubd memory only if happened in kernel space. Signed-off-by: Paolo 'Blaisorblade' Giarrusso --- um-linux-2.4.27-paolo/arch/um/drivers/ubd_kern.c | 12 ++++++++-- um-linux-2.4.27-paolo/arch/um/include/mem.h | 2 - um-linux-2.4.27-paolo/arch/um/include/mem_kern.h | 2 - um-linux-2.4.27-paolo/arch/um/kernel/physmem.c | 27 +++++++++++++++++------ um-linux-2.4.27-paolo/arch/um/kernel/trap_kern.c | 6 ++--- 5 files changed, 36 insertions(+), 13 deletions(-) diff -puN arch/um/kernel/trap_kern.c~remapper-fix arch/um/kernel/trap_kern.c --- um-linux-2.4.27/arch/um/kernel/trap_kern.c~remapper-fix 2005-04-15 11:12:56.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/trap_kern.c 2005-04-15 11:12:56.000000000 +0200 @@ -94,7 +94,7 @@ void register_remapper(struct remapper * list_add(&info->list, &physmem_remappers); } -static int check_remapped_addr(unsigned long address, int is_write) +static int check_remapped_addr(unsigned long address, int is_write, int is_user) { struct remapper *remapper; struct list_head *ele; @@ -107,7 +107,7 @@ static int check_remapped_addr(unsigned list_for_each(ele, &physmem_remappers){ remapper = list_entry(ele, struct remapper, list); - if((*remapper->proc)(fd, address, is_write, offset)) + if((*remapper->proc)(fd, address, is_write, offset, is_user)) return(1); } @@ -125,7 +125,7 @@ unsigned long segv(unsigned long address flush_tlb_kernel_vm(); return(0); } - else if(check_remapped_addr(address & PAGE_MASK, is_write)) + else if(check_remapped_addr(address & PAGE_MASK, is_write, is_user)) return(0); else if(current->mm == NULL) panic("Segfault with no mm"); diff -puN arch/um/drivers/ubd_kern.c~remapper-fix arch/um/drivers/ubd_kern.c --- um-linux-2.4.27/arch/um/drivers/ubd_kern.c~remapper-fix 2005-04-15 11:12:56.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/drivers/ubd_kern.c 2005-04-15 11:12:56.000000000 +0200 @@ -1043,7 +1043,7 @@ static int prepare_request(struct reques * to write the data to disk first, then we can map the disk * page in and continue normally from there. */ - if((req->cmd == WRITE) && !is_remapped(req->buffer)){ + if((req->cmd == WRITE) && !is_remapped(req->buffer, dev->fd, io_req->offset + dev->cow.data_offset)){ io_req->map_fd = dev->fd; io_req->map_offset = io_req->offset + dev->cow.data_offset; @@ -1249,12 +1249,20 @@ static int ubd_revalidate(kdev_t rdev) } static int ubd_check_remapped(int fd, unsigned long address, int is_write, - __u64 offset) + __u64 offset, int is_user) { __u64 bitmap_offset; unsigned long new_bitmap[2]; int i, err, n; + /* This can only fix kernelspace faults */ + if(is_user) + return(0); + + /* ubd-mmap is only enabled in skas mode */ + if(CHOOSE_MODE(1, 0)) + return(0); + /* If it's not a write access, we can't do anything about it */ if(!is_write) return(0); diff -puN arch/um/include/mem.h~remapper-fix arch/um/include/mem.h --- um-linux-2.4.27/arch/um/include/mem.h~remapper-fix 2005-04-15 11:12:56.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/include/mem.h 2005-04-15 11:12:56.000000000 +0200 @@ -11,7 +11,7 @@ extern void set_kmem_end(unsigned long new); extern int phys_mapping(unsigned long phys, __u64 *offset_out); extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w); -extern int is_remapped(void *virt); +extern int is_remapped(const void *virt, int fd, __u64 offset); extern int physmem_remove_mapping(void *virt); extern void physmem_forget_descriptor(int fd); diff -puN arch/um/include/mem_kern.h~remapper-fix arch/um/include/mem_kern.h --- um-linux-2.4.27/arch/um/include/mem_kern.h~remapper-fix 2005-04-15 11:12:56.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/include/mem_kern.h 2005-04-15 11:12:56.000000000 +0200 @@ -11,7 +11,7 @@ struct remapper { struct list_head list; - int (*proc)(int, unsigned long, int, __u64); + int (*proc)(int, unsigned long, int, __u64, int); }; extern void register_remapper(struct remapper *info); diff -puN arch/um/kernel/physmem.c~remapper-fix arch/um/kernel/physmem.c --- um-linux-2.4.27/arch/um/kernel/physmem.c~remapper-fix 2005-04-15 11:12:56.000000000 +0200 +++ um-linux-2.4.27-paolo/arch/um/kernel/physmem.c 2005-04-15 11:12:56.000000000 +0200 @@ -100,14 +100,19 @@ int physmem_subst_mapping(void *virt, in unsigned long phys; int err; + phys = __pa(virt); + desc = find_virtmem_hash(&virtmem_hash, (void *) virt); + if(desc != NULL){ + if((virt != desc->virt) || (fd != desc->fd) || + (offset != desc->offset)) + panic("Address 0x%p is already substituted\n", virt); + return(0); + } + fd_maps = descriptor_mapping(fd); if(fd_maps == NULL) return(-ENOMEM); - phys = __pa(virt); - if(find_virtmem_hash(&virtmem_hash, virt) != NULL) - panic("Address 0x%p is already substituted\n", virt); - err = -ENOMEM; desc = kmalloc(sizeof(*desc), GFP_ATOMIC); if(desc == NULL) @@ -178,6 +183,9 @@ void physmem_forget_descriptor(int fd) if(desc == NULL) return; + if(!list_empty(&desc->pages)) + printk("Still have mapped pages on fd %d\n", fd); + list_for_each_safe(ele, next, &desc->pages){ page = list_entry(ele, struct phys_desc, list); offset = page->offset; @@ -210,9 +218,16 @@ void arch_free_page(struct page *page, i } } -int is_remapped(void *virt) +int is_remapped(const void *virt, int fd, __u64 offset) { - return(find_virtmem_hash(&virtmem_hash, virt) != NULL); + struct phys_desc *desc; + + desc = find_virtmem_hash(&virtmem_hash, (void *) virt); + if(desc == NULL) + return(0); + if(offset != desc->offset) + printk("offset mismatch\n"); + return(find_virtmem_hash(&virtmem_hash, (void *) virt) != NULL); } /* Changed during early boot */ _