Commit 03c31052 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.129pre6

parent ee537af3
......@@ -275,6 +275,7 @@ CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_CODA_FS is not set
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_SYSV_FS is not set
......
......@@ -559,7 +559,6 @@ ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_mrecow) /* 190 */
/*
* NOTE!! This doesn' thave to be exact - we just have
......@@ -567,6 +566,6 @@ ENTRY(sys_call_table)
* entries. Don't panic if you notice that this hasn't
* been shrunk every time we add a new system call.
*/
.rept NR_syscalls-190
.rept NR_syscalls-189
.long SYMBOL_NAME(sys_ni_syscall)
.endr
......@@ -86,8 +86,7 @@ static DECLARE_TASK_QUEUE(tq_serial);
static struct tty_driver serial_driver, callout_driver;
static int serial_refcount;
/* serial supmac_irq_hw *) 0xf3000010,
btype definitions */
/* serial subtype definitions */
#define SERIAL_TYPE_NORMAL 1
#define SERIAL_TYPE_CALLOUT 2
......
......@@ -17,23 +17,23 @@
extern unsigned long log_size;
extern struct wait_queue * log_wait;
asmlinkage int sys_syslog(int type, char * bug, int count);
extern int do_syslog(int type, char * bug, int count);
static int kmsg_open(struct inode * inode, struct file * file)
{
return sys_syslog(1,NULL,0);
return do_syslog(1,NULL,0);
}
static int kmsg_release(struct inode * inode, struct file * file)
{
(void) sys_syslog(0,NULL,0);
(void) do_syslog(0,NULL,0);
return 0;
}
static ssize_t kmsg_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
return sys_syslog(2,buf,count);
return do_syslog(2,buf,count);
}
static unsigned int kmsg_poll(struct file *file, poll_table * wait)
......
......@@ -194,7 +194,6 @@
#define __NR_sendfile 187
#define __NR_getpmsg 188 /* some people actually want streams */
#define __NR_putpmsg 189 /* some people actually want streams */
#define __NR_mrecow 190
/* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
......
......@@ -105,7 +105,7 @@ void __init console_setup(char *str, int *ints)
/*
* Commands to sys_syslog:
* Commands to do_syslog:
*
* 0 -- Close the log. Currently a NOP.
* 1 -- Open the log. Currently a NOP.
......@@ -117,7 +117,7 @@ void __init console_setup(char *str, int *ints)
* 7 -- Enable printk's to console
* 8 -- Set level of messages printed to console
*/
asmlinkage int sys_syslog(int type, char * buf, int len)
int do_syslog(int type, char * buf, int len)
{
unsigned long i, j, count, flags;
int do_clear = 0;
......@@ -125,8 +125,6 @@ asmlinkage int sys_syslog(int type, char * buf, int len)
int error = -EPERM;
lock_kernel();
if ((type != 3) && !capable(CAP_SYS_ADMIN))
goto out;
error = 0;
switch (type) {
case 0: /* Close log */
......@@ -228,6 +226,14 @@ asmlinkage int sys_syslog(int type, char * buf, int len)
return error;
}
asmlinkage int sys_syslog(int type, char * buf, int len)
{
if ((type != 3) && !capable(CAP_SYS_ADMIN))
return -EPERM;
return do_syslog(type, buf, len);
}
spinlock_t console_lock;
asmlinkage int printk(const char *fmt, ...)
......
......@@ -9,7 +9,7 @@
O_TARGET := mm.o
O_OBJS := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \
vmalloc.o slab.o mrecow.o \
vmalloc.o slab.o \
swap.o vmscan.o page_io.o page_alloc.o swap_state.o swapfile.o
include $(TOPDIR)/Rules.make
/*
* linux/mm/recow.c
*
* Copyright (C) 1998 Linus Torvalds
*/
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <asm/pgtable.h>
/*
* This implements the "re-COW" system call.
*
* "re-cow" - synchronize two page-aligned areas with each other,
* returning the first offset at which they differ. This is useful
* for doing large memory compares. One example is simulating a
* VGA device under DOSEMU, where you cache the old state of the
* screen, and let DOSEMU have a private copy that it can change.
*
* When you want to synchronize the real screen with the private
* simulation, you "re-cow()" the areas and see where the changes
* have been. It will not only tell you what pages have been modified,
* it will also share pages if they are the same..
*
* Doing this in user mode is prohibitive, as we need to access
* the page tables in order to do this efficiently.
*/
#define verify_recow(mm, vma, addr, len) do { \
vma = find_vma(mm, addr); \
if (!vma || (vma->vm_flags & VM_SHARED) || addr < vma->vm_start || vma->vm_end - addr < len) \
goto badvma; \
} while (0)
static int do_compare(struct mm_struct *mm, pte_t * firstpte, unsigned long addr)
{
pgd_t * pgd;
pgd = pgd_offset(mm, addr);
if (!pgd_none(*pgd)) {
pmd_t * pmd = pmd_offset(pgd, addr);
if (!pmd_none(*pmd)) {
pte_t * pte = pte_offset(pmd, addr);
pte_t entry = *pte;
if (pte_present(entry)) {
unsigned long page1 = pte_page(*firstpte);
unsigned long page2 = pte_page(entry);
if (page1 == page2)
return 1;
if (!memcmp((void *) page1, (void *) page2, PAGE_SIZE)) {
entry = pte_wrprotect(entry);
*firstpte = entry;
*pte = entry;
atomic_inc(&mem_map[MAP_NR(page2)].count);
free_page(page1);
return 2;
}
}
}
}
return 0;
}
/*
* NOTE! We return zero for all "special" cases,
* so that if something is not present for any
* reason the user has to compare that by hand.
*/
static int same_page(struct mm_struct *mm, unsigned long addr1, unsigned long addr2)
{
pgd_t * pgd;
pgd = pgd_offset(mm, addr1);
if (!pgd_none(*pgd)) {
pmd_t * pmd = pmd_offset(pgd, addr1);
if (!pmd_none(*pmd)) {
pte_t * pte = pte_offset(pmd, addr1);
if (pte_present(*pte))
return do_compare(mm, pte, addr2);
}
}
return 0;
}
asmlinkage long sys_mrecow(unsigned long addr1, unsigned long addr2, size_t len)
{
int shared = 0;
long retval;
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma1, *vma2;
/*
* Everything has to be page-aligned..
*/
if ((addr1 | addr2 | len) & ~PAGE_MASK)
return -EINVAL;
/* Make sure we're not aliased (trivially the same for the whole length) */
if (addr1 == addr2)
return len;
down(&mm->mmap_sem);
/*
* We require that the comparison areas are fully contained
* within the vm_area_structs, and that they are both private
* mappings..
*/
retval = -EFAULT;
verify_recow(mm, vma1, addr1, len);
verify_recow(mm, vma2, addr2, len);
/*
* We need to have the same page protections on both
* areas, otherwise we'll mess up when we combine pages.
*
* Right now we also only allow this on anonymous areas,
* I don't know if we'd want to expand it to other things
* at some point.
*/
retval = -EINVAL;
if (pgprot_val(vma1->vm_page_prot) != pgprot_val(vma2->vm_page_prot))
goto badvma;
if (vma1->vm_file || vma2->vm_file)
goto badvma;
/*
* Ok, start the page walk..
*/
lock_kernel();
retval = 0;
while (len) {
int same = same_page(mm, addr1, addr2);
if (!same)
break;
shared |= same;
len -= PAGE_SIZE;
retval += PAGE_SIZE;
addr1 += PAGE_SIZE;
addr2 += PAGE_SIZE;
}
unlock_kernel();
if (shared)
flush_tlb_mm(mm);
badvma:
up(&mm->mmap_sem);
return retval;
}
......@@ -66,6 +66,11 @@ void rw_swap_page(int rw, unsigned long entry, char * buf, int wait)
printk("Internal error: bad swap-device\n");
return;
}
/* Don't allow too many pending pages in flight.. */
if (atomic_read(&nr_async_pages) > SWAP_CLUSTER_MAX)
wait = 1;
p = &swap_info[type];
offset = SWP_OFFSET(entry);
if (offset >= p->max) {
......
......@@ -706,22 +706,13 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
case SIOCSIFHWBROADCAST:
return(dev_ioctl(cmd,(void *) arg));
case SIOCSIFADDR:
case SIOCGIFADDR:
return ec_dev_ioctl(sock, cmd, (void *)arg);
break;
default:
if ((cmd >= SIOCDEVPRIVATE) &&
(cmd <= (SIOCDEVPRIVATE + 15)))
return(dev_ioctl(cmd,(void *) arg));
#ifdef CONFIG_NET_RADIO
if((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST))
return(dev_ioctl(cmd,(void *) arg));
#endif
return -EOPNOTSUPP;
return(dev_ioctl(cmd,(void *) arg));
}
/*NOTREACHED*/
return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment