diff -u --recursive v1.1.32/linux/Makefile linux/Makefile --- v1.1.32/linux/Makefile Thu Jul 21 08:18:00 1994 +++ linux/Makefile Thu Jul 21 10:37:39 1994 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 32 +SUBLEVEL = 33 all: Version zImage diff -u --recursive v1.1.32/linux/drivers/block/cdu31a.c linux/drivers/block/cdu31a.c --- v1.1.32/linux/drivers/block/cdu31a.c Thu Jul 14 00:48:20 1994 +++ linux/drivers/block/cdu31a.c Wed Jul 20 23:13:28 1994 @@ -1772,6 +1772,9 @@ int num_spin_ups; + if (filp->f_mode & 2) + return -EACCES; + if (!sony_spun_up) { num_spin_ups = 0; diff -u --recursive v1.1.32/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v1.1.32/linux/drivers/block/hd.c Thu Jul 21 08:18:02 1994 +++ linux/drivers/block/hd.c Thu Jul 21 07:38:40 1994 @@ -218,12 +218,12 @@ } static void hd_request (void); -unsigned int identified [MAX_HD] = {0,}; /* 1 = drive ID already displayed */ -unsigned int unmask_intr [MAX_HD] = {0,}; /* 1 = unmask IRQs during I/O */ -unsigned int max_mult [MAX_HD] = {0,}; /* max sectors for MultMode */ -unsigned int mult_req [MAX_HD] = {0,}; /* requested MultMode count */ -unsigned int mult_count [MAX_HD] = {0,}; /* currently enabled MultMode count */ -struct request WCURRENT; +static unsigned int identified [MAX_HD] = {0,}; /* 1 = drive ID already displayed */ +static unsigned int unmask_intr [MAX_HD] = {0,}; /* 1 = unmask IRQs during I/O */ +static unsigned int max_mult [MAX_HD] = {0,}; /* max sectors for MultMode */ +static unsigned int mult_req [MAX_HD] = {0,}; /* requested MultMode count */ +static unsigned int mult_count [MAX_HD] = {0,}; /* currently enabled MultMode count */ +static struct request WCURRENT; static void rawstring (char *prefix, char *s, int n) { diff -u --recursive v1.1.32/linux/drivers/block/mcd.c linux/drivers/block/mcd.c --- v1.1.32/linux/drivers/block/mcd.c Sat Jul 9 16:30:45 1994 +++ linux/drivers/block/mcd.c Wed Jul 20 23:13:28 1994 @@ -1029,6 +1029,9 @@ if (mcdPresent == 0) return -ENXIO; /* no hardware */ + + if (fp->f_mode & 2) /* write access? */ + return -EACCES; if (!mcd_open_count && mcd_state == MCD_S_IDLE) { diff -u --recursive v1.1.32/linux/drivers/block/sbpcd.c linux/drivers/block/sbpcd.c --- v1.1.32/linux/drivers/block/sbpcd.c Sat Jul 16 19:51:21 1994 +++ linux/drivers/block/sbpcd.c Wed Jul 20 23:13:28 1994 @@ -3211,6 +3211,9 @@ if (ndrives==0) return (-ENXIO); /* no hardware */ + if (fp->f_mode & 2) + return -EACCES; + i = MINOR(ip->i_rdev); if ( (i<0) || (i>=NR_SBPCD) ) { diff -u --recursive v1.1.32/linux/drivers/char/console.c linux/drivers/char/console.c --- v1.1.32/linux/drivers/char/console.c Thu Jul 21 08:18:04 1994 +++ linux/drivers/char/console.c Thu Jul 21 14:06:28 1994 @@ -35,6 +35,9 @@ * Code to check for different video-cards mostly by Galen Hunt, * * + * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94 + * + * */ #define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */ @@ -80,7 +83,7 @@ #include /* Routines for selection control. */ -int set_selection(const int arg); +int set_selection(const int arg, struct tty_struct *tty); int paste_selection(struct tty_struct *tty); static void clear_selection(void); static void highlight_pointer(const int currcons, const int where); @@ -153,6 +156,7 @@ /* misc */ unsigned long vc_ques : 1; unsigned long vc_need_wrap : 1; + unsigned long vc_report_mouse : 1; unsigned long vc_tab_stop[5]; /* Tab stops. 160 columns. */ unsigned char * vc_translate; unsigned char * vc_G0_charset; @@ -196,6 +200,7 @@ #define deccm (vc_cons[currcons].vc_deccm) #define decim (vc_cons[currcons].vc_decim) #define need_wrap (vc_cons[currcons].vc_need_wrap) +#define report_mouse (vc_cons[currcons].vc_report_mouse) #define color (vc_cons[currcons].vc_color) #define s_color (vc_cons[currcons].vc_s_color) #define def_color (vc_cons[currcons].vc_def_color) @@ -775,6 +780,16 @@ respond_string(buf, tty); } +static void mouse_report(int currcons, struct tty_struct * tty, + int butt, int mrx, int mry) +{ + char buf[8]; + + sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx), + (char)('!' + mry)); + respond_string(buf, tty); +} + static inline void status_report(int currcons, struct tty_struct * tty) { respond_string("\033[0n", tty); /* Terminal ok */ @@ -832,6 +847,9 @@ else clr_kbd(decarm); break; + case 9: + report_mouse = on_off; + break; case 25: /* Cursor on/off */ deccm = on_off; set_cursor(currcons); @@ -1001,6 +1019,7 @@ G1_charset = GRAF_TRANS; charset = 0; need_wrap = 0; + report_mouse = 0; disp_ctrl = 0; toggle_meta = 0; @@ -1838,8 +1857,16 @@ return (v < l) ? l : ((v > u) ? u : v); } +/* invoked via ioctl(TIOCLINUX) */ +int mouse_reporting_p(void) +{ + int currcons = fg_console; + + return ((report_mouse) ? 0 : -EINVAL); +} + /* set the current selection. Invoked by ioctl(). */ -int set_selection(const int arg) +int set_selection(const int arg, struct tty_struct *tty) { unsigned short *args, xs, ys, xe, ye; int currcons = fg_console; @@ -1862,6 +1889,11 @@ ye = limit(ye, 0, video_num_lines - 1); ps = ys * video_size_row + (xs << 1); pe = ye * video_size_row + (xe << 1); + + if (report_mouse && (sel_mode & 16)) { + mouse_report(currcons, tty, sel_mode & 15, xs, ys); + return 0; + } if (ps > pe) /* make sel_start <= sel_end */ { diff -u --recursive v1.1.32/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v1.1.32/linux/drivers/char/tty_io.c Thu Jul 21 08:18:07 1994 +++ linux/drivers/char/tty_io.c Thu Jul 21 12:38:29 1994 @@ -66,9 +66,10 @@ #undef TTY_DEBUG_HANGUP #ifdef CONFIG_SELECTION -extern int set_selection(const int arg); +extern int set_selection(const int arg, struct tty_struct *tty); extern int paste_selection(struct tty_struct *tty); extern int sel_loadlut(const int arg); +extern int mouse_reporting_p(void); extern int shift_state; #endif /* CONFIG_SELECTION */ extern int do_screendump(int arg); @@ -1381,7 +1382,7 @@ return do_get_ps_info(arg); #ifdef CONFIG_SELECTION case 2: - return set_selection(arg); + return set_selection(arg, tty); case 3: return paste_selection(tty); case 4: @@ -1392,6 +1393,8 @@ case 6: put_fs_byte(shift_state,arg); return 0; + case 7: + return mouse_reporting_p(); #endif /* CONFIG_SELECTION */ default: return -EINVAL; diff -u --recursive v1.1.32/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v1.1.32/linux/drivers/scsi/sr.c Tue Jul 19 10:18:54 1994 +++ linux/drivers/scsi/sr.c Wed Jul 20 23:13:27 1994 @@ -268,6 +268,9 @@ if(MINOR(inode->i_rdev) >= NR_SR || !scsi_CDs[MINOR(inode->i_rdev)].device) return -ENXIO; /* No such device */ + if (filp->f_mode & 2) + return -EACCES; + check_disk_change(inode->i_rdev); if(!scsi_CDs[MINOR(inode->i_rdev)].device->access_count++) diff -u --recursive v1.1.32/linux/fs/exec.c linux/fs/exec.c --- v1.1.32/linux/fs/exec.c Tue Jun 28 22:30:27 1994 +++ linux/fs/exec.c Thu Jul 21 10:51:35 1994 @@ -537,6 +537,8 @@ mpnt1 = mpnt->vm_next; if (mpnt->vm_ops && mpnt->vm_ops->close) mpnt->vm_ops->close(mpnt); + if (mpnt->vm_inode) + iput(mpnt->vm_inode); kfree(mpnt); mpnt = mpnt1; } diff -u --recursive v1.1.32/linux/fs/nfs/mmap.c linux/fs/nfs/mmap.c --- v1.1.32/linux/fs/nfs/mmap.c Tue Jul 19 10:19:13 1994 +++ linux/fs/nfs/mmap.c Thu Jul 21 10:11:39 1994 @@ -23,63 +23,11 @@ #include #include +/* + * Fill in the supplied page for mmap + */ static unsigned long nfs_file_mmap_nopage(struct vm_area_struct * area, - unsigned long address, unsigned long page, int error_code); - -extern void file_mmap_free(struct vm_area_struct * area); -extern int file_mmap_share(struct vm_area_struct * from, struct vm_area_struct * to, - unsigned long address); - -struct vm_operations_struct nfs_file_mmap = { - NULL, /* open */ - file_mmap_free, /* close */ - nfs_file_mmap_nopage, /* nopage */ - NULL, /* wppage */ - file_mmap_share, /* share */ - NULL, /* unmap */ -}; - - -/* This is used for a general mmap of a nfs file */ -int nfs_mmap(struct inode * inode, struct file * file, - unsigned long addr, size_t len, int prot, unsigned long off) -{ - struct vm_area_struct * mpnt; - - if (prot & PAGE_RW) /* only PAGE_COW or read-only supported now */ - return -EINVAL; - if (off & (inode->i_sb->s_blocksize - 1)) - return -EINVAL; - if (!inode->i_sb || !S_ISREG(inode->i_mode)) - return -EACCES; - if (!IS_RDONLY(inode)) { - inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - } - - mpnt = (struct vm_area_struct * ) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL); - if (!mpnt) - return -ENOMEM; - - unmap_page_range(addr, len); - mpnt->vm_task = current; - mpnt->vm_start = addr; - mpnt->vm_end = addr + len; - mpnt->vm_page_prot = prot; - mpnt->vm_flags = 0; - mpnt->vm_share = NULL; - mpnt->vm_inode = inode; - inode->i_count++; - mpnt->vm_offset = off; - mpnt->vm_ops = &nfs_file_mmap; - insert_vm_struct(current, mpnt); - merge_segments(current->mm->mmap, NULL, NULL); - return 0; -} - - -static unsigned long nfs_file_mmap_nopage(struct vm_area_struct * area, unsigned long address, - unsigned long page, int error_code) + unsigned long address, unsigned long page, int error_code) { struct inode * inode = area->vm_inode; unsigned int clear; @@ -125,4 +73,50 @@ *(char *)--tmp = 0; } return page; +} +struct vm_operations_struct nfs_file_mmap = { + NULL, /* open */ + NULL, /* close */ + nfs_file_mmap_nopage, /* nopage */ + NULL, /* wppage */ + NULL, /* share */ + NULL, /* unmap */ +}; + + +/* This is used for a general mmap of a nfs file */ +int nfs_mmap(struct inode * inode, struct file * file, + unsigned long addr, size_t len, int prot, unsigned long off) +{ + struct vm_area_struct * mpnt; + + if (prot & PAGE_RW) /* only PAGE_COW or read-only supported now */ + return -EINVAL; + if (off & (inode->i_sb->s_blocksize - 1)) + return -EINVAL; + if (!inode->i_sb || !S_ISREG(inode->i_mode)) + return -EACCES; + if (!IS_RDONLY(inode)) { + inode->i_atime = CURRENT_TIME; + inode->i_dirt = 1; + } + + mpnt = (struct vm_area_struct * ) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL); + if (!mpnt) + return -ENOMEM; + + unmap_page_range(addr, len); + mpnt->vm_task = current; + mpnt->vm_start = addr; + mpnt->vm_end = addr + len; + mpnt->vm_page_prot = prot; + mpnt->vm_flags = 0; + mpnt->vm_share = NULL; + mpnt->vm_inode = inode; + inode->i_count++; + mpnt->vm_offset = off; + mpnt->vm_ops = &nfs_file_mmap; + insert_vm_struct(current, mpnt); + merge_segments(current->mm->mmap, NULL, NULL); + return 0; } diff -u --recursive v1.1.32/linux/include/linux/mm.h linux/include/linux/mm.h --- v1.1.32/linux/include/linux/mm.h Thu Jul 21 08:18:19 1994 +++ linux/include/linux/mm.h Thu Jul 21 13:56:31 1994 @@ -61,6 +61,8 @@ unsigned long page); int (*share)(struct vm_area_struct * from, struct vm_area_struct * to, unsigned long address); int (*unmap)(struct vm_area_struct *area, unsigned long, size_t); + void (*swapout)(struct vm_area_struct *, unsigned long *); + unsigned long (*swapin)(struct vm_area_struct *, unsigned long); }; extern unsigned long __bad_page(void); @@ -167,7 +169,7 @@ extern void swap_free(unsigned long page_nr); extern unsigned long swap_duplicate(unsigned long page_nr); -extern void swap_in(unsigned long *table_ptr); +extern unsigned long swap_in(unsigned long entry); extern void si_swapinfo(struct sysinfo * val); extern void rw_swap_page(int rw, unsigned long nr, char * buf); @@ -222,5 +224,13 @@ /* vm_ops not present page codes */ #define SHM_SWP_TYPE 0x41 extern void shm_no_page (ulong *); + +/* swap cache stuff (in swap.c) */ +extern unsigned long * swap_cache; + +extern inline unsigned long in_swap_cache (unsigned long addr) +{ + return swap_cache[addr >> PAGE_SHIFT]; +} #endif diff -u --recursive v1.1.32/linux/include/linux/unistd.h linux/include/linux/unistd.h --- v1.1.32/linux/include/linux/unistd.h Tue Jun 21 14:16:25 1994 +++ linux/include/linux/unistd.h Thu Jul 21 08:24:30 1994 @@ -143,6 +143,7 @@ #define __NR_bdflush 134 #define __NR_sysfs 135 #define __NR_personality 136 +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ extern int errno; diff -u --recursive v1.1.32/linux/ipc/shm.c linux/ipc/shm.c --- v1.1.32/linux/ipc/shm.c Thu Jul 21 13:54:37 1994 +++ linux/ipc/shm.c Thu Jul 21 13:54:37 1994 @@ -19,6 +19,7 @@ static int newseg (key_t key, int shmflg, int size); static int shm_map (struct shm_desc *shmd, int remap); static void killseg (int id); +static unsigned long shm_swap_in(struct vm_area_struct *, unsigned long); static int shm_tot = 0; /* total number of shared memory pages */ static int shm_rss = 0; /* number of shared memory pages that are in memory */ @@ -375,13 +376,24 @@ return 0; } +static struct vm_operations_struct shm_vm_ops = { + NULL, /* open */ + NULL, /* close */ + NULL, /* nopage (done with swapin) */ + NULL, /* wppage */ + NULL, /* share */ + NULL, /* unmap */ + NULL, /* swapout (hardcoded right now) */ + shm_swap_in /* swapin */ +}; + /* * This is really minimal support to make the shared mem stuff * ve known by the general VM manager. It should add the vm_ops * field so that 'munmap()' and friends work correctly on shared * memory areas.. */ -static int add_vm_area(unsigned long addr, unsigned long len) +static int add_vm_area(unsigned long addr, unsigned long len, int readonly) { struct vm_area_struct * vma; @@ -392,12 +404,15 @@ vma->vm_task = current; vma->vm_start = addr; vma->vm_end = addr + len; - vma->vm_page_prot = PAGE_SHARED; + if (readonly) + vma->vm_page_prot = PAGE_READONLY; + else + vma->vm_page_prot = PAGE_SHARED; vma->vm_flags = VM_SHM; vma->vm_share = NULL; vma->vm_inode = NULL; vma->vm_offset = 0; - vma->vm_ops = NULL; + vma->vm_ops = &shm_vm_ops; insert_vm_struct(current, vma); merge_segments(current->mm->mmap, NULL, NULL); return 0; @@ -476,7 +491,7 @@ shmd->end = addr + shp->shm_npages * PAGE_SIZE; shmd->task = current; - if ((err = add_vm_area(shmd->start, shmd->end - shmd->start))) { + if ((err = add_vm_area(shmd->start, shmd->end - shmd->start, shmflg & SHM_RDONLY))) { kfree(shmd); return err; } @@ -614,36 +629,34 @@ } /* - * page not present ... go through shm_pages .. called from swap_in() + * page not present ... go through shm_pages */ -void shm_no_page (unsigned long *ptent) +static unsigned long shm_swap_in(struct vm_area_struct * vma, unsigned long code) { unsigned long page; - unsigned long code = *ptent; struct shmid_ds *shp; unsigned int id, idx; id = (code >> SHM_ID_SHIFT) & SHM_ID_MASK; if (id > max_shmid) { printk ("shm_no_page: id=%d too big. proc mem corruptedn", id); - return; + return BAD_PAGE | PAGE_SHARED; } shp = shm_segs[id]; if (shp == IPC_UNUSED || shp == IPC_NOID) { printk ("shm_no_page: id=%d invalid. Race.\n", id); - return; + return BAD_PAGE | PAGE_SHARED; } idx = (code >> SHM_IDX_SHIFT) & SHM_IDX_MASK; if (idx >= shp->shm_npages) { printk ("shm_no_page : too large page index. id=%d\n", id); - return; + return BAD_PAGE | PAGE_SHARED; } if (!(shp->shm_pages[idx] & PAGE_PRESENT)) { if(!(page = get_free_page(GFP_KERNEL))) { oom(current); - *ptent = BAD_PAGE | PAGE_ACCESSED | 7; - return; + return BAD_PAGE | PAGE_SHARED; } if (shp->shm_pages[idx] & PAGE_PRESENT) { free_page (page); @@ -667,10 +680,9 @@ current->mm->min_flt++; page = shp->shm_pages[idx]; if (code & SHM_READ_ONLY) /* write-protect */ - page &= ~2; + page &= ~PAGE_RW; mem_map[MAP_NR(page)]++; - *ptent = page; - return; + return page; } /* diff -u --recursive v1.1.32/linux/kernel/exit.c linux/kernel/exit.c --- v1.1.32/linux/kernel/exit.c Tue Jun 21 14:16:26 1994 +++ linux/kernel/exit.c Thu Jul 21 10:23:45 1994 @@ -365,6 +365,8 @@ struct vm_area_struct * next = mpnt->vm_next; if (mpnt->vm_ops && mpnt->vm_ops->close) mpnt->vm_ops->close(mpnt); + if (mpnt->vm_inode) + iput(mpnt->vm_inode); kfree(mpnt); mpnt = next; } diff -u --recursive v1.1.32/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.1.32/linux/kernel/ksyms.c Fri Jul 8 13:26:41 1994 +++ linux/kernel/ksyms.c Thu Jul 21 08:25:01 1994 @@ -79,6 +79,8 @@ X(do_munmap), X(insert_vm_struct), X(zeromap_page_range), + X(unmap_page_range), + X(merge_segments), /* internal kernel memory management */ X(__get_free_pages), @@ -95,6 +97,7 @@ X(iput), X(namei), X(lnamei), + X(open_namei), /* device registration */ X(register_chrdev), @@ -133,6 +136,8 @@ /* process management */ X(wake_up), X(wake_up_interruptible), + X(sleep_on), + X(interruptible_sleep_on), X(schedule), X(current), X(jiffies), diff -u --recursive v1.1.32/linux/kernel/sched.c linux/kernel/sched.c --- v1.1.32/linux/kernel/sched.c Thu Jul 21 08:18:21 1994 +++ linux/kernel/sched.c Thu Jul 21 00:00:52 1994 @@ -412,8 +412,9 @@ return 1; } } - if (p->next || p->prev) - printk("del_timer() called with timer not initialized\n"); + if (timer->next || timer->prev) + printk("del_timer() called from %08lx with timer not initialized\n", + ((unsigned long *) &timer)[-1]); restore_flags(flags); return 0; #else diff -u --recursive v1.1.32/linux/kernel/sys_call.S linux/kernel/sys_call.S --- v1.1.32/linux/kernel/sys_call.S Tue Jun 21 14:16:26 1994 +++ linux/kernel/sys_call.S Thu Jul 21 08:24:30 1994 @@ -537,5 +537,6 @@ .long _sys_bdflush .long _sys_sysfs /* 135 */ .long _sys_personality + .long 0 /* for afs_syscall */ - .space (NR_syscalls-136)*4 + .space (NR_syscalls-137)*4 diff -u --recursive v1.1.32/linux/mm/memory.c linux/mm/memory.c --- v1.1.32/linux/mm/memory.c Thu Jul 21 08:18:22 1994 +++ linux/mm/memory.c Thu Jul 21 15:06:57 1994 @@ -724,9 +724,16 @@ from &= PAGE_MASK; from_page = from + PAGE_PTR(from_address); from = *(unsigned long *) from_page; -/* is the page clean and present? */ - if ((from & (PAGE_PRESENT | PAGE_DIRTY)) != PAGE_PRESENT) +/* is the page present? */ + if (!(from & PAGE_PRESENT)) return 0; +/* if it is private, it must be clean to be shared */ + if ((from_area->vm_page_prot & PAGE_COW) && (from & PAGE_DIRTY)) + return 0; +/* the swap caching doesn't really handle shared pages.. */ + if (in_swap_cache(from)) + return 0; +/* is the page reasonable at all? */ if (from >= high_memory) return 0; if (mem_map[MAP_NR(from)] & MAP_PAGE_RESERVED) @@ -856,6 +863,28 @@ return 0; } +static inline void do_swap_page(struct vm_area_struct * vma, + unsigned long address, unsigned long * pge, unsigned long entry) +{ + unsigned long page; + + if (vma->vm_ops && vma->vm_ops->swapin) + page = vma->vm_ops->swapin(vma, entry); + else + page = swap_in(entry); + if (*pge != entry) { + free_page(page); + return; + } + page = page | vma->vm_page_prot; + if (mem_map[MAP_NR(page)] > 1 && (page & PAGE_COW)) + page &= ~PAGE_RW; + ++vma->vm_task->mm->rss; + ++vma->vm_task->mm->maj_flt; + *pge = page; + return; +} + void do_no_page(struct vm_area_struct * vma, unsigned long address, unsigned long error_code) { @@ -870,9 +899,7 @@ if (entry & PAGE_PRESENT) return; if (entry) { - ++vma->vm_task->mm->rss; - ++vma->vm_task->mm->maj_flt; - swap_in((unsigned long *) page); + do_swap_page(vma, address, (unsigned long *) page, entry); return; } address &= PAGE_MASK; @@ -886,6 +913,7 @@ page = get_free_page(GFP_KERNEL); if (share_page(vma, address, error_code, page)) { ++vma->vm_task->mm->min_flt; + ++vma->vm_task->mm->rss; return; } if (!page) { @@ -1224,7 +1252,7 @@ /* This handles a generic mmap of a disk file */ -unsigned long file_mmap_nopage(struct vm_area_struct * area, unsigned long address, +static unsigned long file_mmap_nopage(struct vm_area_struct * area, unsigned long address, unsigned long page, int error_code) { struct inode * inode = area->vm_inode; @@ -1244,33 +1272,11 @@ return bread_page(page, inode->i_dev, nr, inode->i_sb->s_blocksize, !(error_code & PAGE_RW)); } -void file_mmap_free(struct vm_area_struct * area) -{ - if (area->vm_inode) - iput(area->vm_inode); -#if 0 - if (area->vm_inode) - printk("Free inode %x:%d (%d)\n",area->vm_inode->i_dev, - area->vm_inode->i_ino, area->vm_inode->i_count); -#endif -} - -/* - * Compare the contents of the mmap entries, and decide if we are allowed to - * share the pages - */ -int file_mmap_share(struct vm_area_struct * area1, - struct vm_area_struct * area2, - unsigned long address) -{ - return 1; -} - struct vm_operations_struct file_mmap = { NULL, /* open */ - file_mmap_free, /* close */ + NULL, /* close */ file_mmap_nopage, /* nopage */ NULL, /* wppage */ - file_mmap_share, /* share */ + NULL, /* share */ NULL, /* unmap */ }; diff -u --recursive v1.1.32/linux/mm/mmap.c linux/mm/mmap.c --- v1.1.32/linux/mm/mmap.c Sat Jul 9 16:30:47 1994 +++ linux/mm/mmap.c Thu Jul 21 10:23:45 1994 @@ -194,6 +194,8 @@ if (addr == area->vm_start && end == area->vm_end) { if (area->vm_ops && area->vm_ops->close) area->vm_ops->close(area); + if (area->vm_inode) + iput(area->vm_inode); return; } @@ -216,8 +218,8 @@ mpnt->vm_start = end; if (mpnt->vm_inode) mpnt->vm_inode->i_count++; - insert_vm_struct(current, mpnt); area->vm_end = addr; /* Truncate area */ + insert_vm_struct(current, mpnt); } /* construct whatever mapping is needed */ diff -u --recursive v1.1.32/linux/mm/swap.c linux/mm/swap.c --- v1.1.32/linux/mm/swap.c Tue Jul 19 10:19:15 1994 +++ linux/mm/swap.c Thu Jul 21 15:10:42 1994 @@ -8,6 +8,7 @@ * This file should contain most things doing the swapping from/to disk. * Started 18.12.91 */ +#define SWAP_CACHE_INFO #include #include @@ -47,13 +48,115 @@ extern int shm_swap (int); -/* - * The following are used to make sure we don't thrash too much... - * NOTE!! NR_LAST_FREE_PAGES must be a power of 2... - */ -#define NR_LAST_FREE_PAGES 32 -static unsigned long last_free_pages[NR_LAST_FREE_PAGES] = {0,}; +unsigned long *swap_cache; +static unsigned long swap_cache_size; + +#ifdef SWAP_CACHE_INFO +static unsigned long add_calls_total = 0; +static unsigned long add_calls_success = 0; +static unsigned long del_calls_total = 0; +static unsigned long del_calls_success = 0; +static unsigned long find_calls_total = 0; +static unsigned long find_calls_success = 0; + +extern inline void show_swap_cache_info (void) +{ + printk("Swap cache: add %ld/%ld, delete %ld/%ld, find %ld/%ld\n", + add_calls_total, add_calls_success, + del_calls_total, del_calls_success, + find_calls_total, find_calls_success); +} +#endif + +extern inline unsigned long init_swap_cache (unsigned long mem_start, + unsigned long mem_end) +{ + mem_start = (mem_start + 15) & ~15; + swap_cache = (unsigned long *) mem_start; + swap_cache_size = mem_end >> PAGE_SHIFT; + memset(swap_cache, 0, swap_cache_size * sizeof (unsigned long)); +#ifdef SWAP_CACHE_INFO + printk("%ld bytes for swap cache allocated\n", + swap_cache_size * sizeof(unsigned long)); +#endif + + return (unsigned long) (swap_cache + swap_cache_size); +} + +extern inline long find_in_swap_cache (unsigned long addr) +{ + unsigned long entry; + +#ifdef SWAP_CACHE_INFO + find_calls_total++; +#endif + __asm__ __volatile__ ( + "xchgl %0,%1\n" + : "=m" (swap_cache[addr >> PAGE_SHIFT]), + "=r" (entry) + : "0" (swap_cache[addr >> PAGE_SHIFT]), + "1" (0) + ); +#ifdef SWAP_CACHE_INFO + if (entry) + find_calls_success++; +#endif + + return entry; +} + +extern inline int add_to_swap_cache (unsigned long addr, unsigned long entry) +{ + struct swap_info_struct * p = &swap_info[SWP_TYPE(entry)]; + +#ifdef SWAP_CACHE_INFO + add_calls_total++; +#endif + if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { + __asm__ __volatile__ ( + "xchgl %0,%1\n" + : "=m" (swap_cache[addr >> PAGE_SHIFT]), + "=r" (entry) + : "0" (swap_cache[addr >> PAGE_SHIFT]), + "1" (entry) + ); + if (entry) { + printk("swap_cache: replacing non-NULL entry\n"); + } +#ifdef SWAP_CACHE_INFO + add_calls_success++; +#endif + return 1; + } + return 0; +} + + +extern inline int delete_from_swap_cache(unsigned long addr) +{ + unsigned long entry; + +#ifdef SWAP_CACHE_INFO + del_calls_total++; +#endif + __asm__ __volatile__ ( + "xchgl %0,%1\n" + : "=m" (swap_cache[addr >> PAGE_SHIFT]), + "=r" (entry) + : "0" (swap_cache[addr >> PAGE_SHIFT]), + "1" (0) + ); + if (entry) { +#ifdef SWAP_CACHE_INFO + del_calls_success++; +#endif + swap_free(entry); + return 1; + } + return 0; +} + void rw_swap_page(int rw, unsigned long entry, char * buf) { unsigned long type, offset; @@ -142,7 +245,7 @@ } p = type + swap_info; if (offset >= p->max) { - printk("swap_free: weirdness\n"); + printk("swap_duplicate: weirdness\n"); return 0; } if (!p->swap_map[offset]) { @@ -193,42 +296,24 @@ wake_up(&lock_queue); } -void swap_in(unsigned long *table_ptr) +unsigned long swap_in(unsigned long entry) { - unsigned long entry; unsigned long page; - entry = *table_ptr; - if (PAGE_PRESENT & entry) { - printk("trying to swap in present page\n"); - return; - } - if (!entry) { - printk("No swap page in swap_in\n"); - return; - } - if (SWP_TYPE(entry) == SHM_SWP_TYPE) { - shm_no_page ((unsigned long *) table_ptr); - return; - } if (!(page = get_free_page(GFP_KERNEL))) { oom(current); - page = BAD_PAGE; - } else - read_swap_page(entry, (char *) page); - if (*table_ptr != entry) { - free_page(page); - return; + return BAD_PAGE; } - *table_ptr = page | (PAGE_DIRTY | PAGE_PRIVATE); - swap_free(entry); + read_swap_page(entry, (char *) page); + if (add_to_swap_cache(page, entry)) + return page | PAGE_PRIVATE; + swap_free(entry); + return page | PAGE_DIRTY | PAGE_PRIVATE; } static inline int try_to_swap_out(unsigned long * table_ptr) { - int i; - unsigned long page; - unsigned long entry; + unsigned long page, entry; page = *table_ptr; if (!(PAGE_PRESENT & page)) @@ -237,13 +322,14 @@ return 0; if (mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED) return 0; + + if ((PAGE_DIRTY & page) && delete_from_swap_cache(page)) { + return 0; + } if (PAGE_ACCESSED & page) { *table_ptr &= ~PAGE_ACCESSED; return 0; } - for (i = 0; i < NR_LAST_FREE_PAGES; i++) - if (last_free_pages[i] == (page & PAGE_MASK)) - return 0; if (PAGE_DIRTY & page) { page &= PAGE_MASK; if (mem_map[MAP_NR(page)] != 1) @@ -256,6 +342,26 @@ free_page(page); return 1; } + + if ((entry = find_in_swap_cache(page))) { + *table_ptr |= PAGE_DIRTY; + if (mem_map[MAP_NR(page)] != 1) { + return 0; + } + if (!entry) { + if (!(entry = get_swap_page())) { + return 0; + } + *table_ptr = entry; + invalidate(); + write_swap_page(entry, (char *) (page & PAGE_MASK)); + } else { + *table_ptr = entry; + invalidate(); + } + free_page(page & PAGE_MASK); + return 1; + } page &= PAGE_MASK; *table_ptr = 0; invalidate(); @@ -531,8 +637,10 @@ if (!(*map & MAP_PAGE_RESERVED)) { save_flags(flag); cli(); - if (!--*map) + if (!--*map) { free_pages_ok(addr, order); + delete_from_swap_cache(addr); + } restore_flags(flag); if(*map == 1) { int j; @@ -639,6 +747,9 @@ } restore_flags(flags); printk("= %lukB)\n", total); +#ifdef SWAP_CACHE_INFO + show_swap_cache_info(); +#endif } /* @@ -654,6 +765,7 @@ struct task_struct *p; nr = 0; + /* * When we have to sleep, we restart the whole algorithm from the same * task we stopped in. That at least rids us of all races. @@ -677,8 +789,15 @@ page = *ppage; if (!page) continue; - if (page & PAGE_PRESENT) + if (page & PAGE_PRESENT) { + if (!(page = in_swap_cache(page))) + continue; + if (SWP_TYPE(page) != type) + continue; + *ppage |= PAGE_DIRTY; + delete_from_swap_cache(*ppage); continue; + } if (SWP_TYPE(page) != type) continue; if (!tmp) { @@ -898,6 +1017,7 @@ unsigned long mask = PAGE_MASK; int i; + start_mem = init_swap_cache(start_mem, end_mem); mem_map = (unsigned short *) start_mem; p = mem_map + MAP_NR(end_mem); start_mem = (unsigned long) p; diff -u --recursive v1.1.32/linux/net/inet/arp.c linux/net/inet/arp.c --- v1.1.32/linux/net/inet/arp.c Thu Jul 21 08:18:23 1994 +++ linux/net/inet/arp.c Wed Jul 20 23:51:46 1994 @@ -746,13 +746,13 @@ entry->hlen = hlen; entry->htype = htype; entry->flags = ATF_COM; + entry->timer.next = entry->timer.prev = NULL; memcpy(entry->ha, sha, hlen); entry->last_used = jiffies; entry->dev = skb->dev; skb_queue_head_init(&entry->skb); entry->next = arp_tables[hash]; arp_tables[hash] = entry; - entry->timer.next = entry->timer.prev = NULL; sti(); } @@ -837,14 +837,14 @@ entry->htype = dev->type; entry->flags = 0; memset(entry->ha, 0, dev->addr_len); - entry->last_used = jiffies; - entry->next = arp_tables[hash]; entry->dev = dev; - arp_tables[hash] = entry; + entry->last_used = jiffies; entry->timer.next = entry->timer.prev = NULL; entry->timer.function = arp_expire_request; entry->timer.data = (unsigned long)entry; entry->timer.expires = ARP_RES_TIME; + entry->next = arp_tables[hash]; + arp_tables[hash] = entry; add_timer(&entry->timer); entry->retries = ARP_MAX_TRIES; skb_queue_head_init(&entry->skb); @@ -1048,8 +1048,8 @@ entry->ip = ip; entry->hlen = hlen; entry->htype = htype; - entry->next = arp_tables[hash]; entry->timer.next = entry->timer.prev = NULL; + entry->next = arp_tables[hash]; arp_tables[hash] = entry; skb_queue_head_init(&entry->skb); }