RE: patch for migshm
"Moshe Bar" <moshe-ay74M1d3r6RWk0Htik3J/[email protected]>
| Newsgroups | gmane.linux.cluster.openmosix.devel |
|---|---|
| Organization | Morpheus Holdings, Inc |
| Message-ID | <[email protected]> |
Ratna Thanks a lot of this. Lots of people have been asking for it. I will compile and test this week-end when I get back home. Many thanks Moshe -----Original Message----- From: Ratna Manoj Bolla [mailto:[email protected]] Sent: Monday, May 08, 2006 5:35 AM To: openmosix-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org Cc: moshe-ay74M1d3r6RWk0Htik3J/[email protected] Subject: patch for migshm Below is the patch for MigShm. - No STAY_FOR_MONKEY flag - implemented Distributed shared memory. - MAP_SHARED mappings can now migrate. -more debugging has to be done. plz report bugs and suggestions. below is my one of the test program followed by patch. #include<stdio.h> #include<sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> char *pid2proc_path(int); char path[50]; int b[80]; main() { int fd = open("om_file",O_RDWR); char *a = mmap(0,4096*15,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); int i = 0; unsigned long k=0; char *b =a;// mmap(0,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0); fork(); fork(); fork(); fork(); while(k++ <= 0xffffff00); k=0; while(k++ <= 0xffffff00); k=0; // while(k++ <= 0xffffff00); k=0; // while(k++ <= 0xffffff00); k=0; // while(k++ <= 0xffffff00); k=0; char ch = 'A'; while(1) { i++; if(i== 15000) break; // sleep(1); if(ch == 'Z') ch = 'A'; *a = ch; // sleep(1); printf("p:%d-%c\n",i,*a); a+=3; ch++; } } Patch: diff -Naur linux-2.4.26-om1/fs/file_table.c linux-2.4.26-om1-o/fs/file_table.c --- linux-2.4.26-om1/fs/file_table.c 2006-05-08 15:01:47.000000000 +0530 +++ linux-2.4.26-om1-o/fs/file_table.c 2006-05-07 17:56:02.000000000 +0530 @@ -13,6 +13,7 @@ #include <linux/smp_lock.h> #include <linux/iobuf.h> +#include <hpc/mig_shm.h> /* sysctl tunables... */ struct files_stat_struct files_stat = {0, 0, NR_FILE}; @@ -104,8 +105,12 @@ struct inode * inode = dentry->d_inode; if (atomic_dec_and_test(&file->f_count)) { +#ifdef CONFIG_MOSIX + if(current->mosix.dflags & DREMOTE) + shm_send_message(current->mosix.deppe,(struct shm_page *)(home_file(file)),NULL,PUT_FILE); +#endif /* CONFIG_MOSIX */ locks_remove_flock(file); - + if (file->f_iobuf) free_kiovec(1, &file->f_iobuf); diff -Naur linux-2.4.26-om1/fs/read_write.c linux-2.4.26-om1-o/fs/read_write.c --- linux-2.4.26-om1/fs/read_write.c 2006-05-08 15:01:50.000000000 +0530 +++ linux-2.4.26-om1-o/fs/read_write.c 2006-05-07 17:56:02.000000000 +0530 @@ -169,10 +169,26 @@ } #endif +#ifdef CONFIG_MOSIX + +extern void +put_pages(struct address_space *mapping,loff_t offset,size_t count,int writer,unsigned long error); + +extern unsigned long +get_pages(struct address_space *mapping,loff_t offset,size_t count,int writer); + +#endif /* CONFIG_MOSIX */ + + + asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count) { ssize_t ret; struct file * file; +#ifdef CONFIG_MOSIX + unsigned long error=0; + loff_t offset; +#endif /* CONFIG_MOSIX */ #ifdef CONFIG_MOSIX_DFSA dfsa_syscall_on_file(fd, 1); @@ -186,10 +202,23 @@ if (!ret) { ssize_t (*read)(struct file *, char *, size_t, loff_t *); ret = -EINVAL; - if (file->f_op && (read = file->f_op->read) != NULL) - ret = read(file, buf, count, &file->f_pos); + if (file->f_op && (read = file->f_op->read) != NULL) +#ifdef CONFIG_MOSIX + { + error = get_pages(file->f_dentry->d_inode->i_mapping,(offset = file->f_pos),count,0); + if(!error) +#endif /* CONFIG_MOSIX */ + ret = read(file, buf, count, &file->f_pos); +#ifdef CONFIG_MOSIX + put_pages(file->f_dentry->d_inode->i_mapping,offset,count,0,error); + } +#endif /* CONFIG_MOSIX */ } } + + if(error) + ret = -1; + if (ret > 0) dnotify_parent(file->f_dentry, DN_ACCESS); fput(file); @@ -201,6 +230,10 @@ { ssize_t ret; struct file * file; +#ifdef CONFIG_MOSIX + unsigned long error=0; + loff_t offset; +#endif /* CONFIG_MOSIX */ #ifdef CONFIG_MOSIX_DFSA dfsa_syscall_on_file(fd, 1); @@ -215,10 +248,23 @@ if (!ret) { ssize_t (*write)(struct file *, const char *, size_t, loff_t *); ret = -EINVAL; - if (file->f_op && (write = file->f_op->write) != NULL) - ret = write(file, buf, count, &file->f_pos); - } + if (file->f_op && (write = file->f_op->write) != NULL) +#ifdef CONFIG_MOSIX + { + error = get_pages(file->f_dentry->d_inode->i_mapping,(offset = file->f_pos),count,1); + + if(!error) +#endif /* CONFIG_MOSIX */ + ret = write(file, buf, count, &file->f_pos); +#ifdef CONFIG_MOSIX + put_pages(file->f_dentry->d_inode->i_mapping,offset,count,1,error); + } +#endif /* CONFIG_MOSIX */ + } } + + if(error) + ret = -1; if (ret > 0) dnotify_parent(file->f_dentry, DN_MODIFY); fput(file); diff -Naur linux-2.4.26-om1/hpc/comm.c linux-2.4.26-om1-o/hpc/comm.c --- linux-2.4.26-om1/hpc/comm.c 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/comm.c 2006-05-07 17:56:02.000000000 +0530 @@ -31,7 +31,6 @@ #define MIG_DAEMON_PORT 0x3412 #define INFO_DAEMON_PORT 0x3415 - /* * mosix specific data per contact */ @@ -65,7 +64,7 @@ #define COMM_SOCKET_BUFFER 131072 #define COMM_REMOTE_TIMO ((unsigned long) 200*HZ) /* changed form 300 */ -#define COMM_CONNECT_TIMO ((unsigned long) 4*HZ) /* changed from 5 */ +#define COMM_CONNECT_TIMO ((unsigned long) 10*HZ) /* changed from 5 */ #define COMM_RECONN_TIMO ((unsigned long) 10*HZ) #ifdef CONFIG_MOSIX_DFSA @@ -171,7 +170,6 @@ static int comm_waitaccept(void); static int comm_poll(int, int, unsigned long); static void comm_data_ready(struct sock *, int); -static int comm_getname(struct socket *, struct sockaddr *); static void comm_shutdown(mosix_link *); static inline struct socket *comm_set_address(int, struct sockaddr *, int); @@ -315,8 +313,6 @@ him = ((int *) ptr)[0]; me = ((int *) ptr)[1]; - if (him & 0x80000000) - rinode_flush_files(him & ~0x80000000); if (comm_getpeer(current->mosix.contact) == (him & 0x7fffffff) && PE == me) ret = 2 * sizeof (int); @@ -367,6 +363,8 @@ */ switch (mos) { + case MIGSHM_COMM: + case COMM_MIGSHM: case COMM_INFO: sock->sk->data_ready = comm_data_ready; break; @@ -493,6 +491,8 @@ case COMM_LOOSE: bind = 0; /* fall through */ + case MIGSHM_COMM: + case COMM_MIGSHM: case COMM_INFO: listen = 0; /* fall through */ @@ -763,7 +763,7 @@ mosix_panic("comm_free() # 1"); out: - + return; } /* @@ -1564,6 +1564,7 @@ return (error); } +unsigned long AVG_TRIES = 2; /* * comm_recvfrom() - receive a datagram from someone * NOTE NOTE NOTE: the timeout is in microseconds -- NOT ticks! @@ -1580,7 +1581,14 @@ int error; int nrecv = len, msgflg = 0; DECLARE_WAITQUEUE(wait, current); + unsigned long tries = LONG_MAX; + unsigned long for_avg = 0; + if (timo == GTIME_OUT) + tries = 3 * AVG_TRIES-1; + else if (timo == INT_TIME_OUT) + tries = 4 * AVG_TRIES * NPE - 1; + else if (timo) { #if MILLION % HZ timo = timo * HZ / MILLION; @@ -1591,13 +1599,13 @@ oldfs = get_fs(); set_fs(KERNEL_DS); - if (timo) - msgflg |= MSG_DONTWAIT; + if(timo == GTIME_OUT || timo == INT_TIME_OUT || !timo) + timo = MAX_SCHEDULE_TIMEOUT; else - timo = MAX_SCHEDULE_TIMEOUT; + msgflg |= MSG_DONTWAIT; add_wait_queue(mlink->sock->sk->sleep, &wait); - while (1) { + while (tries) { set_current_state(msgflg ? TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE); @@ -1622,6 +1630,10 @@ error = -EINTR; break; } + if(tries != LONG_MAX) { + tries--; + for_avg++; + } } remove_wait_queue(mlink->sock->sk->sleep, &wait); set_current_state(TASK_RUNNING); @@ -1629,6 +1641,12 @@ if (msg.msg_flags & MSG_TRUNC) { error = -EDIST; + } else if(!tries) + error = -ETIME; + else if (tries != LONG_MAX ) { + AVG_TRIES = (AVG_TRIES + for_avg) / 2; + if(AVG_TRIES < 2) + AVG_TRIES = 2; } return (error); @@ -1681,7 +1699,7 @@ /* * comm_getname: fill in our name */ -static int +int comm_getname(struct socket *sock, struct sockaddr *saddr) { switch (comm_type) { @@ -1741,6 +1759,7 @@ case COMM_TOADDR: /* address was set by the caller */ break; + case COMM_MIGSHM: case COMM_INFO: proto = IPPROTO_UDP; type = SOCK_DGRAM; @@ -1751,10 +1770,17 @@ sa->sin_addr.s_addr = INADDR_ANY; if (mos == COMM_MIGD) sa->sin_port = MIG_DAEMON_PORT; - else + else if(mos == COMM_INFO) sa->sin_port = INFO_DAEMON_PORT; + else if(mos == COMM_MIGSHM) + sa->sin_port = MIGSHM_DEAMON_PORT; break; case COMM_ACCEPT: + case MIGSHM_COMM: + if(mos == MIGSHM_COMM) { + type = SOCK_DGRAM; + proto = IPPROTO_UDP; + } memset((void *) sa, 0, sizeof (struct sockaddr_in)); sa->sin_family = AF_INET; sa->sin_addr.s_addr = INADDR_ANY; diff -Naur linux-2.4.26-om1/hpc/deputy.c linux-2.4.26-om1-o/hpc/deputy.c --- linux-2.4.26-om1/hpc/deputy.c 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/deputy.c 2006-05-07 17:56:02.000000000 +0530 @@ -24,6 +24,9 @@ #include <asm/mmu_context.h> #include <linux/smp_lock.h> #include <linux/highmem.h> +#include <linux/pagemap.h> +#include <hpc/mig_shm.h> +#include <hpc/shm_pagemap.h> #ifdef CONFIG_MOSIX_DFSA #include <hpc/dfsa.h> #endif /* CONFIG_MOSIX_DFSA */ @@ -343,27 +346,30 @@ deputy_handle_interim_request(int type, void *head, int hlen) { switch (type) { - case REM_NOTHING: - comm_free(head); - return (comm_send(REM_NOTHING | REPLY, NULL, 0, NULL, 0, 0)); - case REM_PAGE: - return (deputy_bring_page((struct bring_page_h *) head)); - case REM_GETTSC: - return (deputy_tsc()); - case REM_MORESTRINGS: - return (deputy_more_strings - ((struct execve_more_strings_h *) head)); - case REM_BRING_ME_REGS: - return (deputy_bring_me_regs((unsigned long *) head)); - case REM_GETALOAD: - return (send_local_aload(REM_GETALOAD | REPLY)); - default: - printk("Process %s, uid=%d, received an unexpected " - "urgent request\n" "(type 0x%x) from the " - "remote site where it was running\n", - desc_mostask(NULL), current->uid, type); - comm_free(head); - return (-EDIST); + + case REM_UPGRADE: + return(deputy_upgrade((struct upgrade_h *)head)); + case REM_NOTHING: + comm_free(head); + return (comm_send(REM_NOTHING | REPLY, NULL, 0, NULL, 0, 0)); + case REM_PAGE: + return (deputy_bring_page((struct bring_page_h *) head)); + case REM_GETTSC: + return (deputy_tsc()); + case REM_MORESTRINGS: + return (deputy_more_strings + ((struct execve_more_strings_h *) head)); + case REM_BRING_ME_REGS: + return (deputy_bring_me_regs((unsigned long *) head)); + case REM_GETALOAD: + return (send_local_aload(REM_GETALOAD | REPLY)); + default: + printk("Process %s, uid=%d, received an unexpected " + "urgent request\n" "(type 0x%x) from the " + "remote site where it was running\n", + desc_mostask(NULL), current->uid, type); + comm_free(head); + return (-EDIST); } } @@ -431,29 +437,29 @@ unsigned long mosix_deputy_mmap(struct file *fp, unsigned long addr, int fixed, - unsigned long len, unsigned long flags, unsigned long off, - off_t isize, nopage_t nopage) + unsigned long len, unsigned long flags, unsigned long off, + off_t isize, nopage_t nopage) { - struct mmap_parameters_h mp; - int error; - unsigned long result; - - mp.addr = addr; - mp.fixed = fixed; - mp.len = len; - mp.flags = flags; - mp.pgoff = off; - mp.origin = PE; - if ((mp.fp = fp)) { - mp.dp = fp->f_dentry; - mp.uniq = mp.fp->f_dentry->d_inode->i_unique; - mp.isize = mp.fp->f_dentry->d_inode->i_size; - } - mp.nopage = nopage; - if ((error = deputy_request(DEP_MMAP, &mp, sizeof (mp), NULL, 0, 0, - (void **) &result, -sizeof (result)))) - return (error); - return (result); + struct mmap_parameters_h mp; + int error; + unsigned long result; + + mp.addr = addr; + mp.fixed = fixed; + mp.len = len; + mp.flags = flags; + mp.pgoff = off; + mp.origin = PE; + if ((mp.fp = fp)) { + mp.dp = fp->f_dentry; + mp.uniq = mp.fp->f_dentry->d_inode->i_unique; + mp.isize = mp.fp->f_dentry->d_inode->i_size; + } + mp.nopage = nopage; + if ((error = deputy_request(DEP_MMAP, &mp, sizeof (mp), NULL, 0, 0, + (void **) &result, -sizeof (result)))) + return (error); + return (result); } long @@ -519,9 +525,6 @@ case FATAL_SIGSEGV: force_sig(SIGSEGV, current); break; - case REMOTE_FILE_RELEASED: - mosix_rebuild_file_list(); - break; case SIGSEGV: case SIGKILL: case SIGVTALRM: @@ -910,31 +913,118 @@ } int +deputy_upgrade(struct upgrade_h *u) +{ + struct shm_page *shm_page = u->rem_shm_page_addr; + struct page *page = NULL; + struct shm_page_ret_h r; + int err; + + + spin_lock(&shm_page->shm_lock); + if((shm_page->state & PERM_ERR) || (shm_page->state & UPGRADE_ERR)) + r.ret = 2; + else + if(((shm_page->state & STATE_MASK) == SHARED) && !(shm_page->state & DROPPING) && (!shm_page->readers)) { + shm_page->state &= ~SHARED; + shm_page->state |= BUSY_EXCLUSIVE; + + spin_unlock(&shm_page->shm_lock); + page = find_get_page(shm_page->mapping,shm_page->index); + + if(page) { + invalidate(shm_page,page,1); + page_cache_release(page); + } + + + shm_send_message(0,shm_page,NULL,DROP_NEXTPREV); + + shm_page->next = shm_page->prev = PE; + shm_page->next_addr = shm_page->prev_addr = shm_page; + + spin_lock(&shm_page->shm_lock); + shm_page->owner = current->mosix.whereami; + shm_page->rem_shm_page_addr = u->shm_page; + + shm_page->state &= ~BUSY_EXCLUSIVE; + shm_page->state |= EXCLUSIVE; + r.ret = 0; + } else + r.ret = 1; + + spin_unlock(&shm_page->shm_lock); + + comm_free(u); + cli(); + r.deputytime = current->mosix.deputytime; + current->mosix.deputytime = 0; + sti(); + err = deputy_reply(REM_UPGRADE, &r, sizeof (r),NULL, 0, 0,2); + + return err; +} +int deputy_bring_page(struct bring_page_h *b) { struct file *fp = b->fp; struct vm_area_struct v; - struct page_ret_h r; + struct shm_page_ret_h r; int err; int address = b->offset; struct page *page; struct task_struct *p = current; + struct shm_page *shm_page=NULL; + + struct vm_operations_struct file_vm_ops = { + nopage: b->nopage, + }; + v.vm_start = v.vm_pgoff = 0; v.vm_end = address + PAGE_SIZE; v.vm_mm = p->mm; /* (eg. NULL) */ v.vm_file = fp; - v.vm_flags = 0; /* anything really, but VM_SHARED */ + v.vm_ops = &file_vm_ops; + + v.vm_flags = (unsigned long)b->rem_shm_page_addr; deeper_sleep(); - page = b->nopage(&v, address, 0); + + page = get_nopage(&v, address, &shm_page, (b->access & WITH_WRITE_ACC) ? 1 : 0); + lighter_sleep(); if (page == NOPAGE_OOM) { r.ret = -ENOMEM; - page = 0; - } else - r.ret = page ? 0 : -EFBIG; - comm_free(b); + page = NULL; + } else if(page == PAGE_BUSY) { + page = NULL; + r.ret = -EBUSY; + } + else + r.ret = (page ? 0 : -EINVAL); + + if(page && (b->access & (WITH_WRITE_ACC|WITH_READ_ACC))) { + + r.rem_shm_page_addr = shm_page; + + if(b->access & WITH_WRITE_ACC ) { + if((!(v.vm_start)) && (!(v.vm_end))) { + r.next = 0; + r.next_addr = NULL; + } else { + r.next_addr = (struct shm_page *)v.vm_start; + r.next = v.vm_end; + } + } else { + r.next = PE; + r.next_addr = shm_page; + r.prev = v.vm_end; + r.prev_addr = (struct shm_page *)(v.vm_start); + } + + } + cli(); r.deputytime = p->mosix.deputytime; p->mosix.deputytime = 0; @@ -942,13 +1032,77 @@ err = deputy_reply(REM_PAGE, &r, sizeof (r), page ? kmap(page) : NULL, page ? PAGE_SIZE : 0, 0, 2); - if (page) { - kunmap(page); - __free_page(page); + + if(shm_page) { + if(err) { + if(b->access & WITH_WRITE_ACC) { + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~BUSY_EXCLUSIVE; + if(!(v.vm_start) && !(v.vm_end)) { + shm_page->state |= EXCLUSIVE; + shm_page->owner = PE; + shm_page->prev = shm_page->next = PE; + shm_page->next_addr = shm_page->prev_addr = shm_page; + spin_unlock(&shm_page->shm_lock); + shm_pagecache_release(shm_page); + } else { + shm_page->state |= (SHARED|DROPPING); + spin_unlock(&shm_page->shm_lock); + shm_page->next = PE; + shm_page->next_addr = shm_page; + if(shm_send_message(shm_page->prev,shm_page,NULL,DROP_NEXT)) { + printk(KERN_ERR "reader loop broken because of %d Reboot all\n",shm_page->prev); + shm_page->owner = shm_page->next = shm_page->prev = PE; + shm_page->next_addr = shm_page->prev_addr = shm_page; + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~(SHARED|DROPPING); + shm_page->state |= EXCLUSIVE; + spin_unlock(&shm_page->shm_lock); + shm_pagecache_release(shm_page); + goto out; + } + shm_page->next = v.vm_end; + shm_page->next_addr = (struct shm_page *)v.vm_start; + shm_page->state &= ~DROPPING; + } + } else { + spin_lock(&shm_page->shm_lock); + if(shm_page->next == current->mosix.whereami) { + shm_page->prev = shm_page->next = PE; + shm_page->prev_addr = shm_page->next_addr = shm_page; + } else { + shm_page->prev = v.vm_end; + shm_page->prev_addr = (struct shm_page *)(v.vm_start); + } + shm_page->state &= ~DROPPING; + spin_unlock(&shm_page->shm_lock); + } + } else { + if(b->access & WITH_WRITE_ACC) { + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~BUSY_EXCLUSIVE; + shm_page->state |= EXCLUSIVE; + shm_page->owner = current->mosix.whereami; + shm_page->rem_shm_page_addr = b->rem_shm_page_addr; + shm_page->prev = shm_page->next = PE; + shm_page->next_addr = shm_page->prev_addr = shm_page; + spin_unlock(&shm_page->shm_lock); + } + } + out: + shm_pagecache_release(shm_page); } + + comm_free(b); + if (page) { + kunmap(page); + __free_page(page); + } return (err); } + + int deputy_tsc(void) { @@ -1143,8 +1297,7 @@ if (deputy_request(DEP_EXEC_MMAP, NULL, 0, NULL, 0, 0, (void **) &r, -sizeof (r))) return (-ENOMEM); - if (!r) - mosix_clear_all_held_files(current); + return (r); } diff -Naur linux-2.4.26-om1/hpc/init.c linux-2.4.26-om1-o/hpc/init.c --- linux-2.4.26-om1/hpc/init.c 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/init.c 2006-05-07 17:56:02.000000000 +0530 @@ -28,6 +28,30 @@ void init_mosix(void) { + extern struct super_block bad_super_block; + static struct super_operations empty_sops = {}; + struct super_block *s = &bad_super_block; + if (s) { + memset(s, 0, sizeof(struct super_block)); + INIT_LIST_HEAD(&s->s_dirty); + INIT_LIST_HEAD(&s->s_locked_inodes); + INIT_LIST_HEAD(&s->s_files); + INIT_LIST_HEAD(&s->s_instances); + init_rwsem(&s->s_umount); + sema_init(&s->s_lock, 1); + down_write(&s->s_umount); + s->s_count = S_BIAS; + atomic_set(&s->s_active, 1); + sema_init(&s->s_vfs_rename_sem,1); + sema_init(&s->s_nfsd_free_path_sem,1); + sema_init(&s->s_dquot.dqio_sem, 1); + sema_init(&s->s_dquot.dqoff_sem, 1); + s->s_maxbytes = MAX_NON_LFS; + s->s_op = &empty_sops; + s->dq_op = NULL; + s->s_qcop = NULL; + } + extern int x86_udelay_tsc; cpuspeed = ((int64_t) loops_per_jiffy) * STD_SPD / STD_LOOPS; if (!x86_udelay_tsc) @@ -43,4 +67,5 @@ mosinfo_update_gateways(); kernel_thread(mosix_info_daemon, NULL, 0); kernel_thread(mosix_mem_daemon, NULL, 0); + kernel_thread(mosix_migshm_daemon,NULL,0); } diff -Naur linux-2.4.26-om1/hpc/kernel.c linux-2.4.26-om1-o/hpc/kernel.c --- linux-2.4.26-om1/hpc/kernel.c 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/kernel.c 2006-05-07 17:56:02.000000000 +0530 @@ -555,8 +555,6 @@ m->stay |= DSTAY_SYSTEM; else m->stay &= ~DSTAY_SYSTEM; - m->held_files = NULL; - m->held_allocated = 0; rwlock_init(&m->state_lock); m->contact = 0; m->ucache = NULL; @@ -597,7 +595,7 @@ init_waitqueue_head(mos_to_waitp(m)); m->mosix_log = NULL; m->dirty_bits = 0; - return (fork_mosix_remote_files(p)); + return 0; } void @@ -729,63 +727,6 @@ m->pass_regs = 0; } -void -mosix_bring_monkey_users_back(struct inode *ip) -{ - struct task_struct *p, *found, *me = current; - DECLARE_WAITQUEUE(wait, me); - - while (1) { - found = NULL; - read_lock(&tasklist_lock); - for_each_task(p) - if (p != me && !(p->mosix.dflags & DREMOTE) && - task_maps_ip(p, ip)) { - task_lock(p); - p->mosix.stay |= DSTAY_FOR_MONKEY; - task_unlock(p); - if (p->mosix.dflags & DDEPUTY) { - tell_process(p, DREQ_HOMEWAKE); - wake_up_mosix(p); - if (!found) { - found = p; - get_task_struct(p); - } - } - } - if (!found) { - read_unlock(&tasklist_lock); - /* VMODIFIED is needed against a nearly-impossible - * REMOTE race, when ip is modified, then unmonkied - * and a process migrates there even before the - * previous completed exiting: - */ - OPENMOSIX_VMODIFIED(ip); - return; - } - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(mos_to_waitp(&found->mosix), &wait); - read_unlock(&tasklist_lock); - schedule(); - remove_wait_queue(mos_to_waitp(&found->mosix), &wait); - set_current_state(TASK_RUNNING); - free_task_struct(found); - } -} - -void -mosix_no_longer_monkey(struct inode *ip) -{ - struct task_struct *p; - - read_lock(&tasklist_lock); - for_each_task(p) - if (!(p->mosix.dflags & (DREMOTE | DDEPUTY)) && task_maps_ip(p, ip)) { - tell_process(p, DREQ_CHECKSTAY); - wake_up_mosix(p); - } - read_unlock(&tasklist_lock); -} /* * caller is responsible to down_[read|write](¤t->mm->mmap_sem) @@ -824,8 +765,6 @@ ip = mpnt->vm_file->f_dentry->d_inode; mode = ip->i_mode; - if (ip->i_mapping->i_mmap_shared) - stay |= DSTAY_FOR_MONKEY; if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) stay |= DSTAY_FOR_DEV; @@ -917,8 +856,6 @@ { if ((p->mosix.dflags & (DPASSING | DREMOTE)) == DPASSING) return; - if (p->mosix.held_files) - mosix_clear_all_held_files(p); if (!(p->mosix.dflags & DDEPUTY)) mosix_pre_dropping_mm(p, p->mm); task_lock(p); @@ -940,8 +877,6 @@ p->mosix.stay &= ~(DSTAY_PER_MM | DSTAY_FOR_CLONE); task_unlock(p); p->mosix.pages_i_bring = 0; - if (p->mosix.held_files) - mosix_clear_all_held_files(p); } int diff -Naur linux-2.4.26-om1/hpc/Makefile linux-2.4.26-om1-o/hpc/Makefile --- linux-2.4.26-om1/hpc/Makefile 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/Makefile 2006-05-07 17:56:02.000000000 +0530 @@ -20,7 +20,7 @@ obj-y := alternate.o auto_syscalls.o balance.o comm.o config.o decay.o \ deputy.o div.o export.o freemem.o init.o info.o kernel.o load.o \ mig.o hpcadmin.o hpcproc.o prequest.o remote.o rinode.o \ - service.o syscalls.o ucache.o badops.o + service.o syscalls.o ucache.o badops.o mig_shm.o shm_comm.o shm_filemap.o obj-$(CONFIG_MOSIX_DFSA) += dfsa.o diff -Naur linux-2.4.26-om1/hpc/mig.c linux-2.4.26-om1-o/hpc/mig.c --- linux-2.4.26-om1/hpc/mig.c 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/mig.c 2006-05-07 17:56:02.000000000 +0530 @@ -215,7 +215,9 @@ if (SHOW_MIGRATIONS) printk("Weeeeeeeee.....\n"); #endif /* SHOW_MIGRATIONS */ + kickstart(); + panic("kickstart returned"); /*NOTREACHED*/ failed: if (load_came_in) { @@ -254,7 +256,6 @@ { struct task_struct *p = current; int error; - if (!PE) return (whereto && whereto != GOBACKHOME && whereto != MUSTGOHOME ? -EDIST : 0); @@ -278,7 +279,7 @@ return (0); } #endif /* CONFIG_MOSIX_CHEAT_MIGSELF */ - if (whereto && ((p->mosix.stay & DSTAY) || !mos_to_net(whereto, 0))) + if (whereto && ((p->mosix.stay & DSTAY) || !mos_to_net(whereto, 0))) return (-EDIST); spin_lock_irq(&runqueue_lock); @@ -477,9 +478,6 @@ int error; int omigpages; - if (!p->mosix.held_files && (error = mosix_rebuild_file_list())) - return (error); - lock_mosix(); write_lock_irq(&tasklist_lock); p->mosix.remote_caps = current->cap_effective; @@ -500,7 +498,7 @@ unlock_mosix(); p->mosix.deputy_regs = ALL_REGISTERS; p->mosix.pass_regs = 0; - + if (!(mlink = comm_open(whereto, 0, comm_connect_timo))) { error = -EDIST; goto failed; @@ -591,10 +589,6 @@ #endif /*SHOW_MIGRATIONS */ end_coming_in(0); current->mosix.pages_i_bring = 0; - if (p->mosix.dflags & DDELAYHELD) { - p->mosix.dflags &= ~DDELAYHELD; - mosix_rebuild_file_list(); - } return (0); } @@ -715,8 +709,6 @@ stop_storing_common_ps_info(); flush_read_cache(); free_ucache(); - if (m->stay & DSTAY_FOR_MONKEY) - mosix_check_for_freedom_to_move(); } else { if (m->contact) { comm_close(m->contact); @@ -772,6 +764,7 @@ m.uniq = ip->i_unique; m.isize = ip->i_size; m.nopage = vma->vm_ops->nopage; + } } else { m.fp = NULL; @@ -962,9 +955,9 @@ comm_migration_mode(1); neutralize_my_load(1); /* don't count me: I'm going to disappear */ if (mig_send_mm_stats() || mig_send_mm_areas() || - (credit = mig_send_pages()) < 0 || - (current->used_math && mig_send_fp()) || - (current->mm->context.ldt && mig_send_ldt()) || + (credit = mig_send_pages()) < 0 || + (current->used_math && mig_send_fp()) || + (current->mm->context.ldt && mig_send_ldt()) || mig_send_misc(credit)) { comm_send(MIG_NOT_COMING, NULL, 0, NULL, 0, 0); comm_migration_mode(0); @@ -1000,6 +993,12 @@ /* unconvert prot+flags: */ flags = MAP_FIXED | MAP_PRIVATE; + + if(m->flags & VM_SHARED) { + flags &= ~(MAP_PRIVATE); + flags|=MAP_SHARED; + } + prot = 0; if (m->flags & VM_GROWSDOWN) flags |= MAP_GROWSDOWN; @@ -1481,7 +1480,6 @@ if (to > 0) return (passto(to, 0) ? (mos_to_net(to, NULL) ? -ENETUNREACH : -ENXIO) : 0); - switch (to) { case DM_GOBACKHOME: return (passto(GOBACKHOME, 0) ? -EDIST : 0); diff -Naur linux-2.4.26-om1/hpc/mig_shm.c linux-2.4.26-om1-o/hpc/mig_shm.c --- linux-2.4.26-om1/hpc/mig_shm.c 1970-01-01 05:30:00.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/mig_shm.c 2006-05-08 10:48:35.000000000 +0530 @@ -0,0 +1,744 @@ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/shm.h> +#include <linux/mman.h> +#include <linux/locks.h> +#include <linux/pagemap.h> +#include <linux/swap.h> +#include <linux/smp_lock.h> +#include <linux/blkdev.h> +#include <linux/file.h> +#include <linux/swapctl.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/iobuf.h> +#include<asm/system.h> + +#include <asm/pgalloc.h> +#include <asm/uaccess.h> +#include <asm/mman.h> + +#include <linux/highmem.h> +#include<linux/vmalloc.h> + + +#include<hpc/protocol.h> +#include<hpc/mig_shm.h> +#include<hpc/shm_pagemap.h> +#include <linux/hpc.h> + + + +void invalidate(struct shm_page *shm_page,struct page *page,int write_access) +{ + + pte_t pte; + pte_t *page_table; + unsigned long address; + struct vm_area_struct *vma; + struct mm_struct *mm; + struct address_space *mapping = page->mapping; + struct task_struct *p = current; + int i=1; + + lock_page(page); + + spin_lock(&shm_page->shm_lock); + + if(!(p->mosix.dflags & DDEPUTY) && !(p->mosix.dflags & DREMOTE) && !(shm_page->state & AT_HOME)) { + if(write_access) { + shm_page->state &= ~STATE_MASK; + shm_page->state |= IDLE; + } + else { + shm_page->state &= ~STATE_MASK; + shm_page->state |= SHARED; + } + } + + spin_unlock(&shm_page->shm_lock); + + if((page->mapping == shm_page->mapping) && (page->index == shm_page->index)) { + + spin_lock(&mapping->i_shared_lock); + vma = mapping->i_mmap_shared; + + while(vma) { + if(page->index >= vma->vm_pgoff) { + address = ((page->index - vma->vm_pgoff) << PAGE_CACHE_SHIFT) + vma->vm_start; + if(address < vma->vm_end ) { + mm = vma->vm_mm; + spin_lock(&mm->page_table_lock); + page_table = pte_offset(pmd_offset(pgd_offset(mm,address),address),address); + if(pte_present(*page_table) && (i || !pte_write(*page_table))) { + flush_cache_page(vma, address); + pte = ptep_get_and_clear(page_table); + flush_tlb_page(vma, address); + + if(!write_access) + set_pte(page_table,pte_wrprotect(pte)); + else { + mm->rss--; + page_cache_release(page); + } + + if (pte_dirty(pte)) + set_page_dirty(page); + } + spin_unlock(&mm->page_table_lock); + } + } + vma = vma->vm_next_share; + if(!vma && i--) + vma = mapping->i_mmap; + } + + spin_unlock(&mapping->i_shared_lock); + } +/* + * else + * + * printk("{trancated:%u %u}",page->mapping,page->index); + */ + + + if(write_access && !(p->mosix.dflags & DREMOTE) && !(p->mosix.dflags & DDEPUTY) && !(shm_page->state & AT_HOME)) { + page->shm_page = NULL; + shm_pagecache_release(shm_page); + + ClearPageUptodate(page); + ClearPageDirty(page); + } + + unlock_page(page); + return; +} + + +static int send_upgrade(struct shm_page *shm_page,struct page *page) +{ + int res = 1; + + lock_page(page); + + if((shm_page->state & STATE_MASK) == SHARED) { + res = remote_upgrade(shm_page); + if(!res) { + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~SHARED; + shm_page->owner = PE; + shm_page->state |= EXCLUSIVE; + spin_unlock(&shm_page->shm_lock); + } else if(res == 2) { + shm_page->state |= PERM_ERR; + printk(KERN_ERR "A shared page here is invalid: Reboot !\n"); + } + } else if((shm_page->state & STATE_MASK) == EXCLUSIVE && ((shm_page->owner == PE) || (shm_page->owner == 0))) + res = 0; + + unlock_page(page); + return res; +} + +static struct page *get_exc_rem(struct vm_area_struct *vma,unsigned long address,struct shm_page *shm_page) +{ + struct page *page; + int res = 0; + + page = vma->vm_ops->nopage(vma,address,WITH_WRITE_ACC); + + if(!page || (page == NOPAGE_OOM) || page == PAGE_BUSY) + return page; + + spin_lock(&shm_page->shm_lock); + + if(!(res = ((shm_page->state & STATE_MASK) == IDLE)) && ((shm_page->state & STATE_MASK) == SHARED)) { + spin_unlock(&shm_page->shm_lock); + res = send_upgrade(shm_page,page); + goto out; + } + + spin_unlock(&shm_page->shm_lock); + +out: if(!res) + return page; + else { + page_cache_release(page); + if(res == 1) + return PAGE_BUSY; + else + return NULL; + } +} + + +static struct page *get_page_exc_in_exc(struct vm_area_struct *vma, unsigned long address,struct shm_page *shm_page) +{ + struct page *page = NULL; + + switch(current->mosix.dflags & (DDEPUTY|DREMOTE)) { + + case DREMOTE : + + spin_unlock(&shm_page->shm_lock); + page = get_exc_rem(vma,address,shm_page); + + break; + + case DDEPUTY: + + if(!vma) goto AS_HERE; + + shm_page->state &= ~EXCLUSIVE; + shm_page->state |= BUSY_EXCLUSIVE; + spin_unlock(&shm_page->shm_lock); + + if(!PE || (shm_page->owner == 0) || (shm_page->owner == PE)) { + page = vma->vm_ops->nopage(vma,address,0); + if((page == NOPAGE_OOM )|| !page) { + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~BUSY_EXCLUSIVE; + shm_page->state |= EXCLUSIVE; + spin_unlock(&shm_page->shm_lock); + return page; + } + invalidate(shm_page,page,1); + shm_pagecache_get(shm_page); + } else { + page = find_or_create_page(shm_page->mapping,shm_page->index,GFP_NOFS); + + if(shm_send_message(shm_page->owner,shm_page,page,FORWARD_REQUEST_WRITE)) + goto here; + + SetPageUptodate(page); + set_page_dirty(page); + unlock_page(page); + } + + vma->vm_end = 0; + vma->vm_start = 0; + + break; + + AS_HERE: + default: + if(!PE || (shm_page->owner == 0) || (shm_page->owner == PE)) { + spin_unlock(&shm_page->shm_lock); + if(vma) + page = vma->vm_ops->nopage(vma, address,0); + } else { + + shm_page->state &= ~EXCLUSIVE; + shm_page->state |= BUSY_EXCLUSIVE; + + spin_unlock(&shm_page->shm_lock); + + page = find_or_create_page(shm_page->mapping, + shm_page->index,GFP_NOFS); + + shm_page->next = shm_page->prev = PE; + shm_page->next_addr = shm_page->prev_addr = shm_page; + + + if(shm_send_message(shm_page->owner,shm_page,page,FORWARD_REQUEST_WRITE)) { + here : unlock_page(page); + page_cache_release(page); + printk(KERN_ERR "Data Loss : What happened to node %d ,Reboot this node\n",shm_page->owner); + spin_lock(&shm_page->shm_lock); + shm_page->owner = PE; + shm_page->state &= ~BUSY_EXCLUSIVE; + shm_page->state |= (EXCLUSIVE|PERM_ERR); + spin_unlock(&shm_page->shm_lock); + shm_pagecache_release(shm_page); + return NULL; + } + + SetPageUptodate(page); + set_page_dirty(page); + unlock_page(page); + + shm_page->owner = PE; + + spin_lock(&shm_page->shm_lock); + shm_page->state |= EXCLUSIVE; + shm_page->state &= ~BUSY_EXCLUSIVE; + spin_unlock(&shm_page->shm_lock); + + shm_pagecache_release(shm_page); + } + } + return page; +} + +static struct page *get_page_exc_in_shared(struct vm_area_struct *vma, unsigned long address,struct shm_page *shm_page) +{ + struct page *page = NULL; + + switch(current->mosix.dflags & (DDEPUTY|DREMOTE)) { + + case DREMOTE : + + spin_unlock(&shm_page->shm_lock); + page = get_exc_rem(vma,address,shm_page); + + break; + + case DDEPUTY: + + if(!vma) goto AS_HERE; + + if(shm_page->state & DROPPING) { + page = PAGE_BUSY; + spin_unlock(&shm_page->shm_lock); + } else { + shm_page->state &= ~SHARED; + shm_page->state |= BUSY_EXCLUSIVE; + + spin_unlock(&shm_page->shm_lock); + + + page = vma->vm_ops->nopage(vma,address,0); + + if((page == NOPAGE_OOM) || !page) { + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~BUSY_EXCLUSIVE; + shm_page->state |= SHARED; + spin_unlock(&shm_page->shm_lock); + return page; + } + + invalidate(shm_page,page,1); + + + vma->vm_start = 0; + vma->vm_end = 0; + + if(PE && (shm_page->prev != PE) && (shm_page->prev != 0)) { + vma->vm_end = shm_page->next; + vma->vm_start = (unsigned long)shm_page->next_addr; + shm_page->next = current->mosix.whereami; + shm_page->next_addr = (struct shm_page *)vma->vm_flags; + if(shm_send_message(shm_page->prev,shm_page,page,DROP_NEXT)) { + printk("reader loop broken because of %d ! reboot all",shm_page->prev); + shm_page->state |= UPGRADE_ERR; + } + } + } + + break; + + AS_HERE: + default: + if(shm_page->state & DROPPING) { + spin_unlock(&shm_page->shm_lock); + page = PAGE_BUSY; + } else { + shm_page->owner = PE; + shm_page->state |= DROPPING; + spin_unlock(&shm_page->shm_lock); + + if(vma) + page = vma->vm_ops->nopage(vma,address,0); + + if(PE && (shm_page->next != PE) && (shm_page->next != 0)) + if(shm_send_message(shm_page->next,shm_page,page,INVALIDATE)) + shm_page->state |= UPGRADE_ERR; + + shm_page->next = shm_page->prev = PE; + shm_page->next_addr = shm_page->prev_addr = shm_page; + + spin_lock(&shm_page->shm_lock); + + shm_page->state &= ~SHARED; + shm_page->state |= EXCLUSIVE; + shm_page->state &= ~DROPPING; + + spin_unlock(&shm_page->shm_lock); + + shm_pagecache_release(shm_page); + } + + break; + + } + return page; +} + +static struct page *get_page_shared_in_exc(struct vm_area_struct *vma, unsigned long address,struct shm_page *shm_page) +{ + struct page *page = PAGE_BUSY; + + switch(current->mosix.dflags & (DDEPUTY|DREMOTE)) { + case DREMOTE: + + spin_unlock(&shm_page->shm_lock); + page = vma->vm_ops->nopage(vma,address,WITH_READ_ACC); + break; + + case DDEPUTY: + + if(!vma) goto AS_HERE; + + shm_page->prev = shm_page->next = current->mosix.whereami; + shm_page->prev_addr = shm_page->next_addr = (struct shm_page *)vma->vm_flags; + + if(!PE || (shm_page->owner == 0) || (shm_page->owner == PE)) { + shm_page->state &= ~EXCLUSIVE; + shm_page->state |= (SHARED|DROPPING); + spin_unlock(&shm_page->shm_lock); + + page = vma->vm_ops->nopage(vma,address,0); + if((page == NOPAGE_OOM) || (!page)) { + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~(SHARED|DROPPING); + shm_page->state |= EXCLUSIVE; + spin_unlock(&shm_page->shm_lock); + return page; + } + + vma->vm_end = PE; + vma->vm_start =(unsigned long) shm_page; + + invalidate(shm_page,page,0); + shm_pagecache_get(shm_page); + } else { + shm_page->state &= ~EXCLUSIVE; + shm_page->state |= BUSY_SHARED; + spin_unlock(&shm_page->shm_lock); + + vma->vm_end = shm_page->owner; + vma->vm_start = (unsigned long)shm_page->rem_shm_page_addr; + + shm_page->next = shm_page->owner; + shm_page->next_addr = shm_page->rem_shm_page_addr; + + page = find_or_create_page(shm_page->mapping,shm_page->index,GFP_NOFS); + + if(shm_send_message(shm_page->owner, shm_page,page, FORWARD_REQUEST_READ)) + goto here; + + SetPageUptodate(page); + set_page_dirty(page); + unlock_page(page); + + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~ BUSY_SHARED; + shm_page->state |= (SHARED|DROPPING); + spin_unlock(&shm_page->shm_lock); + } + + break; + + AS_HERE: + default: + + if(!PE || (shm_page->owner == 0) || (shm_page->owner == PE)) { + spin_unlock(&shm_page->shm_lock); + if(vma) + page = vma->vm_ops->nopage(vma,address,0); + } else { + shm_page->state &= ~EXCLUSIVE; + shm_page->state |= BUSY_SHARED; + spin_unlock(&shm_page->shm_lock); + + shm_page->prev = shm_page->next = shm_page->owner; + shm_page->prev_addr = shm_page->next_addr = shm_page->rem_shm_page_addr; + + page = find_or_create_page(shm_page->mapping,shm_page->index,GFP_NOFS); + + if(shm_send_message(shm_page->owner,shm_page,page,FORWARD_REQUEST_READ)) { + here: unlock_page(page); + page_cache_release(page); + printk(KERN_INFO "Data Loss : What happened to node %d ? Reboot this node\n",shm_page->owner); + shm_page->owner = PE; + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~BUSY_SHARED; + shm_page->state |= (EXCLUSIVE|PERM_ERR); + spin_unlock(&shm_page->shm_lock); + shm_pagecache_release(shm_page); + return NULL; + } + + SetPageUptodate(page); + set_page_dirty(page); + unlock_page(page); + + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~BUSY_SHARED; + shm_page->state |= SHARED; + spin_unlock(&shm_page->shm_lock); + } + + break; + } + return page; +} + +static struct page *get_page_shared_in_shared(struct vm_area_struct *vma, unsigned long address,struct shm_page *shm_page) +{ + struct page *page = PAGE_BUSY; + struct task_struct *p = current; + + if(p->mosix.dflags & DDEPUTY) { + + if(shm_page->state & DROPPING) { + spin_unlock(&shm_page->shm_lock); + return(page); + } + + shm_page->state |= DROPPING; + spin_unlock(&shm_page->shm_lock); + + page = vma->vm_ops->nopage(vma,address,0); + if((page == NOPAGE_OOM) || !page) { + shm_page->state &= ~DROPPING; + return page; + } + if(PE && (shm_page->prev != PE) && (shm_page->prev != 0)) { + + vma->vm_end = shm_page->next; + vma->vm_start = (unsigned long)shm_page->next_addr; + + shm_page->next = p->mosix.whereami; + shm_page->next_addr = (struct shm_page *)vma->vm_flags; + + if(shm_send_message(shm_page->prev,shm_page,NULL,DROP_NEXT)) { + printk(KERN_ERR "node %d down:reader loop broken,reboot all !\n",shm_page->prev); + shm_page->next = vma->vm_end; + shm_page->next_addr = (struct shm_page *)vma->vm_start; + + shm_send_message(shm_page->next,shm_page,NULL,INVALIDATE); + + shm_page->owner = shm_page->next = shm_page->prev =PE; + shm_page->next_addr = shm_page->prev_addr = shm_page; + + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~(DROPPING|SHARED); + shm_page->state |= (EXCLUSIVE|UPGRADE_ERR); + spin_unlock(&shm_page->shm_lock); + + page_cache_release(page); + shm_pagecache_release(shm_page); + return NULL; + } + + shm_page->next = vma->vm_end; + shm_page->next_addr = (struct shm_page *) vma->vm_start; + + vma->vm_start = (unsigned long)shm_page->prev_addr; + vma->vm_end = shm_page->prev; + + } else { + vma->vm_start = (unsigned long)shm_page; + vma->vm_end = PE; + shm_page->next_addr = (struct shm_page *)vma->vm_flags; + shm_page->next = p->mosix.whereami; + } + + shm_page->prev = current->mosix.whereami; + shm_page->prev_addr = (struct shm_page *)vma->vm_flags; + + } else { + + spin_unlock(&shm_page->shm_lock); + page = vma->vm_ops->nopage(vma,address,(p->mosix.dflags & DREMOTE) ? WITH_READ_ACC:0); + + } + return page; +} + + + + +static struct page *send_page_exclusive(struct vm_area_struct *vma, unsigned long address, + struct shm_page *shm_page,int write_access) +{ + struct page *page = PAGE_BUSY; + + spin_lock(&shm_page->shm_lock); + + if((current->mosix.dflags & DDEPUTY) && (shm_page->writers || shm_page->readers)) { + spin_unlock(&shm_page->shm_lock); + goto out; + } + + switch(shm_page->state & STATE_MASK) { + + case EXCLUSIVE: + case IDLE: + if((write_access == 11) && (!PE || ((shm_page->state & STATE_MASK) == EXCLUSIVE))) { + spin_unlock(&shm_page->shm_lock); + return NULL; + } + + page = get_page_exc_in_exc(vma, address, shm_page); + + break; + + case SHARED: + page = get_page_exc_in_shared(vma, address, shm_page); + break; + default: + spin_unlock(&shm_page->shm_lock); + break; + } + +out: + return page; +} + +static struct page *send_page_shared(struct vm_area_struct *vma,unsigned long address,struct shm_page *shm_page) +{ + struct page *page = PAGE_BUSY; + + spin_lock(&shm_page->shm_lock); + if((current->mosix.dflags & DDEPUTY) && ((shm_page->writers) || (shm_page->state & UPGRADE_ERR)) ) { + if(shm_page->state & UPGRADE_ERR) + page = NULL; + spin_unlock(&shm_page->shm_lock); + goto out; + } + + switch(shm_page->state & STATE_MASK) { + + case EXCLUSIVE: + case IDLE: + + page = get_page_shared_in_exc(vma,address,shm_page); + + break; + case SHARED: + page = get_page_shared_in_shared(vma,address,shm_page); + break; + default: + spin_unlock(&shm_page->shm_lock); + break; + } + +out: + return page; +} + +void wait_here() +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(5*HZ); +} + +struct page *get_nopage(struct vm_area_struct *vma, unsigned long address,struct shm_page **shm_page,int write_access) +{ + struct page *new_page = NULL; + struct task_struct *p = current; + struct address_space *mapping = vma->vm_file->f_dentry->d_inode->i_mapping; + unsigned long index = ((address - vma->vm_start) >> PAGE_CACHE_SHIFT) + vma->vm_pgoff; + + *shm_page = find_or_create_shm_page(mapping,index); + if((*shm_page)->state & PERM_ERR) + goto out; + + while(1) { + if((write_access == 1) || (write_access == 11)) + new_page=send_page_exclusive(vma, address & PAGE_MASK, *shm_page, write_access); + else if(write_access == 0 || write_access == 2) + new_page=send_page_shared(vma, address & PAGE_MASK, *shm_page); + + if((new_page != PAGE_BUSY) || (p->mosix.dflags & DDEPUTY)) + break; + else + wait_here(); + } + +out: if((new_page == NULL || new_page == NOPAGE_OOM || new_page == PAGE_BUSY || (write_access == 2)) && write_access != 11) { + shm_pagecache_release(*shm_page); + *shm_page = NULL; + } + + return new_page; +} + +int +get_pages(struct address_space *mapping,loff_t offset,size_t count,int writer) +{ + struct shm_page *shm_page; + struct page *page=NULL; + unsigned long index = (offset >> PAGE_CACHE_SHIFT), + end = ((offset+count) >> PAGE_CACHE_SHIFT); + + for(;index <= end; index++) { + + shm_page = find_or_create_shm_page(mapping,index); + + if(shm_page->state & PERM_ERR) + return (index + 1); + + spin_lock(&shm_page->shm_lock); + + if(writer) + shm_page->writers++; + else + shm_page->readers++; + + + again: switch(shm_page->state & STATE_MASK) { + case EXCLUSIVE: + if(PE && (shm_page->owner != PE) && (shm_page->owner != 0)) { + if(writer) { + if(shm_page->readers) { + page = PAGE_BUSY; + spin_unlock(&shm_page->shm_lock); + } + else + page = get_page_exc_in_exc(NULL,0,shm_page); + } else + page = get_page_shared_in_exc(NULL,0,shm_page); + + if(page == PAGE_BUSY) + goto here; + else if (page) + page_cache_release(page); + } else + spin_unlock(&shm_page->shm_lock); + break; + + case SHARED: + if(!writer) { + spin_unlock(&shm_page->shm_lock); + break; + } else if(!get_page_exc_in_shared(NULL,0,shm_page)) { + break; + } else + goto here; + default: + spin_unlock(&shm_page->shm_lock); + here: wait_here(); + spin_lock(&shm_page->shm_lock); + goto again; + } + } + return 0; +} +void +put_pages(struct address_space *mapping,loff_t offset,size_t count,int writer,unsigned long end) +{ + + struct shm_page *shm_page; + unsigned long index = (offset >> PAGE_CACHE_SHIFT); + + if(!end--) + end = ((offset+count) >> PAGE_CACHE_SHIFT); + + for(;index <= end; index++) { + shm_page = find_get_shm_page(mapping,index,shm_page_hash(mapping,index)); + + spin_lock(&shm_page->shm_lock); + if(writer) + shm_page->writers--; + else + shm_page->readers--; + spin_unlock(&shm_page->shm_lock); + + shm_pagecache_release(shm_page); + shm_pagecache_release(shm_page); + } +} + diff -Naur linux-2.4.26-om1/hpc/remote.c linux-2.4.26-om1-o/hpc/remote.c --- linux-2.4.26-om1/hpc/remote.c 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/remote.c 2006-05-07 17:56:02.000000000 +0530 @@ -31,6 +31,8 @@ #include <linux/file.h> #include <hpc/balance.h> #include <hpc/dfsa.h> +#include <hpc/mig_shm.h> +#include <hpc/shm_pagemap.h> int remote_wait(int expect, void **head, int *hlen) @@ -109,10 +111,6 @@ remote_mprotect((struct mprotect_parameters_h *) *head); break; - case DEP_LISTHOLD: - comm_free(*head); - error = remote_report_files(); - break; case DEP_SETUPFRAME: error = remote_setup_frame((struct setupframe_parameters_h @@ -471,22 +469,93 @@ bump_syscalls(); /* no accurate numbers, but it costs! */ wait_for_permission_to_continue(); } +int +remote_writepage(struct page *page) +{ + struct shm_page *shm_page; + int res; + shm_page = page->shm_page; + + struct address_space *mapping = page->mapping; + unsigned long index = page->index; + +retry: if((shm_page->state & STATE_MASK) == IDLE) + goto out; + + if((shm_page->state & STATE_MASK) == EXCLUSIVE) + res = shm_send_message(page->mapping->host->u.remote_i.origin,shm_page,page,WRITE_ BACK); + else + res = shm_send_message(page->mapping->host->u.remote_i.origin,shm_page,page,DROP_P AGE); + + if(res == 1) { + SetPageDirty(page); + unlock_page(page); + wait_here(); + lock_page(page); + if(mapping != page->mapping || index != page->index) + goto out; + + goto retry; + } else { + ClearPageDirty(page); + if(res) + printk(KERN_ERR "Comm loss: Reboot this and %d %d nodes !\n",shm_page->next,shm_page->prev); + + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~STATE_MASK; + shm_page->state |= IDLE; + spin_unlock(&shm_page->shm_lock); + + page->shm_page = NULL; + shm_pagecache_release(shm_page); + } + +out: unlock_page(page); + return(0); +} + +int +remote_upgrade(struct shm_page *shm_page) +{ + struct upgrade_h u; + struct shm_page_ret_h r; + + u.rem_shm_page_addr = shm_page->rem_shm_page_addr; + u.shm_page = shm_page; + int error; + + if (!(error = remote_request(REM_UPGRADE, &u, sizeof (u), NULL, 0, 0, + (void **) &r, -sizeof (r)))) { + if((!(r.ret)) && (shm_page->prev != 0) && (shm_page->prev != PE)) + shm_send_message(shm_page->next,shm_page,NULL,INVALIDATE); + error = r.ret; + } + + absorb_deptime(r.deputytime); + return error; +} + int remote_readpage(struct file *fp, struct page *page) { - int error; + int error=0; char *buffer = kmap(page); struct bring_page_h b; - struct page_ret_h r; + struct shm_page_ret_h r; int dpagein = (current->mosix.dflags & DPAGEIN) ^ DPAGEIN; struct task_struct *p = current; - + struct shm_page *shm_page = page->shm_page; + if (!PageLocked(page)) PAGE_BUG(page); + b.fp = home_file(fp); - b.offset = page->index << PAGE_CACHE_SHIFT; + b.offset = (page->index << PAGE_CACHE_SHIFT); b.nopage = fp->f_dentry->d_inode->u.remote_i.nopage; + b.rem_shm_page_addr = shm_page; + b.access = (shm_page->state & ACC_MASK); + if (p->mosix.rfreepages > 0) p->mosix.rfreepages--; else @@ -498,28 +567,65 @@ p->mosix.dflags |= dpagein; spin_unlock_irq(&runqueue_lock); } - if (!b.nopage) /* home rebooted, we should be dead anyway */ - error = -EIO; + + if (!b.nopage) /* home rebooted, we should be dead anyway */ + error = -EIO; else if (!(error = remote_request(REM_PAGE, &b, sizeof (b), NULL, 0, 0, - (void **) &r, -sizeof (r)))) + (void **) &r, -sizeof (r)))) error = r.ret; - if (!error) + + if (!error) error = comm_copydata(buffer, PAGE_SIZE, 0); - else if (error == -EFBIG) { - memset(buffer, 0, PAGE_SIZE); - error = 0; - } - if (error) { + + if(!error) { + + spin_lock(&shm_page->shm_lock); + + shm_page->owner = PE; + + shm_page->state &= ~STATE_MASK; + shm_page->state |= ((b.access & WITH_WRITE_ACC) ? EXCLUSIVE : SHARED); + + spin_unlock(&shm_page->shm_lock); + + shm_page->rem_shm_page_addr = r.rem_shm_page_addr; + + shm_page->next = r.next; + shm_page->next_addr = r.next_addr; + + if(b.access & WITH_WRITE_ACC) { + if(r.next_addr) + if(shm_send_message(shm_page->next,shm_page,page,INVALIDATE)) + printk(KERN_ERR "REBOOT ALL\n"); + shm_page->next_addr = shm_page->prev_addr = shm_page; + shm_page->next = shm_page->prev = PE; + + } else { + shm_page->prev = r.prev; + shm_page->prev_addr = r.prev_addr; + shm_send_message(current->mosix.deppe,shm_page,NULL,DROP_PAGE_END); + } + + SetPageUptodate(page); + set_page_dirty(page); + } else { + ClearPageUptodate(page); - SetPageError(page); - } else - SetPageUptodate(page); + ClearPageDirty(page); + SetPageError(page); + page->shm_page = NULL; + shm_pagecache_release(shm_page); + } + + shm_page->state &= ~ACC_MASK; + UnlockPage(page); kunmap(page); spin_lock_irq(&runqueue_lock); p->mosix.dflags &= ~dpagein; spin_unlock_irq(&runqueue_lock); absorb_deptime(r.deputytime); + return (error); } @@ -658,28 +764,34 @@ } } else rf = NULL; - /* unconvert prot+flags: */ - prot = 0; - flags = MAP_PRIVATE; - if (m->fixed) - flags |= MAP_FIXED; - if (m->flags & VM_GROWSDOWN) - flags |= MAP_GROWSDOWN; - if (m->flags & VM_DENYWRITE) - flags |= MAP_DENYWRITE; - if (m->flags & VM_EXECUTABLE) - flags |= MAP_EXECUTABLE; - if (m->flags & VM_READ) - prot |= VM_READ; - if (m->flags & VM_WRITE) - prot |= VM_WRITE; - if (m->flags & VM_EXEC) - prot |= VM_EXEC; + prot = 0; + flags = MAP_PRIVATE; + if(m->flags & VM_SHARED) { + flags &= ~(MAP_PRIVATE); + flags|=MAP_SHARED; + } + if (m->fixed) + flags |= MAP_FIXED; + if (m->flags & VM_GROWSDOWN) + flags |= MAP_GROWSDOWN; + if (m->flags & VM_DENYWRITE) + flags |= MAP_DENYWRITE; + if (m->flags & VM_EXECUTABLE) + flags |= MAP_EXECUTABLE; + if (m->flags & VM_READ) + prot |= PROT_READ; + if (m->flags & VM_WRITE) + prot |= PROT_WRITE; + if (m->flags & VM_EXEC) + prot |= PROT_EXEC; + if (m->flags & VM_MAYSHARE) current->mosix.dirty_bits |= MMAP_MAYSHARE; + result = do_mmap_pgoff(rf, m->addr, m->len, prot, flags, m->pgoff); + if (m->flags & VM_MAYSHARE) - current->mosix.dirty_bits &= ~MMAP_MAYSHARE; + current->mosix.dirty_bits &= ~MMAP_MAYSHARE; if (rf && !IS_ERR((const void *) result)) { int pages = (m->len + PAGE_SIZE - 1) / PAGE_SIZE; @@ -688,8 +800,9 @@ current->mosix.rfreepages += pages; } if (m->flags & VM_READHINTMASK) - sys_madvise(m->addr, m->len, (m->flags & VM_SEQ_READ) ? - MADV_RANDOM : MADV_SEQUENTIAL); + sys_madvise(m->addr, m->len, (m->flags & VM_SEQ_READ) ? + MADV_RANDOM : MADV_SEQUENTIAL); + err: if (rf) fput(rf); diff -Naur linux-2.4.26-om1/hpc/rinode.c linux-2.4.26-om1-o/hpc/rinode.c --- linux-2.4.26-om1/hpc/rinode.c 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/rinode.c 2006-05-07 17:56:02.000000000 +0530 @@ -10,14 +10,16 @@ #include <hpc/protocol.h> #include <hpc/comm.h> #include <linux/hpc.h> +#include <linux/locks.h> #include <linux/smp_lock.h> #include <linux/file.h> #include <linux/dcache.h> #include <linux/slab.h> #include <hpc/routines.h> #include <hpc/debug.h> - +#include <hpc/mig_shm.h> /* REMOTE section: */ +//extern int remote_writepage(struct file*,struct page*); spinlock_t rinode_list_lock = SPIN_LOCK_UNLOCKED; @@ -33,7 +35,6 @@ static struct dentry_operations remote_dentry_ops = { .d_delete = remote_dentry_delete, - .d_iput = remote_dentry_iput }; static struct file_operations remote_file_operations = { @@ -41,19 +42,21 @@ }; struct address_space_operations remote_aops = { + .writepage = remote_writepage, .readpage = remote_readpage, }; -void -invalidate_old_remote_pages(struct inode *ip) + +static +struct inode *hpc_new_inode(struct super_block *sb) { - down(&ip->i_sem); - /* we prefer "invalidate_inode_pages", - but it does not work on locked pages */ - truncate_inode_pages(ip->i_mapping, 0); - up(&ip->i_sem); + struct inode *inode = new_inode(sb); + if(inode) + insert_inode_hash(inode); + return (inode); } + struct file * get_remote_file(int origin, struct file *fpr, struct dentry *dpr, uint64_t uniq, off_t isize, nopage_t nopage) @@ -80,6 +83,7 @@ } if (!(f = get_empty_filp())) return (NULL); + spin_lock(&dcache_lock); spin_lock(&rinode_list_lock); for (d = rinode_list; d; d = next_entry(d)) { @@ -99,23 +103,29 @@ spin_unlock(&dcache_lock); if (to_iput) iput(to_iput); + if (to_dput) dput(to_dput); - if (cng) - invalidate_old_remote_pages(ip); + f->f_dentry = d; f->f_op = &remote_file_operations; - f->f_mode = FMODE_READ; + f->f_mode = FMODE_READ|FMODE_WRITE; home_file(f) = fpr; + + shm_send_message(current->mosix.deppe,(struct shm_page *)fpr,NULL,GET_FILE); + return (f); } } spin_unlock(&rinode_list_lock); spin_unlock(&dcache_lock); - if (!(ip = new_inode(&bad_super_block))) { + + if (!(ip = hpc_new_inode(&bad_super_block))) { put_filp(f); return (NULL); } + + ip->i_mode = S_IFREG; ip->u.remote_i.origin = origin; ip->u.remote_i.dp = dpr; @@ -124,8 +134,9 @@ ip->i_size = isize; ip->i_fop = &remote_file_operations; ip->i_mapping->a_ops = &remote_aops; - if (!(d = d_alloc(NULL, &(const struct qstr) { - "/", 1, 0}))) { + if (!(d = d_alloc(NULL, &(const struct qstr) { + "/", 1, 0 } ))) { + put_filp(f); iput(ip); return (NULL); @@ -150,10 +161,11 @@ rinode_list = d; f->f_dentry = d; f->f_op = &remote_file_operations; - f->f_mode = 1; + f->f_mode = FMODE_READ|FMODE_WRITE; home_file(f) = fpr; spin_unlock(&rinode_list_lock); spin_unlock(&dcache_lock); + shm_send_message(current->mosix.deppe,(struct shm_page *)fpr,NULL,GET_FILE); return (f); } @@ -179,14 +191,7 @@ spin_unlock(&rinode_list_lock); return (1); } - -static void -remote_dentry_iput(struct dentry *dp, struct inode *ip) -{ - invalidate_old_remote_pages(ip); - iput(ip); -} - + struct vm_operations_struct rinode_mmap = { .nopage = filemap_nopage, }; @@ -194,393 +199,6 @@ static int mosix_remote_file_mmap(struct file *file, struct vm_area_struct *vma) { - if (vma->vm_flags & VM_SHARED) - panic("REMOTE VM_SHARED mmap"); vma->vm_ops = &rinode_mmap; return (0); } - -int -remote_report_files(void) -{ - struct vm_area_struct *vma, *vmb; - struct mm_struct *mm = current->mm; - struct file **fp = NULL; - int n = 0; - int result; - - down_read(&mm->mmap_sem); - for (vma = mm->mmap; vma; vma = vma->vm_next) - if (vma->vm_file) { - for (vmb = mm->mmap; vmb != vma; vmb = vmb->vm_next) - if (vmb->vm_file == vma->vm_file) - break; - if (vmb == vma) - n++; - } - up_read(&mm->mmap_sem); - if (n && !(fp = kmalloc(n * sizeof (struct file *), GFP_KERNEL))) - n = -EAGAIN; - else { - down_read(&mm->mmap_sem); - for (n = 0, vma = mm->mmap; vma; vma = vma->vm_next) - if (vma->vm_file) { - for (vmb = mm->mmap; vmb != vma; - vmb = vmb->vm_next) - if (vmb->vm_file == vma->vm_file) - break; - if (vmb == vma) - fp[n++] = home_file(vma->vm_file); - } - up_read(&mm->mmap_sem); - } - result = comm_send(DEP_LISTHOLD | REPLY, &n, sizeof (int), - fp, n > 0 ? n * sizeof (struct file *) : 0, 0); - if (n > 0) - kfree(fp); - return (result); -} - -void -rinode_flush_files(int pe) -{ - struct dentry *dp; - struct inode *ip; - - loop: - spin_lock(&rinode_list_lock); - for (dp = rinode_list; dp; dp = next_entry(dp)) { - ip = dp->d_inode; - if (ip->u.remote_i.origin == pe && ip->u.remote_i.nopage) { - ip->u.remote_i.dp = NULL; - /* (the pointer is no good and any process - * still using this inode is doomed anyway) */ - ip->u.remote_i.unique = 0xffffffffffffffffULL; - ip->u.remote_i.nopage = NULL; - spin_unlock(&rinode_list_lock); - invalidate_old_remote_pages(ip); - goto loop; - } - } - spin_unlock(&rinode_list_lock); -} - -/* DEPUTY section: */ - -#define DEFAULT_ALLOCATION 10 - -#define ALLOCATED_NEW 1 -#define ALLOCATED_NEW_AND_DENY 2 -#define ADDED_A_DENY 3 -#define FOUND_OLD 4 - -int -mosix_register_a_file(struct file *fp, int denywrite) -{ - struct task_struct *p = current; - int i, new; - struct held_files *nh, *oh; - struct mm_struct *mm; - - if (!p->mosix.held_allocated) { - if ((mm = p->mm) && atomic_read(&mm->mm_realusers) > 1) - return (0); - nh = NULL; /* COMPILER BUG -- hope it is optimized out */ - for (i = DEFAULT_ALLOCATION; i > 0; i >>= 1) - if ((nh = (struct held_files *) - kmalloc(i * sizeof (struct held_files), - GFP_KERNEL))) - break; - if (!nh) - return (-ENOMEM); - memset(nh, 0, i * sizeof (struct held_files)); - task_lock(p); - p->mosix.held_files = nh; - p->mosix.held_allocated = i; - task_unlock(p); - new = 0; - } else { - new = -1; - for (i = 0; i < p->mosix.held_allocated; i++) - if ((struct file *) p->mosix.held_files[i].f == fp) { - if (!denywrite - || p->mosix.held_files[i].denywrite) - return (FOUND_OLD); - if (deny_write_access(fp)) - return (-ETXTBSY); - p->mosix.held_files[i].denywrite = 1; - return (ADDED_A_DENY); - } else if (new == -1 && !p->mosix.held_files[i].f) - new = i; - if (new == -1) { - nh = NULL; /* COMPILER BUG -- hope it is optimized out */ - for (i = DEFAULT_ALLOCATION; i > 0; i >>= 1) - if ((nh = - kmalloc((i + - p->mosix.held_allocated) * - sizeof (struct held_files), - GFP_KERNEL))) - break; - if (!i) - return (-ENOMEM); - for (new = p->mosix.held_allocated + i - 1; - new >= p->mosix.held_allocated; new--) - nh[new].f = NULL; - for (new = 0; new < p->mosix.held_allocated; new++) - nh[new] = p->mosix.held_files[new]; - oh = p->mosix.held_files; - task_lock(p); - p->mosix.held_files = nh; - p->mosix.held_allocated += i; - task_unlock(p); - kfree(oh); - } - } - get_file(fp); - task_lock(p); - p->mosix.held_files[new].f = fp; - task_unlock(p); - if ((p->mosix.held_files[new].denywrite = denywrite)) { - if (deny_write_access(fp)) { - task_lock(p); - p->mosix.held_files[new].f = NULL; - task_unlock(p); - return (-ETXTBSY); - } - return (ALLOCATED_NEW_AND_DENY); - } else - return (ALLOCATED_NEW); -} - -void -mosix_undo_last_file_registration(struct file *fp, int result) -{ - unsigned int i; - struct mosix_task *m = ¤t->mosix; - - if (result == FOUND_OLD) - return; - for (i = 0; i < m->held_allocated; i++) - if ((struct file *) m->held_files[i].f == fp) { - switch (result) { - case ADDED_A_DENY: - case ALLOCATED_NEW_AND_DENY: - if (!m->held_files[i].denywrite) - printk - ("%s: mosix_undo_last_file_registration - no denywrite\n", - desc_mostask(m)); - else - allow_write_access(fp); - if (result == ADDED_A_DENY) - break; - case ALLOCATED_NEW: - fput(fp); - task_lock(current); - m->held_files[i].f = NULL; - task_unlock(current); - break; - } - return; - } - printk("%s: mosix_undo_last_file_registration - not found\n", - desc_mostask(m)); -} - -void -mosix_update_remote_files(void) -{ - struct task_struct *p = current; - struct held_files *h = p->mosix.held_files; - unsigned int i, j; - int op, np; - struct file **rf; - struct file *fp; - - if (!(op = p->mosix.held_allocated)) - return; - if (deputy_request(DEP_LISTHOLD, NULL, 0, NULL, 0, 0, - (void **) &np, -sizeof (int))) - deputy_die_on_communication(); - if (np < 0 || (np && comm_recvdata((void **) &rf) < 0)) - deputy_die_on_communication(); - for (j = 0; j < op; j++) - h[j].denywrite = (h[j].denywrite != 0) | 2; - for (i = 0; i < np; i++) { - for (j = 0; j < op; j++) - if (h[j].f == rf[i]) { - h[j].denywrite &= ~2; - break; - } - if (j == op) - panic("mosix_update_remote_files: not listed"); - } - for (j = 0; j < op; j++) - if ((fp = h[j].f) && (h[j].denywrite & 2)) { - task_lock(p); - h[j].f = NULL; - task_unlock(p); - if (h[j].denywrite & 1) - allow_write_access(fp); - fput(fp); - } - if (np) - comm_free(rf); -} - -int -mosix_rebuild_file_list(void) -{ - struct task_struct *p = current; - struct vm_area_struct *vma, *vmb; - struct mm_struct *mm = p->mm; - struct held_files *hf = NULL, *old; - unsigned int i, n; - int oldn; - unsigned int denywrite; - struct file *this; - - if (p->mosix.dflags & DDEPUTY) { - if (p->mosix.dflags & DINCOMING) - p->mosix.dflags |= DDELAYHELD; - else - mosix_update_remote_files(); - return (0); - } - if (atomic_read(&mm->mm_realusers) > 1) { - mosix_clear_all_held_files(p); /* discard old */ - return (-EBUSY); /* thread */ - } - /* because we are the only clone, no MM lock is needed */ - /* and the initial count cannot change */ - - for (n = 0, vma = mm->mmap; vma; vma = vma->vm_next) - if ((this = vma->vm_file)) { - for (vmb = mm->mmap; vmb != vma; vmb = vmb->vm_next) - if (vmb->vm_file == vma->vm_file) - break; - if (vmb == vma) { - if (this->f_dentry->d_inode->i_mapping-> - i_mmap_shared) { - monkey: - mosix_clear_all_held_files(p); - tell_process(p, DREQ_CHECKSTAY); - return (-EDIST); - } - n++; - } - } - if (n && !(hf = kmalloc(n * sizeof (struct held_files), GFP_KERNEL))) { - mosix_clear_all_held_files(p); /* discard old */ - return (-ENOMEM); - } - for (n = 0, vma = mm->mmap; vma; vma = vma->vm_next) - if ((this = vma->vm_file)) { - for (vmb = mm->mmap; vmb != vma; vmb = vmb->vm_next) - if (vmb->vm_file == this) - goto already_placed; - denywrite = 0; - for (; vmb; vmb = vmb->vm_next) - if (vmb->vm_file == this - && (vmb->vm_flags & VM_DENYWRITE)) { - denywrite = 1; - atomic_dec(&this->f_dentry->d_inode-> - i_writecount); - break; - } - get_file(this); - hf[n].f = this; - hf[n++].denywrite = denywrite; - already_placed:; - } - /* must not use "mosix_clear_all_held_files" because it could sleep */ - /* in 'fput' when another held file becomes VMONKEY */ - oldn = p->mosix.held_allocated; - old = p->mosix.held_files; - task_lock(p); - p->mosix.held_files = hf; - p->mosix.held_allocated = n; - task_unlock(p); - if (old) { - for (i = 0; i < oldn; i++) - if ((this = old[i].f)) { - if (old[i].denywrite) - allow_write_access(this); - fput(this); - } - kfree(old); - } - /* final race check: has any file been made monkey meanwhile? */ - for (i = 0; i < n; i++) - if (hf[i].f->f_dentry->d_inode->i_mapping->i_mmap_shared) - goto monkey; - return (0); -} - -int -fork_mosix_remote_files(struct task_struct *p) -{ - unsigned int i; - struct file *fp; - - if (!(p->mosix.held_allocated = current->mosix.held_allocated)) - return (0); - if (!(p->mosix.held_files = kmalloc(p->mosix.held_allocated * - sizeof (struct held_files), - GFP_KERNEL))) { - p->mosix.held_allocated = 0; - return (-ENOMEM); - } - for (i = 0; i < current->mosix.held_allocated; i++) - if ((fp = (struct file *) current->mosix.held_files[i].f)) { - get_file(fp); - p->mosix.held_files[i].f = fp; - if ((p->mosix.held_files[i].denywrite = - current->mosix.held_files[i].denywrite)) - atomic_dec(&fp->f_dentry->d_inode-> - i_writecount); - } else - p->mosix.held_files[i].f = NULL; - return (0); -} - -void -mosix_clear_all_held_files(struct task_struct *p) -{ - unsigned int i; - int n; - struct held_files *h; - - if (!(n = p->mosix.held_allocated)) - return; - h = p->mosix.held_files; - task_lock(p); - p->mosix.held_files = NULL; - p->mosix.held_allocated = 0; - task_unlock(p); - for (i = 0; i < n; i++) - if (h[i].f) { - if (h[i].denywrite) - allow_write_access(h[i].f); - fput(h[i].f); - } - kfree(h); -} - -int -task_maps_ip(struct task_struct *p, struct inode *ip) -{ - unsigned int i; - int n; - int ret = 0; - struct held_files *h; - - task_lock(p); - if ((n = p->mosix.held_allocated)) - for (h = p->mosix.held_files, i = 0; i < n; i++) - if (h[i].f && (h[i].f)->f_dentry->d_inode == ip) { - ret = 1; - break; - } - task_unlock(p); - return (ret); -} diff -Naur linux-2.4.26-om1/hpc/service.c linux-2.4.26-om1-o/hpc/service.c --- linux-2.4.26-om1/hpc/service.c 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/service.c 2006-05-07 17:56:02.000000000 +0530 @@ -227,6 +227,7 @@ struct vm_area_struct *vma; int count = 0; int isfile; + int isshared = 0; unsigned long start, addr, pgd_end, pmd_end, pte_end; pgd_t *pgdir; pmd_t *pmdir; @@ -254,6 +255,7 @@ start = addr; pgdir = pgd_offset(mm, start); isfile = (vma->vm_file != NULL); + isshared = !(!(vma->vm_flags & VM_SHARED)); for (addr = start; addr < vma->vm_end; addr = pgd_end, pgdir++) { if (let_go-- == 0) { @@ -281,8 +283,8 @@ if (pte_end > pmd_end) pte_end = pmd_end; if (pte_present(*pte) ? - (isfile - && !pte_really_dirty(*pte)) + (isfile && + (isshared || !pte_really_dirty(*pte))) : pte_none(*pte)) { if (isfile && count_in_file) diff -Naur linux-2.4.26-om1/hpc/shm_comm.c linux-2.4.26-om1-o/hpc/shm_comm.c --- linux-2.4.26-om1/hpc/shm_comm.c 1970-01-01 05:30:00.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/shm_comm.c 2006-05-07 17:56:02.000000000 +0530 @@ -0,0 +1,452 @@ +#include <linux/sched.h> +#include <linux/socket.h> +#include <linux/poll.h> +#include <linux/hpcctl.h> +#include <net/sock.h> +#include <hpc/defs.h> +#include <hpc/routines.h> +#include <hpc/protocol.h> +#include <linux/hpc.h> +#include <asm/uaccess.h> +#include <linux/smp_lock.h> +#include <linux/swap.h> +#include <linux/pagemap.h> +#include <linux/stddef.h> +#include <hpc/comm.h> +#include <hpc/debug.h> +#include <hpc/hpcversion.h> +#include <hpc/balance.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <hpc/mig_shm.h> +#include <hpc/shm_pagemap.h> + + +static char MIGSHMDSTR[] = "MigShmD"; + + +static struct mosix_addr *fill_to_addr(int mos,struct mosix_addr *to,unsigned short int port); + + +static int +info_recv_message(struct shm_request *request); + +int +mosix_migshm_daemon(void *nothing) +{ + struct task_struct *p = current; + struct shm_request shm_req; + static struct mosix_link *link; + + common_daemon_setup(MIGSHMDSTR, 1); + + restart: + wait_for_mosix_configuration(NULL); + + if (!p->mosix.contact) { + if(!(link = comm_open(COMM_MIGSHM,0,0UL))) + goto h; + comm_use(p, link); + if (!p->mosix.contact) + { + h: printk("%s: failed comm_open - exiting\n",MIGSHMDSTR); + if(p->mosix.contact) + comm_close(NULL); + do_exit(0); + } + } + + while (1) { + comm_wait(); + + /* if openMosix was shut down - restart everything */ + if (!PE) { + comm_close(NULL); + comm_free_linkpool(); + goto restart; + } + + info_recv_message(&shm_req); + } + } + +static int +info_recv_message(struct shm_request *request) +{ + struct mosix_addr ra; /* reply address */ + struct mosix_link *l = current->mosix.contact; + struct shm_page *shm_page; + struct page *page; + int n; + int sender; + unsigned long dummy; + while (1) { + n = comm_recvfrom(request, sizeof(struct shm_request), l, &ra, 0); + if (n == -EDIST ) + continue; /* message > bufsize */ + + if (n < 0) + return (0); + + if (n < sizeof (struct shm_request)) { + continue; + } + sender = request->pe; + if (sender > MAXPE ||((request->which != INVALIDATE) && (sender != net_to_mos(&ra)))) { + continue; + } + + if (sender == PE) { + printk + ("WARNING: Another computer is masquerading as same openMosix node as this (%d)!\n", + PE); + continue; + } + if((request->which == GET_FILE) || (request->which == PUT_FILE)) { + unsigned long dummy = 0; + + + if(request->which == GET_FILE) + get_file((struct file *)request->rem_shm_page_addr); + else + fput((struct file *)request->rem_shm_page_addr); + + comm_sendto(COMM_TOADDR,&dummy,sizeof(dummy),l,&ra); + continue; + } + + shm_page = request->rem_shm_page_addr; + + shm_pagecache_get(shm_page); + + switch(request->which) { + + case INVALIDATE: + + if(!(shm_page->state & AT_HOME)) { + page = find_get_page(shm_page->mapping,shm_page->index); + + invalidate(shm_page,page,1); + + page_cache_release(page); + } + + request->rem_shm_page_addr = shm_page->next_addr; + + if(request->next == 0) + request->next = ((struct sockaddr_in *)(&(ra.saddr)))->sin_port; + + if(shm_page->next != request->pe) + comm_sendto(shm_page->next, request, sizeof (struct shm_request), l, + fill_to_addr(shm_page->next,&ra,MIGSHM_DEAMON_PORT)); + else + comm_sendto(shm_page->next, &dummy,sizeof(dummy),l, + fill_to_addr(shm_page->next,&ra,request->next)); + + break; + + + case FORWARD_REQUEST_READ: + case FORWARD_REQUEST_WRITE: + + if(request->which & FORWARD_REQUEST_READ) { + shm_page->next = request->next; + shm_page->next_addr = request->next_addr; + shm_page->prev = request->prev; + shm_page->prev_addr = request->prev_addr; + } + + page = find_get_page(shm_page->mapping,shm_page->index); + + invalidate(shm_page,page,(request->which & FORWARD_REQUEST_WRITE)); + + comm_sendto(COMM_TOADDR,kmap(page),PAGE_SIZE,l,&ra); + kunmap(page); + + page_cache_release(page); + + break; + + case WRITE_BACK: + { + + struct mosix_link *mlink=NULL; + struct mosix_addr from; + + spin_lock(&shm_page->shm_lock); + + if(shm_page->state & PERM_ERR) { + shm_page->state &= ~(PERM_ERR|STATE_MASK); + shm_page->state |= BUSY_EXCLUSIVE; + shm_page->readers = shm_page->writers = 0; + dummy = 0; + spin_unlock(&shm_page->shm_lock); + goto l; + } + + switch(shm_page->state & STATE_MASK) { + + case BUSY_SHARED: + case BUSY_EXCLUSIVE: + + spin_unlock(&shm_page->shm_lock); + dummy = 1; + break; + + case EXCLUSIVE: + + if(!shm_page->readers) { + shm_page->state &= ~ EXCLUSIVE; + shm_page->state |= BUSY_EXCLUSIVE; + dummy = 0; + } else + dummy = 1; + + spin_unlock(&shm_page->shm_lock); + break; + } + l: + + if(!dummy) { + mlink = comm_open(MIGSHM_COMM, &from,comm_connect_timo); + if(!mlink) break; + comm_sendto(COMM_TOADDR,&dummy,sizeof(dummy),mlink,&ra); + } else + comm_sendto(COMM_TOADDR,&dummy,sizeof(dummy),l,&ra); + + if(!dummy) { + + page = find_or_create_page(shm_page->mapping,shm_page->index,GFP_NOFS); + + comm_recvfrom(kmap(page),PAGE_SIZE,mlink,&ra,0); + SetPageUptodate(page); + set_page_dirty(page); + shm_page->owner = PE; + unlock_page(page); + kunmap(page); + spin_lock(&shm_page->shm_lock); + shm_page->state &= ~BUSY_EXCLUSIVE; + shm_page->state |= EXCLUSIVE; + spin_unlock(&shm_page->shm_lock); + + page_cache_release(page); + comm_close(mlink); + shm_pagecache_release(shm_page); + } + + } + + break; + + case DROP_PAGE_START: + + dummy = 1; + + spin_lock(&shm_page->shm_lock); + + if(shm_page->state & UPGRADE_ERR) + dummy = 2; + else + if(((shm_page->state & STATE_MASK) == SHARED) && !(shm_page->state & DROPPING)) { + shm_page->state |= DROPPING; + dummy = 0; + } + + spin_unlock(&shm_page->shm_lock); + + comm_sendto(COMM_TOADDR,&dummy,sizeof(dummy),l,&ra); + + + break; + + case DROP_PAGE_END: + + shm_page->state &= ~DROPPING; + break; + + case DROP_PREV: + + shm_page->prev = request->prev; + shm_page->prev_addr = request->prev_addr; + + comm_sendto(COMM_TOADDR,&dummy,sizeof(dummy),l,&ra); + + break; + + case DROP_NEXT: + + shm_page->next = request->next; + shm_page->next_addr = request->next_addr; + + comm_sendto(COMM_TOADDR,&dummy,sizeof(dummy),l,&ra); + break; + } + + shm_pagecache_release(shm_page); + } +} + +struct mosix_addr * fill_to_addr(int mos,struct mosix_addr *to,unsigned short int port) +{ + struct sockaddr_in *sa = (struct sockaddr_in *)(&(to->saddr)); + if(!mos_to_net(mos,sa)) { + return NULL; + } + sa->sin_port = port; + return to; +} + +int shm_send_message(int mos,struct shm_page *shm_page,struct page *buf_page,int which) +{ + struct mosix_addr to,from; + struct shm_request request; + struct task_struct *p = current; + int res = 1 ; + struct mosix_link *mlink = NULL; + + if(mos && (!fill_to_addr(mos,&to,MIGSHM_DEAMON_PORT))) + goto out; + + mlink = comm_open(MIGSHM_COMM, &from,comm_connect_timo); + if(!mlink) + goto out; + res = 0; + request.pe = PE; + switch(which) { + + case FORWARD_REQUEST_READ: + case FORWARD_REQUEST_WRITE: + + request.which = which; + + if(which == FORWARD_REQUEST_READ) { + request.next = request.prev = PE; + request.next_addr = request.prev_addr = shm_page; + + if(shm_page->prev != mos) { + request.next = shm_page->prev; + request.next_addr = shm_page->prev_addr; + } + } + + request.rem_shm_page_addr = shm_page->rem_shm_page_addr; + + if((comm_sendto(mos, &request, sizeof (struct shm_request), mlink,&to) < 0) || + (comm_recvfrom(kmap(buf_page),PAGE_SIZE, mlink ,&from,GTIME_OUT) <= 0)) + res = 1; + + kunmap(buf_page); + + break; + + case INVALIDATE: + + request.which = INVALIDATE; + request.rem_shm_page_addr = shm_page->next_addr; + + request.next = 0; + + if((comm_sendto(mos ,&request,sizeof(struct shm_request), mlink, &to) < 0) || + (comm_recvfrom(&res,sizeof(res),mlink,&from,INT_TIME_OUT) <= 0)) + res = 1; + break; + + case WRITE_BACK: + + request.which = WRITE_BACK; + request.rem_shm_page_addr = shm_page->rem_shm_page_addr; + + if((comm_sendto(mos,&request,sizeof(struct shm_request),mlink,&to) < 0) || + (comm_recvfrom(&res,sizeof(res),mlink,&from,GTIME_OUT) <= 0)) + res = 1; + + if(!res) { + + if(comm_sendto(mos,kmap(buf_page),PAGE_SIZE,mlink, + &from) < 0 ) + res = 1; + kunmap(buf_page); + } + + break; + + case DROP_PAGE: + + request.which = DROP_PAGE_START; + request.rem_shm_page_addr = shm_page->rem_shm_page_addr; + + if((comm_sendto(mos,&request,sizeof(struct shm_request),mlink,&to) < 0) || + (comm_recvfrom(&res,sizeof(res),mlink,&from,GTIME_OUT) <= 0)) + res = 1; + + if(!res) { + + case DROP_NEXTPREV: if(!fill_to_addr(shm_page->prev,&to,MIGSHM_DEAMON_PORT)) { + res = 1; + break; + } + case DROP_NEXT: + request.which = DROP_NEXT; + request.rem_shm_page_addr = shm_page->prev_addr; + request.next = shm_page->next; + request.next_addr = shm_page->next_addr; + + if((comm_sendto(shm_page->prev,&request,sizeof(struct shm_request),mlink,&to) < 0) || + (comm_recvfrom(&res,sizeof(res),mlink,&from,GTIME_OUT) <= 0)) + res = 1; + + if(which == DROP_NEXT) + break; + + if(!fill_to_addr(shm_page->next,&to,MIGSHM_DEAMON_PORT)) { + res = 1; + break; + } + + request.which = DROP_PREV; + request.rem_shm_page_addr = shm_page->next_addr; + request.prev = shm_page->prev; + request.prev_addr = shm_page->prev_addr; + + if((comm_sendto(shm_page->next,&request,sizeof(struct shm_request),mlink,&to) < 0) || + (comm_recvfrom(&res,sizeof(res),mlink,&from,GTIME_OUT) <= 0)) + res = 1; + + if(which == DROP_NEXTPREV) + break; + + + if(!fill_to_addr(mos,&to,MIGSHM_DEAMON_PORT)) { + res = 1; + break; + } + + case DROP_PAGE_END: + + request.which = DROP_PAGE_END; + request.rem_shm_page_addr = shm_page->rem_shm_page_addr; + + if(comm_sendto(mos,&request,sizeof(struct shm_request),mlink,&to) < 0) + res = 1; + } + + break; + + case GET_FILE: + case PUT_FILE: + + request.which = which; + request.rem_shm_page_addr = (struct shm_page *)shm_page; + + if((comm_sendto(mos,&request,sizeof(struct shm_request),mlink,&to)<0) || + (comm_recvfrom(&res,sizeof(res),mlink,&from,GTIME_OUT) <= 0)) + res = 1; + + break; + } + + comm_close(mlink); +out: + return res; +} + diff -Naur linux-2.4.26-om1/hpc/shm_filemap.c linux-2.4.26-om1-o/hpc/shm_filemap.c --- linux-2.4.26-om1/hpc/shm_filemap.c 1970-01-01 05:30:00.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/shm_filemap.c 2006-05-07 17:56:02.000000000 +0530 @@ -0,0 +1,209 @@ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/shm.h> +#include <linux/mman.h> +#include <linux/locks.h> +#include <linux/swap.h> +#include <linux/smp_lock.h> +#include <linux/blkdev.h> +#include <linux/file.h> +#include <linux/swapctl.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include<linux/wait.h> +#include <linux/iobuf.h> + +#include <asm/pgalloc.h> +#include <asm/uaccess.h> +#include <asm/mman.h> +#include <asm/atomic.h> + +#include <linux/highmem.h> +#include <hpc/mig_shm.h> +#include <hpc/shm_pagemap.h> + +LIST_HEAD(shm_page_unused_list); + + +spinlock_cacheline_t shm_pagecache_lock_cacheline = {SPIN_LOCK_UNLOCKED}; + + +unsigned int shm_page_hash_bits; + +struct shm_page **shm_page_hash_table; + +void shm_pagecache_release(struct shm_page *shm_page) +{ + if(atomic_read(&shm_page->count) == 0) + BUG(); + + spin_lock(&shm_pagecache_lock); + + atomic_dec(&shm_page->count); + + if((atomic_read(&shm_page->count) == 1) && shm_page->mapping) + remove_shm_page(shm_page); + + if((atomic_read(&shm_page->count) == 0)) + list_add(&shm_page->list, &shm_page_unused_list); + + spin_unlock(&shm_pagecache_lock); +} + +static void add_page_to_hash_queue(struct shm_page * page, struct shm_page **p) + { + struct shm_page *next = *p; + + *p = page; + page->next_hash = next; + page->pprev_hash = p; + if (next) + next->pprev_hash = &page->next_hash; + } +static inline void __add_to_page_cache(struct shm_page * page, + struct address_space *mapping, unsigned long offset, + struct shm_page **hash) + { + + shm_pagecache_get(page); + page->index = offset; + page->mapping = mapping; + add_page_to_hash_queue(page, hash); + } +void add_to_shm_page_cache(struct shm_page * page, struct address_space * mapping, unsigned long offset) +{ + spin_lock(&shm_pagecache_lock); + __add_to_page_cache(page, mapping, offset, shm_page_hash(mapping, offset)); + spin_unlock(&shm_pagecache_lock); +} + +static inline void remove_page_from_hash_queue(struct shm_page * page) +{ + struct shm_page *next = page->next_hash; + struct shm_page **pprev = page->pprev_hash; + + if (next) + next->pprev_hash = pprev; + *pprev = next; + page->pprev_hash = NULL; +} + +void remove_shm_page(struct shm_page * page) + { + remove_page_from_hash_queue(page); + page->mapping = NULL; + atomic_dec(&page->count); + } + + +static struct shm_page *alloc_shm_page(void) +{ + struct shm_page *shm_page = NULL; + struct task_struct *p = current; + + spin_lock(&shm_pagecache_lock); + + if(!list_empty(&shm_page_unused_list)) { + shm_page = list_entry(shm_page_unused_list.prev,struct shm_page,list); + list_del(&shm_page->list); + } + + spin_unlock(&shm_pagecache_lock); + + if(!shm_page) + shm_page = kmem_cache_alloc(shm_page_cachep,SLAB_KERNEL); + + if(!shm_page) + return NULL; + + + memset(shm_page,0,sizeof(struct shm_page)); + atomic_set(&shm_page->count,1); + shm_page->owner = PE; + shm_page->prev = shm_page->next = PE; + shm_page->prev_addr = shm_page->next_addr = shm_page; + shm_page->mapping = NULL; + shm_page->readers = shm_page->writers = 0; + shm_page->shm_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&shm_page->list); + return shm_page; +} + +static inline struct shm_page * __find_page_nolock(struct address_space *mapping, unsigned long offset, + struct shm_page *page) + { + goto inside; + + for (;;) { + page = page->next_hash; + inside: + if (!page) + goto not_found; + if (page->mapping != mapping) + continue; + if (page->index == offset) + break; + } + + not_found: + return page; + } + + /* + * a rather lightweight function, finding and getting a reference to a + * hashed page atomically. + */ + struct shm_page * find_get_shm_page(struct address_space *mapping, + unsigned long offset, struct shm_page **hash) + { + struct shm_page *page; + + /* + * We scan the hash list read-only. Addition to and removal from + * the hash-list needs a held write-lock. + */ + spin_lock(&shm_pagecache_lock); + page = __find_page_nolock(mapping, offset, *hash); + if (page) + atomic_inc(&page->count); + spin_unlock(&shm_pagecache_lock); + return page; + } + /* + * Same as above, but create the page if required.. + */ + struct shm_page * find_or_create_shm_page(struct address_space *mapping, unsigned long index) + { + struct shm_page *page; + struct shm_page **hash = shm_page_hash(mapping, index); + extern struct super_block bad_super_block; + + page = find_get_shm_page(mapping, index, hash); + + if (!page) { + struct shm_page *newpage = alloc_shm_page(); + if (newpage) { + spin_lock(&shm_pagecache_lock); + page = __find_page_nolock(mapping, index, *hash); + if (likely(!page)) { + if((unsigned long)(mapping->host->i_sb) == (unsigned long)(&bad_super_block)) + newpage->state |= IDLE; + else { + newpage->state |= EXCLUSIVE; + newpage->state |= AT_HOME; + } + + page = newpage; + __add_to_page_cache(page, mapping, index, hash); + newpage = NULL; + } else + shm_pagecache_get(page); + spin_unlock(&shm_pagecache_lock); + if (newpage) + shm_pagecache_release(newpage); + } + } + return page; + } + diff -Naur linux-2.4.26-om1/hpc/syscalls.c linux-2.4.26-om1-o/hpc/syscalls.c --- linux-2.4.26-om1/hpc/syscalls.c 2006-05-08 15:02:17.000000000 +0530 +++ linux-2.4.26-om1-o/hpc/syscalls.c 2006-05-07 17:56:02.000000000 +0530 @@ -1733,6 +1733,10 @@ break; } break; + case SHMGET: + case SHMAT: + case SHMDT: + case SEMGET: case MSGGET: /* added this so we can return -EINVAL in the default */ break; case MSGCTL: diff -Naur linux-2.4.26-om1/include/asm-i386/pgtable.h linux-2.4.26-om1-o/include/asm-i386/pgtable.h --- linux-2.4.26-om1/include/asm-i386/pgtable.h 2006-05-08 15:02:19.000000000 +0530 +++ linux-2.4.26-om1-o/include/asm-i386/pgtable.h 2006-05-08 10:49:51.000000000 +0530 @@ -201,7 +201,7 @@ #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT |_PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) diff -Naur linux-2.4.26-om1/include/hpc/comm.h linux-2.4.26-om1-o/include/hpc/comm.h --- linux-2.4.26-om1/include/hpc/comm.h 2006-05-08 15:02:24.000000000 +0530 +++ linux-2.4.26-om1-o/include/hpc/comm.h 2006-05-07 17:56:02.000000000 +0530 @@ -19,6 +19,9 @@ #ifdef __KERNEL__ +#define MIGSHM_DEAMON_PORT 0x3419 + + struct mosix_link; /* defined in hpc/comm.c */ struct mosix_addr; /* defined in include/hpc/protocol.h */ struct mosix_task; @@ -35,7 +38,11 @@ #define COMM_ACCEPT (70002) #define COMM_MIGD (70003) #define COMM_INFO (70004) +#define COMM_MIGSHM (70006) #define COMM_LOOSE (70005) +#define MIGSHM_COMM (70007) + + /* * message flags: @@ -77,6 +84,9 @@ #define COMM_HLEN (sizeof(struct comm_header)) +#define GTIME_OUT 1 +#define INT_TIME_OUT 2 + /* * exported data */ @@ -89,6 +99,7 @@ * communication module interface */ +extern int comm_getname(struct socket *sock, struct sockaddr *saddr); extern void comm_startup(void); extern mosix_link *comm_open(int, mosix_addr *, unsigned long); extern mosix_link *comm_use(struct task_struct *, mosix_link *); @@ -119,7 +130,7 @@ extern mosix_link *comm_borrow_linkpool(void); extern void comm_return_linkpool(mosix_link *); extern void comm_age_linkpool(void); -extern void rinode_flush_files(int); + extern spinlock_t skown_lock; diff -Naur linux-2.4.26-om1/include/hpc/hpctask.h linux-2.4.26-om1-o/include/hpc/hpctask.h --- linux-2.4.26-om1/include/hpc/hpctask.h 2006-05-08 15:02:24.000000000 +0530 +++ linux-2.4.26-om1-o/include/hpc/hpctask.h 2006-05-07 17:56:02.000000000 +0530 @@ -49,12 +49,6 @@ volatile long bstate; /* backed-up state while in MOSIX */ rwlock_t state_lock; /* changes of bstate */ kernel_cap_t remote_caps; /* effective capabilities on REMOTE */ - struct held_files - { - struct file *f; /* a file in use */ - char denywrite; /* whether holding i_writecount down */ - } *held_files; /* files held by remote VM */ - int held_allocated; /* # of entries in "held_inodes" */ struct mosix_link *contact; /* DEPUTY <==> REMOTE connection */ struct task_struct *ancesstor; /* nearest ancesstor when dependent */ uint32_t deputytime; /* ticks spent on DEPUTY */ @@ -194,7 +188,6 @@ #define DTRACESYS2 0x00004000 /* syscall done before 2nd PT_TRACESYS*/ #define DMUSTBEBACK 0x00008000 /* MUST arrive back home */ #define DDUMPABLE 0x00010000 /* copy of dumpable when DEPUTY */ -#define DDELAYHELD 0x00020000 /* rebuild held_files later */ #define DTDUMPABLE 0x00040000 /* copy of task_dumpable when DEPUTY */ #define DMIGFILTER 0x00040000 /* process migration is conditioned */ #ifdef CONFIG_MOSIX_DFSA @@ -214,7 +207,6 @@ #define DREQ_URGENT 0x00000020 /* something urgent (R=>D) */ #define DREQ_CAPCNG 0x00000040 /* capabilities changed */ #define DREQ_INFOCNG 0x00000080 /* disclosed info changed */ -#define DREQ_FILEUNMAP 0x00000100 /* file(s) were unmapped */ #ifdef CONFIG_MOSIX_DFSA #define DREQ_NOTUPTODATE 0x10000000 /* send it all again */ #define DREQ_DFSASYNC 0x20000000 /* DFSA world changed */ @@ -232,7 +224,6 @@ * reasons to stay: */ -#define DSTAY_FOR_MONKEY 0x00000001 /* using monkey vnode */ #define DSTAY_FOR_DEV 0x00000002 /* mapping a device */ #define DSTAY_FOR_86 0x00000004 /* running in 86 mode */ #define DSTAY_SYSTEM 0x00000008 /* system process (init, oM daemon) */ @@ -249,7 +240,7 @@ #define DNOMIGRATE 0x80000000 /* user requested no auto-migrations */ #define DSTAY (~DNOMIGRATE) -#define DSTAY_PER_MM (DSTAY_FOR_MONKEY|DSTAY_FOR_DEV|DSTAY_FOR_MLOCK|DSTAY_FOR_KIOBUF) +#define DSTAY_PER_MM (DSTAY_FOR_DEV|DSTAY_FOR_MLOCK|DSTAY_FOR_KIOBUF) /* * where to go (whereto) diff -Naur linux-2.4.26-om1/include/hpc/mig_shm.h linux-2.4.26-om1-o/include/hpc/mig_shm.h --- linux-2.4.26-om1/include/hpc/mig_shm.h 1970-01-01 05:30:00.000000000 +0530 +++ linux-2.4.26-om1-o/include/hpc/mig_shm.h 2006-05-07 17:56:02.000000000 +0530 @@ -0,0 +1,73 @@ +#ifndef _MIG_SHM_H +#define _MIG_SHM_H +struct shm_pgentry; +struct shm_page { + struct list_head list; + struct address_space *mapping; + unsigned long index; + struct shm_page *next_hash; + atomic_t count; + int prev,next; + unsigned long state; + struct shm_page **pprev_hash; + unsigned int owner; + unsigned int readers; + unsigned int writers; + struct shm_page *rem_shm_page_addr,*prev_addr,*next_addr; + spinlock_t shm_lock; +}; + +/* +struct shm_request { + unsigned long which; + int pe; + struct shm_page *rem_shm_page_addr; + struct shm_page *next_addr,*prev_addr; + unsigned long prev,next; + struct mosix_addr from; +}; +struct wb_reply { + unsigned long dummy; + struct mosix_addr from; +}; +*/ + +#define IDLE 0x00000001 +#define SHARED 0x00000002 +#define EXCLUSIVE 0x00000004 +#define BUSY_SHARED 0x00000008 +#define BUSY_EXCLUSIVE 0x00000010 + +#define DROPPING 0x00000020 + +#define WITH_WRITE_ACC 0x00000040 +#define WITH_READ_ACC 0x00000080 +#define AT_HOME 0x00000200 + +#define INVALIDATE 0x00000001 +#define WRITE_BACK 0x00000002 +#define DROP_PAGE 0x00000004 +#define DROP_PAGE_START 0x00000008 +#define DROP_PAGE_END 0x00000010 +#define DROP_PREV 0x00000020 +#define DROP_NEXT 0x00000040 +#define DROP_NEXTPREV 0x00000080 +#define FORWARD_REQUEST_WRITE 0x00000200 +#define FORWARD_REQUEST_READ 0x00000400 +#define GET_FILE 0x00000800 +#define PUT_FILE 0x00001000 +#define UPGRADE_ERR 0x00002000 +#define PERM_ERR 0x00004000 + +#define ACC_MASK (WITH_WRITE_ACC|WITH_READ_ACC) +#define STATE_MASK (IDLE|SHARED|EXCLUSIVE|BUSY_SHARED|BUSY_EXCLUSIVE) + +extern void invalidate(struct shm_page *shm_page,struct page *page,int write_access); +extern struct page *get_nopage(struct vm_area_struct *vma, unsigned long address,struct shm_page **shm_page,int write_access); +extern void wait_here(void); + + +#endif + + + diff -Naur linux-2.4.26-om1/include/hpc/protocol.h linux-2.4.26-om1-o/include/hpc/protocol.h --- linux-2.4.26-om1/include/hpc/protocol.h 2006-05-08 15:02:24.000000000 +0530 +++ linux-2.4.26-om1-o/include/hpc/protocol.h 2006-05-07 17:56:02.000000000 +0530 @@ -59,6 +59,7 @@ int fixed; unsigned long len; unsigned long flags; + unsigned long prot; unsigned long pgoff; int origin; struct file *fp; @@ -175,13 +176,48 @@ struct file *fp; unsigned long offset; nopage_t nopage; + int access; + struct shm_page *rem_shm_page_addr; +}; +struct write_page_h +{ + struct dentry *dentry; + unsigned long offset; +}; +struct to_be_unlocked_h +{ + struct shm_page *shm_page; + struct page *page; }; -struct page_ret_h +/*struct page_ret_h { int ret; unsigned long deputytime; }; +*/ +struct upgrade_h +{ + struct shm_page *shm_page,*rem_shm_page_addr; +}; + +struct shm_request { + unsigned long which; + int pe; + struct shm_page *rem_shm_page_addr; + struct shm_page *next_addr,*prev_addr; + unsigned long prev,next; +}; + +struct shm_page_ret_h +{ + int ret; + unsigned long deputytime; + struct shm_page *rem_shm_page_addr; + struct shm_page *next_addr,*prev_addr; + unsigned long prev,next; + +}; struct rlimit_h { @@ -459,6 +495,8 @@ #define REM_BRING_ME_REGS (ANYTIME|0x04) #define REM_GETALOAD (ANYTIME|0x05) #define REM_GETTSC (ANYTIME|0x06) +#define REM_UPGRADE (ANYTIME|0x07) +//#define REM_WRITE_BACK_PERM (ANYTIME|0X08) #define REM_NULLMSG 0x01 #define REM_ASIG 0x02 @@ -492,10 +530,13 @@ extern void deputy_add_rusage(struct rusage *); extern void deputy_analyse_remote_signals(struct asig_h *); extern int deputy_bring_page(struct bring_page_h *); +extern int deputy_upgrade(struct upgrade_h *); extern int deputy_tsc(void); extern int deputy_more_strings(struct execve_more_strings_h *); extern int deputy_bring_me_regs(unsigned long *); extern void deputy_inform_remote_of_overheads(void); +extern int deputy_writepage(struct write_page_h *g); +extern int deputy_unlock_page(struct to_be_unlocked_h *head); /* routines on the REMOTE side of the protocol: */ @@ -511,7 +552,9 @@ extern int remote_setup_args(struct execve_setup_args_h *); extern int remote_exec_mmap(void); extern int remote_urgent(void); +extern int remote_upgrade(struct shm_page *); extern int remote_readpage(struct file *, struct page *); +extern int remote_writepage(struct page *); extern int remote_dump_thread(void); extern int remote_init_aout_mm(struct exec *); extern int remote_elf_setup(struct execve_elf_setup_h *); @@ -535,7 +578,6 @@ extern int remote_verify_write(struct user_copy_h *); extern int remote_csum_copy_from_user(struct user_csum_copy_h *); extern int remote_csum_copy_to_user(struct user_csum_copy_h *); -extern int remote_report_files(void); extern int remote_setup_frame(struct setupframe_parameters_h *); extern int remote_nice(long *); extern int remote_caps(kernel_cap_t *); @@ -565,6 +607,12 @@ extern unsigned int which_regs_to_send(void); extern void regs_were_sent(void); + + +extern int mosix_migshm_daemon(void *nothing); +extern int shm_send_message(int mos,struct shm_page *shm_page,struct page *buf_page,int which); + + #endif /*__KERNEL__*/ #endif /* CONFIG_MOSIX */ #endif diff -Naur linux-2.4.26-om1/include/hpc/routines.h linux-2.4.26-om1-o/include/hpc/routines.h --- linux-2.4.26-om1/include/hpc/routines.h 2006-05-08 15:02:24.000000000 +0530 +++ linux-2.4.26-om1-o/include/hpc/routines.h 2006-05-07 17:56:02.000000000 +0530 @@ -122,11 +122,8 @@ extern void deputy_main_loop(void); extern void undeputy(struct task_struct *); extern void deputy_async_requests(void); -extern void mosix_clear_all_held_files(struct task_struct *); -extern int fork_mosix_remote_files(struct task_struct *); extern void coordinate(int, int); extern long call_with_regs(void *, struct pt_regs *, struct pt_regs *); -extern int task_maps_ip(struct task_struct *, struct inode *); extern void deputy_communication_failed(void); extern void deputy_die_on_communication(void) ATTRIB_NORET; @@ -204,6 +201,9 @@ extern int my_mosix_status(void); extern void set_my_cpuspeed(void); + +extern int mosix_migshm_daemon(void *); + /* debugging: */ /* macros: */ diff -Naur linux-2.4.26-om1/include/hpc/shm_pagemap.h linux-2.4.26-om1-o/include/hpc/shm_pagemap.h --- linux-2.4.26-om1/include/hpc/shm_pagemap.h 1970-01-01 05:30:00.000000000 +0530 +++ linux-2.4.26-om1-o/include/hpc/shm_pagemap.h 2006-05-07 17:56:02.000000000 +0530 @@ -0,0 +1,39 @@ +#ifndef _SHM_PAGEMAP_H +#define _SHM_PAGEMAP_H +extern unsigned int shm_page_hash_bits; +#define SHM_PAGE_HASH_BITS (shm_page_hash_bits) +#define SHM_PAGE_HASH_SIZE (1<<SHM_PAGE_HASH_BITS) + +extern struct shm_page **shm_page_hash_table; + +#define shm_wait_table_bits 6 +#define shm_wait_table_shift BITS_PER_LONG - shm_wait_table_bits; + +extern struct list_head shm_page_unused_list; + + +extern spinlock_cacheline_t shm_pagecache_lock_cacheline; +#define shm_pagecache_lock (shm_pagecache_lock_cacheline.lock) + +static inline unsigned long _shm_page_hashfn(struct address_space * mapping, unsigned long index) +{ +#define i (((unsigned long) mapping)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1))) +#define s(x) ((x)+((x)>>SHM_PAGE_HASH_BITS)) + return s(i+index) & (SHM_PAGE_HASH_SIZE-1); +#undef i +#undef s +} + +#define shm_page_hash(mapping,index) (shm_page_hash_table + _shm_page_hashfn(mapping,index)) + + +#define shm_pagecache_get(shm_page) (atomic_inc(&shm_page->count)) + +extern void shm_pagecache_release(struct shm_page *shm_page); +extern struct shm_page * find_or_create_shm_page(struct address_space *mapping, unsigned long index); +extern void add_to_shm_page_cache(struct shm_page * page, struct address_space * mapping, unsigned long offset); +extern void remove_shm_page(struct shm_page * page); +extern struct shm_page * find_get_shm_page(struct address_space *mapping, + unsigned long offset, struct shm_page **hash); + +#endif diff -Naur linux-2.4.26-om1/include/linux/hpc.h linux-2.4.26-om1-o/include/linux/hpc.h --- linux-2.4.26-om1/include/linux/hpc.h 2006-05-08 15:02:28.000000000 +0530 +++ linux-2.4.26-om1-o/include/linux/hpc.h 2006-05-08 10:49:51.000000000 +0530 @@ -22,10 +22,6 @@ /* operations on DEPUTY's data-base of REMOTE files: */ -extern int mosix_register_a_file(struct file *, int); -extern void mosix_undo_last_file_registration(struct file *, int); -extern int mosix_rebuild_file_list(void); -extern void mosix_update_remote_files(void); struct vmalist { @@ -60,8 +56,6 @@ extern void mosix_exit(void); extern void mosix_very_exit(void); extern void mosix_obtain_registers(unsigned long); -extern void mosix_bring_monkey_users_back(struct inode *); -extern void mosix_no_longer_monkey(struct inode *); extern void mosix_check_for_freedom_to_move(void); extern int mosix_pre_clone(void); extern void mosix_post_clone(void); @@ -126,7 +120,6 @@ */ #define FATAL_SIGSEGV SIGINT -#define REMOTE_FILE_RELEASED SIGQUIT /* other signals that can occur on REMOTE: * SIGKILL, SIGSEGV, SIGPROF, SIGVTALRM, SIGFPE, SIGBUS, SIGIOT, SIGILL, diff -Naur linux-2.4.26-om1/include/linux/mm.h linux-2.4.26-om1-o/include/linux/mm.h --- linux-2.4.26-om1/include/linux/mm.h 2006-05-08 15:02:27.000000000 +0530 +++ linux-2.4.26-om1-o/include/linux/mm.h 2006-05-08 10:49:51.000000000 +0530 @@ -183,6 +183,7 @@ #ifdef CONFIG_MOSIX char young; unsigned long last_young; + struct shm_page *shm_page; #endif /* CONFIG_MOSIX */ } mem_map_t; @@ -429,6 +430,7 @@ */ #define NOPAGE_SIGBUS (NULL) #define NOPAGE_OOM ((struct page *) (-1)) +#define PAGE_BUSY ((struct page *) (-2)) /* The array of struct pages */ extern mem_map_t * mem_map; diff -Naur linux-2.4.26-om1/include/linux/slab.h linux-2.4.26-om1-o/include/linux/slab.h --- linux-2.4.26-om1/include/linux/slab.h 2006-05-08 15:02:27.000000000 +0530 +++ linux-2.4.26-om1-o/include/linux/slab.h 2006-05-08 10:49:51.000000000 +0530 @@ -74,6 +74,9 @@ extern kmem_cache_t *bh_cachep; extern kmem_cache_t *fs_cachep; extern kmem_cache_t *sigact_cachep; +#ifdef CONFIG_MOSIX +extern kmem_cache_t *shm_page_cachep; +#endif /* CONFIG_MOSIX */ #endif /* __KERNEL__ */ diff -Naur linux-2.4.26-om1/ipc/shm.c linux-2.4.26-om1-o/ipc/shm.c --- linux-2.4.26-om1/ipc/shm.c 2006-05-08 15:03:24.000000000 +0530 +++ linux-2.4.26-om1-o/ipc/shm.c 2006-05-07 17:56:02.000000000 +0530 @@ -683,17 +683,17 @@ struct vm_area_struct *shmd, *shmdnext; int retval = -EINVAL; -#ifdef CONFIG_MOSIX - if(current->mosix.dflags & DDEPUTY) - return(0); - mosix_rebuild_file_list(); -#endif /* CONFIG_MOSIX */ down_write(&mm->mmap_sem); for (shmd = mm->mmap; shmd; shmd = shmdnext) { shmdnext = shmd->vm_next; if (shmd->vm_ops == &shm_vm_ops && shmd->vm_start - (shmd->vm_pgoff << PAGE_SHIFT) == (ulong) shmaddr) { - do_munmap(mm, shmd->vm_start, shmd->vm_end - shmd->vm_start); +#ifdef CONFIG_MOSIX + if(current->mosix.dflags & DDEPUTY) + deputy_munmap(shmd->vm_start,shmd->vm_end - shmd->vm_start); + else +#endif /* CONFIG_MOSIX */ + do_munmap(mm, shmd->vm_start, shmd->vm_end - shmd->vm_start); retval = 0; } } diff -Naur linux-2.4.26-om1/ipc/shm.c.orig linux-2.4.26-om1-o/ipc/shm.c.orig --- linux-2.4.26-om1/ipc/shm.c.orig 1970-01-01 05:30:00.000000000 +0530 +++ linux-2.4.26-om1-o/ipc/shm.c.orig 2006-05-07 17:47:21.000000000 +0530 @@ -0,0 +1,764 @@ +/* + * linux/ipc/shm.c + * Copyright (C) 1992, 1993 Krishna Balasubramanian + * Many improvements/fixes by Bruno Haible. + * Replaced `struct shm_desc' by `struct vm_area_struct', July 1994. + * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli. + * + * /proc/sysvipc/shm support (c) 1999 Dragos Acostachioaie <[email protected]> + * BIGMEM support, Andrea Arcangeli <[email protected]> + * SMP thread shm, Jean-Luc Boyard <[email protected]> + * HIGHMEM support, Ingo Molnar <[email protected]> + * Make shmmax, shmall, shmmni sysctl'able, Christoph Rohland <[email protected]> + * Shared /dev/zero support, Kanoj Sarcar <kanoj-sJ/[email protected]> + * Move the mm functionality over to mm/shmem.c, Christoph Rohland <[email protected]> + * + * Some changes by Moshe Bar to eliminate fh leaking problem in openMosix + */ + +#include <linux/config.h> +#include <linux/slab.h> +#include <linux/shm.h> +#include <linux/init.h> +#include <linux/file.h> +#include <linux/mman.h> +#include <linux/proc_fs.h> +#include <asm/uaccess.h> +#include <linux/hpc.h> +#include "util.h" + +struct shmid_kernel /* private to the kernel */ +{ + struct kern_ipc_perm shm_perm; + struct file * shm_file; + int id; + unsigned long shm_nattch; + unsigned long shm_segsz; + time_t shm_atim; + time_t shm_dtim; + time_t shm_ctim; + pid_t shm_cprid; + pid_t shm_lprid; +}; + +#define shm_flags shm_perm.mode + +static struct file_operations shm_file_operations; +static struct vm_operations_struct shm_vm_ops; + +static struct ipc_ids shm_ids; + +#define shm_lock(id) ((struct shmid_kernel*)ipc_lock(&shm_ids,id)) +#define shm_unlock(id) ipc_unlock(&shm_ids,id) +#define shm_lockall() ipc_lockall(&shm_ids) +#define shm_unlockall() ipc_unlockall(&shm_ids) +#define shm_get(id) ((struct shmid_kernel*)ipc_get(&shm_ids,id)) +#define shm_buildid(id, seq) \ + ipc_buildid(&shm_ids, id, seq) + +static int newseg (key_t key, int shmflg, size_t size); +static void shm_open (struct vm_area_struct *shmd); +static void shm_close (struct vm_area_struct *shmd); +#ifdef CONFIG_PROC_FS +static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data); +#endif + +size_t shm_ctlmax = SHMMAX; +size_t shm_ctlall = SHMALL; +int shm_ctlmni = SHMMNI; + +static int shm_tot; /* total number of shared memory pages */ + +void __init shm_init (void) +{ + ipc_init_ids(&shm_ids, 1); +#ifdef CONFIG_PROC_FS + create_proc_read_entry("sysvipc/shm", 0, 0, sysvipc_shm_read_proc, NULL); +#endif +} + +static inline int shm_checkid(struct shmid_kernel *s, int id) +{ + if (ipc_checkid(&shm_ids,&s->shm_perm,id)) + return -EIDRM; + return 0; +} + +static inline struct shmid_kernel *shm_rmid(int id) +{ + return (struct shmid_kernel *)ipc_rmid(&shm_ids,id); +} + +static inline int shm_addid(struct shmid_kernel *shp) +{ + return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1); +} + + + +static inline void shm_inc (int id) { + struct shmid_kernel *shp; + + if(!(shp = shm_lock(id))) + BUG(); + shp->shm_atim = CURRENT_TIME; + shp->shm_lprid = current->pid; + shp->shm_nattch++; + shm_unlock(id); +} + +/* This is called by fork, once for every shm attach. */ +static void shm_open (struct vm_area_struct *shmd) +{ + shm_inc (shmd->vm_file->f_dentry->d_inode->i_ino); +} + +/* + * shm_destroy - free the struct shmid_kernel + * + * @shp: struct to free + * + * It has to be called with shp and shm_ids.sem locked, + * but returns with shp unlocked and freed. + */ +static void shm_destroy (struct shmid_kernel *shp) +{ + shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; + shm_rmid (shp->id); + shm_unlock(shp->id); + shmem_lock(shp->shm_file, 0); + fput (shp->shm_file); + kfree (shp); +} + +/* + * remove the attach descriptor shmd. + * free memory for segment if it is marked destroyed. + * The descriptor has already been removed from the current->mm->mmap list + * and will later be kfree()d. + */ +static void shm_close (struct vm_area_struct *shmd) +{ + struct file * file = shmd->vm_file; + int id = file->f_dentry->d_inode->i_ino; + struct shmid_kernel *shp; + + down (&shm_ids.sem); + /* remove from the list of attaches of the shm segment */ + if(!(shp = shm_lock(id))) + BUG(); + shp->shm_lprid = current->pid; + shp->shm_dtim = CURRENT_TIME; + shp->shm_nattch--; + if(shp->shm_nattch == 0 && + shp->shm_flags & SHM_DEST) + shm_destroy (shp); + else + shm_unlock(id); + up (&shm_ids.sem); +} + +static int shm_mmap(struct file * file, struct vm_area_struct * vma) +{ + UPDATE_ATIME(file->f_dentry->d_inode); + vma->vm_ops = &shm_vm_ops; + shm_inc(file->f_dentry->d_inode->i_ino); + return 0; +} + +static struct file_operations shm_file_operations = { + mmap: shm_mmap +}; + +static struct vm_operations_struct shm_vm_ops = { + open: shm_open, /* callback for a new vm-area open */ + close: shm_close, /* callback for when the vm-area is released */ + nopage: shmem_nopage, +}; + +static int newseg (key_t key, int shmflg, size_t size) +{ + int error; + struct shmid_kernel *shp; + int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT; + struct file * file; + char name[13]; + int id; + + if (size < SHMMIN || size > shm_ctlmax) + return -EINVAL; + + if (shm_tot + numpages >= shm_ctlall) + return -ENOSPC; + + shp = (struct shmid_kernel *) kmalloc (sizeof (*shp), GFP_USER); + if (!shp) + return -ENOMEM; + sprintf (name, "SYSV%08x", key); + file = shmem_file_setup(name, size); + error = PTR_ERR(file); + if (IS_ERR(file)) + goto no_file; + + error = -ENOSPC; + id = shm_addid(shp); + if(id == -1) + goto no_id; + shp->shm_perm.key = key; + shp->shm_flags = (shmflg & S_IRWXUGO); + shp->shm_cprid = current->pid; + shp->shm_lprid = 0; + shp->shm_atim = shp->shm_dtim = 0; + shp->shm_ctim = CURRENT_TIME; + shp->shm_segsz = size; + shp->shm_nattch = 0; + shp->id = shm_buildid(id,shp->shm_perm.seq); + shp->shm_file = file; + file->f_dentry->d_inode->i_ino = shp->id; + file->f_op = &shm_file_operations; + shm_tot += numpages; + shm_unlock (id); + return shp->id; + +no_id: + fput(file); +no_file: + kfree(shp); + return error; +} + +asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) +{ + struct shmid_kernel *shp; + int err, id = 0; + + down(&shm_ids.sem); + if (key == IPC_PRIVATE) { + err = newseg(key, shmflg, size); + } else if ((id = ipc_findkey(&shm_ids, key)) == -1) { + if (!(shmflg & IPC_CREAT)) + err = -ENOENT; + else + err = newseg(key, shmflg, size); + } else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) { + err = -EEXIST; + } else { + shp = shm_lock(id); + if(shp==NULL) + BUG(); + if (shp->shm_segsz < size) + err = -EINVAL; + else if (ipcperms(&shp->shm_perm, shmflg)) + err = -EACCES; + else + err = shm_buildid(id, shp->shm_perm.seq); + shm_unlock(id); + } + up(&shm_ids.sem); + return err; +} + +static inline unsigned long copy_shmid_to_user(void *buf, struct shmid64_ds *in, int version) +{ + switch(version) { + case IPC_64: + return copy_to_user(buf, in, sizeof(*in)); + case IPC_OLD: + { + struct shmid_ds out; + + ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm); + out.shm_segsz = in->shm_segsz; + out.shm_atime = in->shm_atime; + out.shm_dtime = in->shm_dtime; + out.shm_ctime = in->shm_ctime; + out.shm_cpid = in->shm_cpid; + out.shm_lpid = in->shm_lpid; + out.shm_nattch = in->shm_nattch; + + return copy_to_user(buf, &out, sizeof(out)); + } + default: + return -EINVAL; + } +} + +struct shm_setbuf { + uid_t uid; + gid_t gid; + mode_t mode; +}; + +static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void *buf, int version) +{ + switch(version) { + case IPC_64: + { + struct shmid64_ds tbuf; + + if (copy_from_user(&tbuf, buf, sizeof(tbuf))) + return -EFAULT; + + out->uid = tbuf.shm_perm.uid; + out->gid = tbuf.shm_perm.gid; + out->mode = tbuf.shm_flags; + + return 0; + } + case IPC_OLD: + { + struct shmid_ds tbuf_old; + + if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old))) + return -EFAULT; + + out->uid = tbuf_old.shm_perm.uid; + out->gid = tbuf_old.shm_perm.gid; + out->mode = tbuf_old.shm_flags; + + return 0; + } + default: + return -EINVAL; + } +} + +static inline unsigned long copy_shminfo_to_user(void *buf, struct shminfo64 *in, int version) +{ + switch(version) { + case IPC_64: + return copy_to_user(buf, in, sizeof(*in)); + case IPC_OLD: + { + struct shminfo out; + + if(in->shmmax > INT_MAX) + out.shmmax = INT_MAX; + else + out.shmmax = (int)in->shmmax; + + out.shmmin = in->shmmin; + out.shmmni = in->shmmni; + out.shmseg = in->shmseg; + out.shmall = in->shmall; + + return copy_to_user(buf, &out, sizeof(out)); + } + default: + return -EINVAL; + } +} + +static void shm_get_stat (unsigned long *rss, unsigned long *swp) +{ + struct shmem_inode_info *info; + int i; + + *rss = 0; + *swp = 0; + + for(i = 0; i <= shm_ids.max_id; i++) { + struct shmid_kernel* shp; + struct inode * inode; + + shp = shm_get(i); + if(shp == NULL) + continue; + inode = shp->shm_file->f_dentry->d_inode; + info = SHMEM_I(inode); + spin_lock (&info->lock); + *rss += inode->i_mapping->nrpages; + *swp += info->swapped; + spin_unlock (&info->lock); + } +} + +asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) +{ + struct shm_setbuf setbuf; + struct shmid_kernel *shp; + int err, version; + + if (cmd < 0 || shmid < 0) + return -EINVAL; + + version = ipc_parse_version(&cmd); + + switch (cmd) { /* replace with proc interface ? */ + case IPC_INFO: + { + struct shminfo64 shminfo; + + memset(&shminfo,0,sizeof(shminfo)); + shminfo.shmmni = shminfo.shmseg = shm_ctlmni; + shminfo.shmmax = shm_ctlmax; + shminfo.shmall = shm_ctlall; + + shminfo.shmmin = SHMMIN; + if(copy_shminfo_to_user (buf, &shminfo, version)) + return -EFAULT; + /* reading a integer is always atomic */ + err= shm_ids.max_id; + if(err<0) + err = 0; + return err; + } + case SHM_INFO: + { + struct shm_info shm_info; + + memset(&shm_info,0,sizeof(shm_info)); + down(&shm_ids.sem); + shm_lockall(); + shm_info.used_ids = shm_ids.in_use; + shm_get_stat (&shm_info.shm_rss, &shm_info.shm_swp); + shm_info.shm_tot = shm_tot; + shm_info.swap_attempts = 0; + shm_info.swap_successes = 0; + err = shm_ids.max_id; + shm_unlockall(); + up(&shm_ids.sem); + if(copy_to_user (buf, &shm_info, sizeof(shm_info))) + return -EFAULT; + + return err < 0 ? 0 : err; + } + case SHM_STAT: + case IPC_STAT: + { + struct shmid64_ds tbuf; + int result; + memset(&tbuf, 0, sizeof(tbuf)); + shp = shm_lock(shmid); + if(shp==NULL) + return -EINVAL; + if(cmd==SHM_STAT) { + err = -EINVAL; + if (shmid > shm_ids.max_id) + goto out_unlock; + result = shm_buildid(shmid, shp->shm_perm.seq); + } else { + err = shm_checkid(shp,shmid); + if(err) + goto out_unlock; + result = 0; + } + err=-EACCES; + if (ipcperms (&shp->shm_perm, S_IRUGO)) + goto out_unlock; + kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm); + tbuf.shm_segsz = shp->shm_segsz; + tbuf.shm_atime = shp->shm_atim; + tbuf.shm_dtime = shp->shm_dtim; + tbuf.shm_ctime = shp->shm_ctim; + tbuf.shm_cpid = shp->shm_cprid; + tbuf.shm_lpid = shp->shm_lprid; + tbuf.shm_nattch = shp->shm_nattch; + shm_unlock(shmid); + if(copy_shmid_to_user (buf, &tbuf, version)) + return -EFAULT; + return result; + } + case SHM_LOCK: + case SHM_UNLOCK: + { +/* Allow superuser to lock segment in memory */ +/* Should the pages be faulted in here or leave it to user? */ +/* need to determine interaction with current->swappable */ + if (!capable(CAP_IPC_LOCK)) + return -EPERM; + + shp = shm_lock(shmid); + if(shp==NULL) + return -EINVAL; + err = shm_checkid(shp,shmid); + if(err) + goto out_unlock; + if(cmd==SHM_LOCK) { + shmem_lock(shp->shm_file, 1); + shp->shm_flags |= SHM_LOCKED; + } else { + shmem_lock(shp->shm_file, 0); + shp->shm_flags &= ~SHM_LOCKED; + } + shm_unlock(shmid); + return err; + } + case IPC_RMID: + { + /* + * We cannot simply remove the file. The SVID states + * that the block remains until the last person + * detaches from it, then is deleted. A shmat() on + * an RMID segment is legal in older Linux and if + * we change it apps break... + * + * Instead we set a destroyed flag, and then blow + * the name away when the usage hits zero. + */ +#ifdef CONFIG_MOSIX + /* mosix_rebuild_file_list(); fh leakage fixed - moshe */ +#endif + down(&shm_ids.sem); + shp = shm_lock(shmid); + err = -EINVAL; + if (shp == NULL) + goto out_up; + err = shm_checkid(shp, shmid); + if(err) + goto out_unlock_up; + if (current->euid != shp->shm_perm.uid && + current->euid != shp->shm_perm.cuid && + !capable(CAP_SYS_ADMIN)) { + err=-EPERM; + goto out_unlock_up; + } + if (shp->shm_nattch){ + shp->shm_flags |= SHM_DEST; + /* Do not find it any more */ + shp->shm_perm.key = IPC_PRIVATE; + shm_unlock(shmid); + } else + shm_destroy (shp); + up(&shm_ids.sem); + return err; + } + + case IPC_SET: + { + if(copy_shmid_from_user (&setbuf, buf, version)) + return -EFAULT; + down(&shm_ids.sem); + shp = shm_lock(shmid); + err=-EINVAL; + if(shp==NULL) + goto out_up; + err = shm_checkid(shp,shmid); + if(err) + goto out_unlock_up; + err=-EPERM; + if (current->euid != shp->shm_perm.uid && + current->euid != shp->shm_perm.cuid && + !capable(CAP_SYS_ADMIN)) { + goto out_unlock_up; + } + + shp->shm_perm.uid = setbuf.uid; + shp->shm_perm.gid = setbuf.gid; + shp->shm_flags = (shp->shm_flags & ~S_IRWXUGO) + | (setbuf.mode & S_IRWXUGO); + shp->shm_ctim = CURRENT_TIME; + break; + } + + default: + return -EINVAL; + } + + err = 0; +out_unlock_up: + shm_unlock(shmid); +out_up: + up(&shm_ids.sem); + return err; +out_unlock: + shm_unlock(shmid); + return err; +} + +/* + * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists. + */ +asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) +{ + struct shmid_kernel *shp; + unsigned long addr; + unsigned long size; + struct file * file; + int err; + unsigned long flags; + unsigned long prot; + unsigned long o_flags; + int acc_mode; + void *user_addr; + + if (shmid < 0) + return -EINVAL; + + if ((addr = (ulong)shmaddr)) { + if (addr & (SHMLBA-1)) { + if (shmflg & SHM_RND) + addr &= ~(SHMLBA-1); /* round down */ + else + return -EINVAL; + } + flags = MAP_SHARED | MAP_FIXED; + } else { + if ((shmflg & SHM_REMAP)) + return -EINVAL; + + flags = MAP_SHARED; + } + + if (shmflg & SHM_RDONLY) { + prot = PROT_READ; + o_flags = O_RDONLY; + acc_mode = S_IRUGO; + } else { + prot = PROT_READ | PROT_WRITE; + o_flags = O_RDWR; + acc_mode = S_IRUGO | S_IWUGO; + } + + /* + * We cannot rely on the fs check since SYSV IPC does have an + * additional creator id... + */ + shp = shm_lock(shmid); + if(shp == NULL) + return -EINVAL; + err = shm_checkid(shp,shmid); + if (err) { + shm_unlock(shmid); + return err; + } + if (ipcperms(&shp->shm_perm, acc_mode)) { + shm_unlock(shmid); + return -EACCES; + } + file = shp->shm_file; + size = file->f_dentry->d_inode->i_size; + shp->shm_nattch++; + shm_unlock(shmid); + +#ifdef CONFIG_MOSIX + user_addr = (void *) do_mmap_down (file, addr, size, prot, flags, 0); +#else + down_write(¤t->mm->mmap_sem); + if (addr && !(shmflg & SHM_REMAP)) { + user_addr = ERR_PTR(-EINVAL); + if (find_vma_intersection(current->mm, addr, addr + size)) + goto invalid; + /* + * If shm segment goes below stack, make sure there is some + * space left for the stack to grow (at least 4 pages). + */ + if (addr < current->mm->start_stack && + addr > current->mm->start_stack - size - PAGE_SIZE * 5) + goto invalid; + } + + user_addr = (void*) do_mmap (file, addr, size, prot, flags, 0); + +invalid: + up_write(¤t->mm->mmap_sem); +#endif /* CONFIG_MOSIX */ + + down (&shm_ids.sem); + if(!(shp = shm_lock(shmid))) + BUG(); + shp->shm_nattch--; + if(shp->shm_nattch == 0 && + shp->shm_flags & SHM_DEST) + shm_destroy (shp); + else + shm_unlock(shmid); + up (&shm_ids.sem); + + *raddr = (unsigned long) user_addr; + err = 0; + if (IS_ERR(user_addr)) + err = PTR_ERR(user_addr); + return err; + +} + +/* + * detach and kill segment if marked destroyed. + * The work is done in shm_close. + */ +asmlinkage long sys_shmdt (char *shmaddr) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *shmd, *shmdnext; + int retval = -EINVAL; + + down_write(&mm->mmap_sem); + for (shmd = mm->mmap; shmd; shmd = shmdnext) { + shmdnext = shmd->vm_next; + if (shmd->vm_ops == &shm_vm_ops + && shmd->vm_start - (shmd->vm_pgoff << PAGE_SHIFT) == (ulong) shmaddr) { +#ifdef CONFIG_MOSIX + if(current->mosix.dflags & DDEPUTY) + deputy_munmap(shmd->vm_start,shmd->vm_end - shmd->vm_start); + else +#endif /* CONFIG_MOSIX */ + do_munmap(mm, shmd->vm_start, shmd->vm_end - shmd->vm_start); + retval = 0; + } + } + up_write(&mm->mmap_sem); + return retval; +} + +#ifdef CONFIG_PROC_FS +static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data) +{ + off_t pos = 0; + off_t begin = 0; + int i, len = 0; + + down(&shm_ids.sem); + len += sprintf(buffer, " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n"); + + for(i = 0; i <= shm_ids.max_id; i++) { + struct shmid_kernel* shp; + + shp = shm_lock(i); + if(shp!=NULL) { +#define SMALL_STRING "%10d %10d %4o %10u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n" +#define BIG_STRING "%10d %10d %4o %21u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n" + char *format; + + if (sizeof(size_t) <= sizeof(int)) + format = SMALL_STRING; + else + format = BIG_STRING; + len += sprintf(buffer + len, format, + shp->shm_perm.key, + shm_buildid(i, shp->shm_perm.seq), + shp->shm_flags, + shp->shm_segsz, + shp->shm_cprid, + shp->shm_lprid, + shp->shm_nattch, + shp->shm_perm.uid, + shp->shm_perm.gid, + shp->shm_perm.cuid, + shp->shm_perm.cgid, + shp->shm_atim, + shp->shm_dtim, + shp->shm_ctim); + shm_unlock(i); + + pos += len; + if(pos < offset) { + len = 0; + begin = pos; + } + if(pos > offset + length) + goto done; + } + } + *eof = 1; +done: + up(&shm_ids.sem); + *start = buffer + (offset - begin); + len -= (offset - begin); + if(len > length) + len = length; + if(len < 0) + len = 0; + return len; +} +#endif diff -Naur linux-2.4.26-om1/kernel/fork.c linux-2.4.26-om1-o/kernel/fork.c --- linux-2.4.26-om1/kernel/fork.c 2006-05-08 15:02:38.000000000 +0530 +++ linux-2.4.26-om1-o/kernel/fork.c 2006-05-07 17:56:02.000000000 +0530 @@ -32,6 +32,7 @@ #ifdef CONFIG_MOSIX #include <linux/hpc.h> +#include<hpc/mig_shm.h> #endif /* CONFIG_MOSIX */ /* The idle threads do not count.. */ @@ -1014,6 +1015,11 @@ /* SLAB cache for mm_struct structures (tsk->mm) */ kmem_cache_t *mm_cachep; +kmem_cache_t *shm_pgentry_cachep; + +#ifdef CONFIG_MOSIX +kmem_cache_t *shm_page_cachep; +#endif /* CONFIG_MOSIX */ void __init proc_caches_init(void) { @@ -1046,4 +1052,15 @@ SLAB_HWCACHE_ALIGN, NULL, NULL); if(!mm_cachep) panic("vma_init: Cannot alloc mm_struct SLAB cache"); + +#ifdef CONFIG_MOSIX + + shm_page_cachep = kmem_cache_create("shm_page", + sizeof(struct shm_page), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if(!shm_page_cachep) + panic("Cannot alloc shm_page SLAB cache"); + +#endif /* CONFIG_MOSIX */ + } diff -Naur linux-2.4.26-om1/mm/filemap.c linux-2.4.26-om1-o/mm/filemap.c --- linux-2.4.26-om1/mm/filemap.c 2006-05-08 15:02:38.000000000 +0530 +++ linux-2.4.26-om1-o/mm/filemap.c 2006-05-07 17:56:02.000000000 +0530 @@ -32,6 +32,8 @@ #ifdef CONFIG_MOSIX #include <linux/hpc.h> +#include <hpc/mig_shm.h> +#include <hpc/shm_pagemap.h> #endif /* CONFIG_MOSIX */ #ifdef CONFIG_MOSIX_DFSA #include <linux/dfsa_interface.h> @@ -764,8 +766,8 @@ * This adds the requested page to the page cache if it isn't already there, * and schedules an I/O to read in its contents from disk. */ -static int FASTCALL(page_cache_read(struct file * file, unsigned long offset)); -static int page_cache_read(struct file * file, unsigned long offset) +static int FASTCALL(page_cache_read(struct file * file, unsigned long offset,unsigned long unused)); +static int page_cache_read(struct file * file, unsigned long offset,unsigned long unused) { struct address_space *mapping = file->f_dentry->d_inode->i_mapping; struct page **hash = page_hash(mapping, offset); @@ -782,6 +784,12 @@ return -ENOMEM; if (!add_to_page_cache_unique(page, mapping, offset, hash)) { +#ifdef CONFIG_MOSIX + if(current->mosix.dflags & DREMOTE) { + page->shm_page = find_get_shm_page(mapping,offset,shm_page_hash(mapping,offset)); + (page->shm_page)->state |= unused; + } +#endif /* CONFIG_MOSIX */ int error = mapping->a_ops->readpage(file, page); page_cache_release(page); return error; @@ -807,7 +815,7 @@ offset = CLUSTER_OFFSET(offset); while ((pages-- > 0) && (offset < filesize)) { - int error = page_cache_read(file, offset); + int error = page_cache_read(file, offset,0); if (error < 0) return error; offset ++; @@ -1359,7 +1367,7 @@ if (ra_index >= end_index) break; - if (page_cache_read(filp, ra_index) < 0) + if (page_cache_read(filp, ra_index,0) < 0) break; ahead++; @@ -1985,7 +1993,7 @@ nr = max; while (nr) { - page_cache_read(file, index); + page_cache_read(file, index,0); index++; nr--; } @@ -2081,23 +2089,20 @@ struct inode *inode = mapping->host; struct page *page, **hash; unsigned long size, pgoff, endoff; - pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff; endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff; - + retry_all: /* * An external ptracer can access pages that normally aren't * accessible.. */ size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - if ((pgoff >= size) && (area->vm_mm == current->mm)) + if ((area->vm_mm == current->mm) && (pgoff >= size)) return NULL; - /* The "size" of the file, as far as mmap is concerned, isn't bigger than the mapping */ if (size > endoff) size = endoff; - /* * Do we have something in the page cache already? */ @@ -2111,22 +2116,29 @@ * Ok, found a page in the page cache, now we need to check * that it's up-to-date. */ - if (!Page_Uptodate(page)) + + + if (!Page_Uptodate(page)) goto page_not_uptodate; + success: /* * Try read-ahead for sequential areas. */ - if (VM_SequentialReadHint(area)) - nopage_sequential_readahead(area, pgoff, size); - + if(!(current->mosix.dflags&DREMOTE)) { + if (VM_SequentialReadHint(area)) + nopage_sequential_readahead(area, pgoff, size); + } /* * Found the page and have a reference on it, need to check sharing * and possibly copy it over to another page.. */ mark_page_accessed(page); flush_page_to_ram(page); + + + return page; no_cached_page: @@ -2137,17 +2149,17 @@ * Otherwise, we're off the end of a privately mapped file, * so we need to map a zero page. */ - if ((pgoff < size) && !VM_RandomReadHint(area)) + if ((pgoff < size) && !VM_RandomReadHint(area)&&!(current->mosix.dflags&DREMOTE)) error = read_cluster_nonblocking(file, pgoff, size); else - error = page_cache_read(file, pgoff); + error = page_cache_read(file, pgoff,unused); /* * The page we want has now been added to the page cache. * In the unlikely event that someone removed it in the * meantime, we'll just come back here and read it again. */ - if (error >= 0) + if (error >= 0) goto retry_find; /* @@ -2155,11 +2167,19 @@ * system is low on memory, or a problem occurs while trying * to schedule I/O. */ + +#ifdef CONFIG_MOSIX + if(error == -EBUSY) + return PAGE_BUSY; +#endif /* CONFIG_MOSIX */ + if (error == -ENOMEM) return NOPAGE_OOM; return NULL; page_not_uptodate: + + lock_page(page); /* Did it get unhashed while we waited for it? */ @@ -2174,12 +2194,35 @@ UnlockPage(page); goto success; } +#ifdef CONFIG_MOSIX + if(current->mosix.dflags & DREMOTE) { + page->shm_page = find_get_shm_page(mapping,pgoff,shm_page_hash(mapping,pgoff)); + (page->shm_page)->state |= unused; + } +#endif /* CONFIG_MOSIX */ - if (!mapping->a_ops->readpage(file, page)) { + if (!(error = mapping->a_ops->readpage(file, page))) { wait_on_page(page); if (Page_Uptodate(page)) goto success; +#ifdef CONFIG_MOSIX + else if(current->mosix.dflags & DREMOTE) { + page_cache_release(page); + return PAGE_BUSY; + } +#endif /* CONFIG_MOSIX */ + } +#ifdef CONFIG_MOSIX + else if(current->mosix.dflags & DREMOTE) { + page_cache_release(page); + if(error == -EBUSY) + return PAGE_BUSY; + else if(error == -ENOMEM) + return NOPAGE_OOM; + else + return NULL; } +#endif /* CONFIG_MOSIX */ /* * Umm, take care of errors if the page isn't up-to-date. @@ -2187,6 +2230,7 @@ * because there really aren't any performance issues here * and we need to check for errors. */ + lock_page(page); /* Somebody truncated the page on us? */ @@ -2202,11 +2246,12 @@ goto success; } ClearPageError(page); - if (!mapping->a_ops->readpage(file, page)) { + + if (!(mapping->a_ops->readpage(file, page))) { wait_on_page(page); if (Page_Uptodate(page)) goto success; - } + } /* * Things didn't work out. Return zero to tell the @@ -2643,7 +2688,7 @@ } } else { while ((start < end) && (start < size)) { - error = page_cache_read(file, start); + error = page_cache_read(file, start,0); start++; if (error < 0) break; @@ -2754,6 +2799,9 @@ int unmapped_error = 0; int error = -EINVAL; + if(current->mosix.dflags & DREMOTE) + return 0; + down_write(¤t->mm->mmap_sem); if (start & ~PAGE_MASK) @@ -3423,10 +3471,32 @@ page_hash_table = (struct page **) __get_free_pages(GFP_ATOMIC, order); } while(page_hash_table == NULL && --order > 0); + + htable_size = mempages; + htable_size *= sizeof(struct shm_page *); + for(order = 0; (PAGE_SIZE << order) < htable_size; order++) + ; + + do { + unsigned long tmp = (PAGE_SIZE << order) / sizeof(struct page *); + + shm_page_hash_bits = 0; + while((tmp >>= 1UL) != 0UL) + shm_page_hash_bits++; + + shm_page_hash_table = (struct shm_page **) + __get_free_pages(GFP_ATOMIC, order); + } while(shm_page_hash_table == NULL && --order > 0); + printk("Page-cache hash table entries: %d (order: %ld, %ld bytes)\n", (1 << page_hash_bits), order, (PAGE_SIZE << order)); if (!page_hash_table) panic("Failed to allocate page hash table\n"); memset((void *)page_hash_table, 0, PAGE_HASH_SIZE * sizeof(struct page *)); + + if (!shm_page_hash_table) + panic("Failed to allocate page hash table\n"); + memset((void *)shm_page_hash_table, 0, SHM_PAGE_HASH_SIZE * sizeof(struct shm_page *)); + } diff -Naur linux-2.4.26-om1/mm/memory.c linux-2.4.26-om1-o/mm/memory.c --- linux-2.4.26-om1/mm/memory.c 2006-05-08 15:02:38.000000000 +0530 +++ linux-2.4.26-om1-o/mm/memory.c 2006-05-07 17:56:02.000000000 +0530 @@ -52,6 +52,8 @@ #ifdef CONFIG_MOSIX #include <linux/hpc.h> +#include <hpc/mig_shm.h> +#include <hpc/shm_pagemap.h> #endif /* CONFIG_MOSIX */ unsigned long max_mapnr; @@ -991,12 +993,46 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, unsigned long address, pte_t *page_table, pte_t pte) { - struct page *old_page, *new_page; + struct page *old_page,*new_page; + struct shm_page *shm_page = NULL; old_page = pte_page(pte); if (!VALID_PAGE(old_page)) goto bad_wp_page; +#ifdef CONFIG_MOSIX + if(vma->vm_flags & VM_SHARED) { + + spin_unlock(&mm->page_table_lock); + + + new_page = get_nopage(vma,address,&shm_page,11); + + + if(shm_page->state & PERM_ERR) { + shm_pagecache_release(shm_page); + return -1; + } + + spin_lock(&shm_page->shm_lock); + + spin_lock(&mm->page_table_lock); + if (pte_same(*page_table, pte) && ( shm_page->owner ==0 || shm_page->owner == PE) && + ((shm_page->state & STATE_MASK) == EXCLUSIVE) ) + break_cow(vma,old_page,address,page_table); + + spin_unlock(&mm->page_table_lock); + spin_unlock(&shm_page->shm_lock); + + shm_pagecache_release(shm_page); + + if(new_page) + page_cache_release(new_page); + + return 1; + } +#endif /* CONFIG_MOSIX */ + if (!TryLockPage(old_page)) { int reuse = can_share_swap_page(old_page); unlock_page(old_page); @@ -1318,32 +1354,47 @@ { struct page * new_page; pte_t entry; +#ifdef CONFIG_MOSIX + struct shm_page *shm_page = NULL; + int ret = 2; +#endif /* CONFIG_MOSIX */ if (!vma->vm_ops || !vma->vm_ops->nopage) return do_anonymous_page(mm, vma, page_table, write_access, address); + spin_unlock(&mm->page_table_lock); - new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, 0); +#ifdef CONFIG_MOSIX + new_page = get_nopage(vma, address&PAGE_MASK, &shm_page, + (!write_access || (vma->vm_flags & VM_SHARED)) ? (!(! write_access)) : 2 ); +#else /* CONFIG_MOSIX */ + new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, 0); +#endif /* CONFIG_MOSIX */ + if (new_page == NULL) /* no page was available -- SIGBUS */ return 0; + if (new_page == NOPAGE_OOM) return -1; - /* - * Should we do an early C-O-W break? - */ if (write_access && !(vma->vm_flags & VM_SHARED)) { - struct page * page = alloc_page(GFP_HIGHUSER); - if (!page) { - page_cache_release(new_page); - return -1; - } - copy_user_highpage(page, new_page, address); - page_cache_release(new_page); - lru_cache_add(page); - new_page = page; - } + struct page * page = alloc_page(GFP_HIGHUSER); + if (!page) { + page_cache_release(new_page); + return -1; + } + copy_user_highpage(page, new_page, address); + page_cache_release(new_page); + lru_cache_add(page); + new_page = page; + } + + +#ifdef CONFIG_MOSIX + if(shm_page) + spin_lock(&(shm_page->shm_lock)); +#endif /* CONFIG_MOSIX */ spin_lock(&mm->page_table_lock); /* @@ -1357,26 +1408,59 @@ * handle that later. */ /* Only go through if we didn't race with anybody else... */ + + +#ifdef CONFIG_MOSIX + if (pte_none(*page_table) && + ((!shm_page) || (((shm_page->state & STATE_MASK) == EXCLUSIVE && (shm_page->owner == 0 || shm_page->owner == PE)) || + (!write_access && (shm_page->state & STATE_MASK) == SHARED))) ) { +#else if (pte_none(*page_table)) { +#endif /* CONFIG_MOSIX */ + + if (!PageReserved(new_page)) ++mm->rss; flush_page_to_ram(new_page); flush_icache_page(vma, new_page); entry = mk_pte(new_page, vma->vm_page_prot); - if (write_access) + if (write_access) entry = pte_mkwrite(pte_mkdirty(entry)); +#ifdef CONFIG_MOSIX + else + entry = pte_wrprotect(entry); +#endif /* CONFIG_MOSIX */ + set_pte(page_table, entry); +#ifdef CONFIG_MOSIX + update_mmu_cache(vma,address,entry); +#endif /* CONFIG_MOSIX */ } else { /* One of our sibling threads was faster, back out. */ page_cache_release(new_page); +#ifdef CONFIG_MOSIX + ret = 1; +#else spin_unlock(&mm->page_table_lock); - return 1; + return 1; +#endif /* CONFIG_MOSIX */ + } +#ifdef CONFIG_MOSIX - /* no need to invalidate: a not-present page shouldn't be cached */ + spin_unlock(&mm->page_table_lock); + + if(shm_page) { + spin_unlock(&(shm_page->shm_lock)); + shm_pagecache_release(shm_page); + } + + return ret; /* Major fault */ +#else update_mmu_cache(vma, address, entry); - spin_unlock(&mm->page_table_lock); - return 2; /* Major fault */ + spin_unlock(&mm->page_table_lock); + return 2; /* Major fault */ +#endif /* CONFIG_MOSIX */ } /* diff -Naur linux-2.4.26-om1/mm/mmap.c linux-2.4.26-om1-o/mm/mmap.c --- linux-2.4.26-om1/mm/mmap.c 2006-05-08 15:02:38.000000000 +0530 +++ linux-2.4.26-om1-o/mm/mmap.c 2006-05-07 17:56:02.000000000 +0530 @@ -27,6 +27,7 @@ #ifdef CONFIG_MOSIX #include <linux/hpc.h> +extern struct page *shm_nopage(struct vm_area_struct *vma, unsigned long address, int unused); #endif /* CONFIG_MOSIX */ #ifdef CONFIG_MOSIX_DFSA #include <linux/dfsa_interface.h> @@ -108,26 +109,11 @@ if (file) { struct inode *inode = file->f_dentry->d_inode; -#ifdef CONFIG_MOSIX - int was_shared = (inode->i_mapping->i_mmap_shared != NULL); -#endif /* CONFIG_MOSIX */ if (vma->vm_flags & VM_DENYWRITE) atomic_inc(&inode->i_writecount); if(vma->vm_next_share) vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share; *vma->vm_pprev_share = vma->vm_next_share; -#ifdef CONFIG_MOSIX - if(was_shared && !inode->i_mapping->i_mmap_shared) - mosix_no_longer_monkey(inode); - if(current->mosix.dflags & DREMOTE) - { - spin_lock_irq(¤t->sigmask_lock); - current->mosix.asig |= (1 << (REMOTE_FILE_RELEASED-1)); - spin_unlock_irq(¤t->sigmask_lock); - } - else - tell_process(current, DREQ_FILEUNMAP); -#endif /* CONFIG_MOSIX */ } #ifdef CONFIG_MOSIX if(current->mosix.stay & DSTAY_PER_MM) @@ -190,13 +176,6 @@ if (brk <= mm->brk) { if (!do_munmap(mm, newbrk, oldbrk-newbrk)) goto set_brk; -#ifdef CONFIG_MOSIX - if(process_told(current, DREQ_FILEUNMAP)) - { - process_ack(current, DREQ_FILEUNMAP); - mosix_rebuild_file_list(); - } -#endif /* CONFIG_MOSIX */ goto out; } @@ -508,35 +487,29 @@ if (file) { switch (flags & MAP_TYPE) { case MAP_SHARED: - if ((prot & PROT_WRITE) && !(file->f_mode & FMODE_WRITE)) + if ((prot & PROT_WRITE) && !(file->f_mode & FMODE_WRITE)) return -EACCES; /* Make sure we don't allow writing to an append-only file.. */ - if (IS_APPEND(file->f_dentry->d_inode) && (file->f_mode & FMODE_WRITE)) + if (IS_APPEND(file->f_dentry->d_inode) && (file->f_mode & FMODE_WRITE)) return -EACCES; /* make sure there are no mandatory locks on the file. */ - if (locks_verify_locked(file->f_dentry->d_inode)) + if (locks_verify_locked(file->f_dentry->d_inode)) return -EAGAIN; vm_flags |= VM_SHARED | VM_MAYSHARE; if (!(file->f_mode & FMODE_WRITE)) vm_flags &= ~(VM_MAYWRITE | VM_SHARED); -#ifdef CONFIG_MOSIX - if(file->f_mode & FMODE_WRITE) - reason_to_come_back |= DSTAY_FOR_MONKEY; -#endif /* CONFIG_MOSIX */ /* fall through */ case MAP_PRIVATE: #ifdef CONFIG_MOSIX - if(file->f_dentry->d_inode->i_mapping->i_mmap_shared) - reason_to_come_back |= DSTAY_FOR_MONKEY; if(S_ISCHR(file->f_dentry->d_inode->i_mode)) reason_to_come_back |= DSTAY_FOR_DEV; if (!(current->mosix.dflags & DINCOMING)) #endif /* CONFIG_MOSIX */ - if (!(file->f_mode & FMODE_READ)) + if (!(file->f_mode & FMODE_READ)) return -EACCES; break; @@ -574,20 +547,14 @@ munmap_back: vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); if (vma && vma->vm_start < addr + len) { - if (do_munmap(mm, addr, len)) + if (do_munmap(mm, addr, len)) return -ENOMEM; -#ifdef CONFIG_MOSIX - if(process_told(current, DREQ_FILEUNMAP)) { - process_ack(current, DREQ_FILEUNMAP); - mosix_rebuild_file_list(); - } -#endif /* CONFIG_MOSIX */ goto munmap_back; } /* Check against address space limit. */ if ((mm->total_vm << PAGE_SHIFT) + len - > current->rlim[RLIMIT_AS].rlim_cur) + > current->rlim[RLIMIT_AS].rlim_cur) return -ENOMEM; /* Private writable mapping? Check memory availability.. */ @@ -627,18 +594,14 @@ vma->vm_raend = 0; #ifdef CONFIG_MOSIX - if(file && !(current->mosix.dflags & DREMOTE) && (registration_result = - mosix_register_a_file(file, (flags & MAP_DENYWRITE) != 0)) < 0) - { - error = registration_result; - goto free_vma; - } + + /* * even if we don't end up mapping locally, perform a dummy mapping, * only to check for fs-specific errors, so we do not fail if and when * we ever come home: */ - if(MMAP_REMOTELY) + if(MMAP_REMOTELY && (file || !(flags&MAP_SHARED))) { vma->vm_file = file; if(file && (error = file->f_op->mmap(file, vma))) @@ -647,10 +610,20 @@ * (perhaps we were mapping /proc/nnnn/mem)? */ if(!MMAP_REMOTELY) goto again_locally_with_vma; + + if(file) + get_file(file); + +GO_HERE: addr = mosix_deputy_mmap(file, addr, (flags & MAP_FIXED) != 0, len, vma->vm_flags, pgoff, file ? file->f_dentry->d_inode->i_size : 0, - file ? vma->vm_ops->nopage : NULL); + file ? vma->vm_ops->nopage : NULL); + + + if(file) + fput(file); + if(IS_ERR((const void *)addr)) { error = addr; @@ -663,35 +636,41 @@ /* we did not really want that vma... only to check */ kmem_cache_free(vm_area_cachep, vma); /* meanwhile someone else could map the same file shared, so: */ - if(file && file->f_dentry->d_inode->i_mapping->i_mmap_shared) + /*if(file && file->f_dentry->d_inode->i_mapping->i_mmap_shared) { if(!mosix_go_home(0)) return(-EAGAIN); - stay_me_and_my_clones(DSTAY_FOR_MONKEY); - } + }*/ return(addr); } #endif /* CONFIG_MOSIX */ - if (file) { + if(file) { error = -EINVAL; - if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) + if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) goto free_vma; if (vm_flags & VM_DENYWRITE) { error = deny_write_access(file); - if (error) + if (error) goto free_vma; correct_wcount = 1; } vma->vm_file = file; get_file(file); error = file->f_op->mmap(file, vma); - if (error) + if (error) goto unmap_and_free_vma; } else if (flags & MAP_SHARED) { error = shmem_zero_setup(vma); if (error) goto free_vma; + file = vma->vm_file; + if(MMAP_REMOTELY) { + if(vma->vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) + BUG(); + vma->vm_flags &= ~(VM_GROWSDOWN|VM_GROWSUP|VM_DENYWRITE); + goto GO_HERE; + } } /* Can addr have changed?? @@ -737,9 +716,9 @@ #ifdef CONFIG_MOSIX if(reason_to_come_back) stay_me_and_my_clones(reason_to_come_back); - if(file && (vm_flags & VM_SHARED)) - mosix_bring_monkey_users_back(file->f_dentry->d_inode); + #endif /* CONFIG_MOSIX */ + return addr; unmap_and_free_vma: @@ -752,17 +731,10 @@ zap_page_range(mm, vma->vm_start, vma->vm_end - vma->vm_start); free_vma: kmem_cache_free(vm_area_cachep, vma); -#ifdef CONFIG_MOSIX - if(registration_result > 0) - mosix_undo_last_file_registration(file, registration_result); -#endif /* CONFIG_MOSIX */ return error; #ifdef CONFIG_MOSIX again_locally_with_vma: kmem_cache_free(vm_area_cachep, vma); - if(registration_result > 0) - mosix_undo_last_file_registration(file, registration_result); - registration_result = 0; again_locally: mm = current->mm; reason_to_come_back = 0; @@ -1200,13 +1172,6 @@ down_write(&mm->mmap_sem); ret = do_munmap(mm, addr, len); up_write(&mm->mmap_sem); -#ifdef CONFIG_MOSIX - if(process_told(current, DREQ_FILEUNMAP)) - { - process_ack(current, DREQ_FILEUNMAP); - mosix_rebuild_file_list(); - } -#endif /* CONFIG_MOSIX */ return ret; } diff -Naur linux-2.4.26-om1/mm/mremap.c linux-2.4.26-om1-o/mm/mremap.c --- linux-2.4.26-om1/mm/mremap.c 2006-05-08 15:02:38.000000000 +0530 +++ linux-2.4.26-om1-o/mm/mremap.c 2006-05-07 17:56:02.000000000 +0530 @@ -375,12 +375,5 @@ down_write(¤t->mm->mmap_sem); ret = do_mremap(addr, old_len, new_len, flags, new_addr); up_write(¤t->mm->mmap_sem); -#ifdef CONFIG_MOSIX - if(process_told(current, DREQ_FILEUNMAP)) - { - process_ack(current, DREQ_FILEUNMAP); - mosix_rebuild_file_list(); - } -#endif /* CONFIG_MOSIX */ return ret; } diff -Naur linux-2.4.26-om1/mm/vmscan.c linux-2.4.26-om1-o/mm/vmscan.c --- linux-2.4.26-om1/mm/vmscan.c 2006-05-08 15:02:38.000000000 +0530 +++ linux-2.4.26-om1-o/mm/vmscan.c 2006-05-07 17:56:02.000000000 +0530 @@ -25,6 +25,8 @@ #include <linux/file.h> #include <asm/pgalloc.h> +#include <hpc/mig_shm.h> +#include <hpc/shm_pagemap.h> /* * "vm_passes" is the number of vm passes before failing the @@ -680,6 +682,25 @@ zonelist_t *zonelist; unsigned long pf_free_pages; int error = 0; + struct list_head *entry; + +#ifdef CONFIG_MOSIX + +again: spin_lock(&shm_pagecache_lock); + + entry = shm_page_unused_list.prev; + if(entry != &shm_page_unused_list) { + struct shm_page *shm_page; + shm_page = list_entry(entry,struct shm_page,list); + list_del(&shm_page->list); + spin_unlock(&shm_pagecache_lock); + kmem_cache_free(shm_page_cachep,shm_page); + goto again; + } + + spin_unlock(&shm_pagecache_lock); + +#endif /* CONFIG_MOSIX */ pf_free_pages = current->flags & PF_FREE_PAGES; current->flags &= ~PF_FREE_PAGES; -Ratna Manoj Bolla. M.Tech 2nd year. CSE dept. IIT-Guwahati,INDIA. ------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642