Commit 7eaba1c7 authored by Linus Torvalds's avatar Linus Torvalds

Linux 2.1.108

I just made a pre-2.1.108 and put it on ftp.kernel.org - it fixes a
problem where my sendfile() forgot to get the kernel lock (blush), so it
randomly didn't work correctly on SMP.

I've also done some more testing of sendfile(), and the nice thing is that
when I compared doing a file copy with sendfile compared to a plain "cp",
the sendfile implementation was about twice as fast (at least my version
of "cp" will just do read+write pairs over and over again). When I copied
a 38MB file the "cp" took 1:58 seconds while sendfile took 1:08 seconds
according to "time" (I have 512MB of RAM, so this was all cached,
obviously)..

I haven't done any network tests, because I don't think I'd be able to see
any difference, and it does need the "SO_CONSTIPATED" thing and a way to
push the end of data for best performance.

Some final words on sendfile():
 - it does report errors correctly. That doesn't mean that you necessarily
   can know _which_ fd produced the error, that you have to find out on
   your own. A file real access can generally result in EIO and EACCES
   (the latter with NFS and other "protection-at-read-time" non-UNIX
   filesystems), while the output write() can result in a number of errors
   as the output fd can be any kind of socket/tty/file. Depending on the
   mode of the output file, the output errors can include EINTR, EAGAIN
   etc, and you can mix sendfile() with select() on the output socket, for
   example.
 - you can give it a length of MAX_ULONG, and it will write as much as it
   can. This is entirely consistent with the notion that it is equivalent
   with write(out, tmpbuf, read(in, tmpbuf, size)) where "tmpbuf" is
   essentially infinite - the read() will read al of the file and return
   the file length in the process. Thus you don't even need to know the
   size of the file beforehand.
   The file copy test was essentially done with a single
        error = sendfile(out, in, ~0);
   and I'm appending my current test-program.

This is going to be in 2.2, btw. The changes are so small and so obviously
have to work that it would be ridiculous not to have this - the only
question is whether I'll try to make it a "copyfd()" system call instead,
falling back on read+write when I can't use the page cache directly. I
suspect I won't.

                        Linus
parent eb4d32c1
This diff is collapsed.
This diff is collapsed.
......@@ -509,10 +509,8 @@ L: linux-kernel@vger.rutgers.edu
S: Maintained
SCSI SUBSYSTEM
P: Leonard N. Zubkoff
M: Leonard N. Zubkoff <lnz@dandelion.com>
L: linux-scsi@vger.rutgers.edu
S: Maintained
S: Unmaintained
SCSI TAPE DRIVER
P: Kai Mdkisara
......
......@@ -4,15 +4,6 @@
#
mainmenu_name "Kernel configuration of Linux for Alpha machines"
# clear all implied options (don't want default values for those):
unset CONFIG_CROSSCOMPILE CONFIG_NATIVE
unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
unset CONFIG_PCI CONFIG_ALPHA_EISA
unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS
unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA
unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
......@@ -31,6 +22,8 @@ endmenu
mainmenu_option next_comment
comment 'General setup'
unset CONFIG_CROSSCOMPILE CONFIG_NATIVE
if [ "`uname`" != "Linux" ]; then
define_bool CONFIG_CROSSCOMPILE y
else
......@@ -63,6 +56,14 @@ choice 'Alpha system type' \
Ruffian CONFIG_ALPHA_RUFFIAN \
Platform2000 CONFIG_ALPHA_P2K" Cabriolet
# clear all implied options (don't want default values for those):
unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
unset CONFIG_PCI CONFIG_ALPHA_EISA
unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS
unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA
unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION
if [ "$CONFIG_ALPHA_BOOK1" = "y" ]
then
define_bool CONFIG_ALPHA_NONAME y
......
......@@ -388,11 +388,11 @@ int get_cpuinfo(char *buffer)
&systype_name, &sysvariation_name);
return sprintf(buffer,
"CPU\t\t\t: Alpha\n"
"CPU model\t\t: %s\n"
"CPU variation\t\t: %ld\n"
"CPU revision\t\t: %ld\n"
"CPU serial number\t: %s\n"
"cpu\t\t\t: Alpha\n"
"cpu model\t\t: %s\n"
"cpu variation\t\t: %ld\n"
"cpu revision\t\t: %ld\n"
"cpu serial number\t: %s\n"
"system type\t\t: %s\n"
"system variation\t: %s\n"
"system revision\t\t: %ld\n"
......
This diff is collapsed.
......@@ -16,7 +16,7 @@ else
dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640
if [ "$CONFIG_BLK_DEV_CMD640" = "y" ]; then
bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED
......@@ -48,7 +48,9 @@ else
bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580
bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030
fi
fi
fi
fi
......
......@@ -98,85 +98,86 @@ ifeq ($(CONFIG_BLK_DEV_HD),y)
L_OBJS += hd.o
endif
ifeq ($(CONFIG_BLK_DEV_IDE),y)
LX_OBJS += ide.o
ifeq ($(CONFIG_PROC_FS),y)
L_OBJS += ide-proc.o
endif
L_OBJS += ide-probe.o
else
ifeq ($(CONFIG_BLK_DEV_IDE),m)
MIX_OBJS += ide.o
# ide-mod includes ide-proc
M_OBJS += ide-mod.o
MX_OBJS += ide-probe.o
endif
endif
ifeq ($(CONFIG_BLK_DEV_RZ1000),y)
L_OBJS += rz1000.o
IDE_OBJS += rz1000.o
endif
ifeq ($(CONFIG_BLK_DEV_CMD640),y)
L_OBJS += cmd640.o
IDE_OBJS += cmd640.o
endif
ifeq ($(CONFIG_BLK_DEV_IDEPCI),y)
L_OBJS += ide-pci.o
IDE_OBJS += ide-pci.o
endif
ifeq ($(CONFIG_BLK_DEV_IDEDMA),y)
L_OBJS += ide-dma.o
endif
ifeq ($(CONFIG_BLK_DEV_PS2),y)
L_OBJS += ps2esdi.o
IDE_OBJS += ide-dma.o
endif
ifeq ($(CONFIG_BLK_DEV_DTC2278),y)
L_OBJS += dtc2278.o
IDE_OBJS += dtc2278.o
endif
ifeq ($(CONFIG_BLK_DEV_HT6560B),y)
L_OBJS += ht6560b.o
IDE_OBJS += ht6560b.o
endif
ifeq ($(CONFIG_BLK_DEV_QD6580),y)
L_OBJS += qd6580.o
IDE_OBJS += qd6580.o
endif
ifeq ($(CONFIG_BLK_DEV_UMC8672),y)
L_OBJS += umc8672.o
IDE_OBJS += umc8672.o
endif
ifeq ($(CONFIG_BLK_DEV_ALI14XX),y)
L_OBJS += ali14xx.o
IDE_OBJS += ali14xx.o
endif
ifeq ($(CONFIG_BLK_DEV_PDC4030),y)
L_OBJS += pdc4030.o
IDE_OBJS += pdc4030.o
endif
ifeq ($(CONFIG_BLK_DEV_TRM290),y)
L_OBJS += trm290.o
IDE_OBJS += trm290.o
endif
ifeq ($(CONFIG_BLK_DEV_OPTI621),y)
L_OBJS += opti621.o
IDE_OBJS += opti621.o
endif
ifeq ($(CONFIG_BLK_DEV_NS87415),y)
L_OBJS += ns87415.o
IDE_OBJS += ns87415.o
endif
ifeq ($(CONFIG_BLK_DEV_CMD646),y)
L_OBJS += cmd646.o
IDE_OBJS += cmd646.o
endif
ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
L_OBJS += sl82c105.o
IDE_OBJS += sl82c105.o
endif
### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored
ifeq ($(CONFIG_PROC_FS),y)
IDE_OBJS += ide-proc.o
endif
###Collect
ifeq ($(CONFIG_BLK_DEV_IDE),y)
LX_OBJS += ide.o
L_OBJS += ide-probe.o $(IDE_OBJS)
else
ifeq ($(CONFIG_BLK_DEV_IDE),m)
MIX_OBJS += ide.o $(IDE_OBJS)
M_OBJS += ide-mod.o ide-probe.o
endif
endif
############
ifeq ($(CONFIG_BLK_DEV_IDEDISK),y)
L_OBJS += ide-disk.o
else
......@@ -209,6 +210,10 @@ else
endif
endif
ifeq ($(CONFIG_BLK_DEV_PS2),y)
L_OBJS += ps2esdi.o
endif
ifeq ($(CONFIG_BLK_DEV_XD),y)
L_OBJS += xd.o
else
......@@ -273,5 +278,5 @@ endif
include $(TOPDIR)/Rules.make
ide-mod.o: ide.o ide-proc.o
$(LD) $(LD_RFLAG) -r -o $@ ide.o ide-proc.o
ide-mod.o: ide.o $(IDE_OBJS)
$(LD) $(LD_RFLAG) -r -o $@ ide.o $(IDE_OBJS)
/*
* linux/drivers/block/ide.c Version 6.13 March 29, 1998
* linux/drivers/block/ide.c Version 6.17 March 29, 1998
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
......@@ -88,6 +88,7 @@
* Version 6.14 fixed IRQ sharing among PCI devices
* Version 6.15 added SMP awareness to IDE drivers
* Version 6.16 fixed various bugs; even more SMP friendly
* Version 6.17 fix for newest EZ-Drive problem
*
* Some additional driver compile-time options are in ide.h
*
......@@ -2560,7 +2561,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
printk("%s ", msg);
if (xparm == -1 && drive->bios_cyl < 1024)
if (xparm == -1 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63))
return 0; /* small disk: no translation needed */
if (drive->id) {
......
......@@ -74,9 +74,9 @@
* BUSY _________ _______
* |____________|
*
* I discovered this using the printer scanner:
* I discovered this using the printer scanner that you can find at:
*
* http://www.cs.unibo.it/~arcangel/pscan/pscan-0.4.tar.gz
* ftp://e-mind.com/pub/linux/pscan/
*
* 11 May 98, Andrea Arcangeli
*/
......@@ -326,8 +326,7 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count)
lp_table[minor].irq_detected = 0;
lp_table[minor].irq_missed = 0;
if (!LP_POLLED(minor))
w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
w_ctr(minor, LP_PSELECP | LP_PINITP);
do {
bytes_written = 0;
......@@ -335,7 +334,7 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count)
if (copy_from_user(lp->lp_buffer, buf, copy_size))
{
w_ctr(minor, LP_PINITP);
w_ctr(minor, LP_PSELECP | LP_PINITP);
return -EFAULT;
}
......@@ -357,7 +356,7 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count)
if (signal_pending(current))
{
w_ctr(minor, LP_PINITP);
w_ctr(minor, LP_PSELECP | LP_PINITP);
if (total_bytes_written + bytes_written)
return total_bytes_written + bytes_written;
else
......@@ -370,7 +369,7 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count)
if (lp_check_status(minor))
{
w_ctr(minor, LP_PINITP);
w_ctr(minor, LP_PSELECP | LP_PINITP);
return rc ? rc : -EIO;
}
......@@ -414,7 +413,7 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count)
} while (count > 0);
w_ctr(minor, LP_PINITP);
w_ctr(minor, LP_PSELECP | LP_PINITP);
return total_bytes_written;
}
......
......@@ -62,7 +62,7 @@
* ever possible.
*/
#define SERIAL_PARANOIA_CHECK
#undef SERIAL_PARANOIA_CHECK
#define CONFIG_SERIAL_NOPAUSE_IO
#define SERIAL_DO_RESTART
......@@ -1661,11 +1661,15 @@ static int set_serial_info(struct async_struct * info,
if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) ||
(new_serial.type < PORT_UNKNOWN) ||
(new_serial.type > PORT_MAX) ||
(new_serial.xmit_fifo_size == 0)) {
(new_serial.type > PORT_MAX)) {
return -EINVAL;
}
if ((new_serial.type != state->type) ||
(new_serial.xmit_fifo_size <= 0))
new_serial.xmit_fifo_size =
uart_config[state->type].dfl_xmit_fifo_size;
/* Make sure address is not already in use */
if (new_serial.type) {
for (i = 0 ; i < NR_PORTS; i++)
......@@ -1714,9 +1718,6 @@ static int set_serial_info(struct async_struct * info,
check_and_exit:
if (!state->port || !state->type)
return 0;
if (state->type != old_state.type)
info->xmit_fifo_size = state->xmit_fifo_size =
uart_config[state->type].dfl_xmit_fifo_size;
if (state->flags & ASYNC_INITIALIZED) {
if (((old_state.flags & ASYNC_SPD_MASK) !=
(state->flags & ASYNC_SPD_MASK)) ||
......@@ -2566,12 +2567,15 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
int retval, line;
unsigned long page;
MOD_INC_USE_COUNT;
line = MINOR(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PORTS))
return -ENODEV;
retval = get_async_struct(line, &info);
if (retval)
return retval;
tty->driver_data = info;
info->tty = tty;
if (serial_paranoia_check(info, tty->device, "rs_open"))
return -ENODEV;
......@@ -2579,8 +2583,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
info->state->count);
#endif
tty->driver_data = info;
info->tty = tty;
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
if (!tmp_buf) {
......@@ -2615,7 +2617,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
if (retval)
return retval;
MOD_INC_USE_COUNT;
retval = block_til_ready(tty, filp, info);
if (retval) {
#ifdef SERIAL_DEBUG_OPEN
......
This diff is collapsed.
......@@ -68,12 +68,12 @@ fi
if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_NCR53C7xx" != "y" ]; then
dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI
if [ "$CONFIG_SCSI_NCR53C8XX" != "n" ]; then
bool ' detect and read serial NVRAMs' CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT
bool ' enable tagged command queueing' CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
int ' default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8
int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32
int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 20
bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE
bool ' use normal IO' CONFIG_SCSI_NCR53C8XX_IOMAPPED
int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 4
int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 5
if [ "$CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE" != "y" ]; then
if [ "$CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS" = "0" ]; then
bool ' not allow targets to disconnect' CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
......
This diff is collapsed.
......@@ -501,7 +501,7 @@ scsi_unregister(struct Scsi_Host * sh){
/* If we are removing the last host registered, it is safe to reuse
* its host number (this avoids "holes" at boot time) (DB)
*/
if (max_scsi_hosts == next_scsi_host && !scsi_loadable_module_flag)
if (max_scsi_hosts == next_scsi_host)
max_scsi_hosts--;
next_scsi_host--;
......
This diff is collapsed.
This diff is collapsed.
......@@ -274,6 +274,7 @@ static struct dev_info device_list[] =
{"NRC","MBR-7","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"NRC","MBR-7.4","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"NAKAMICH","MJ-4.8S","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"PIONEER","CD-ROM DRM-600","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"PIONEER","CD-ROM DRM-602X","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"PIONEER","CD-ROM DRM-604X","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"EMULEX","MD21/S2 ESDI","*", BLIST_SINGLELUN},
......
......@@ -180,7 +180,8 @@ void scsi_old_times_out (Scsi_Cmnd * SCpnt)
scsi_reset (SCpnt,
SCSI_RESET_ASYNCHRONOUS | SCSI_RESET_SUGGEST_BUS_RESET);
break;
case (IN_ABORT | IN_RESET | IN_RESET2):
case IN_RESET2:
case (IN_ABORT | IN_RESET2):
/* Obviously the bus reset didn't work.
* Let's try even harder and call for an HBA reset.
* Maybe the HBA itself crashed and this will shake it loose.
......
......@@ -191,7 +191,7 @@ static void send_sigio(int pid, uid_t uid, uid_t euid)
match = -p->pgrp;
if (pid != match)
continue;
if (!euid &&
if ((euid != 0) &&
(euid ^ p->suid) && (euid ^ p->uid) &&
(uid ^ p->suid) && (uid ^ p->uid))
continue;
......
......@@ -281,7 +281,6 @@ extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page,
extern void free_page_tables(struct mm_struct * mm);
extern void clear_page_tables(struct task_struct * tsk);
extern int new_page_tables(struct task_struct * tsk);
extern int copy_page_tables(struct task_struct * to);
extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size);
extern int copy_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma);
......@@ -291,6 +290,7 @@ extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t p
extern void vmtruncate(struct inode * inode, unsigned long offset);
extern void handle_mm_fault(struct task_struct *tsk,struct vm_area_struct *vma, unsigned long address, int write_access);
extern void check_pgt_cache(void);
extern void make_pages_present(unsigned long addr, unsigned long end);
extern unsigned long paging_init(unsigned long start_mem, unsigned long end_mem);
extern void mem_init(unsigned long start_mem, unsigned long end_mem);
......
......@@ -918,6 +918,22 @@ void handle_mm_fault(struct task_struct *tsk, struct vm_area_struct * vma,
oom(tsk);
}
/*
* Simplistic page force-in..
*/
void make_pages_present(unsigned long addr, unsigned long end)
{
int write;
struct vm_area_struct * vma;
vma = find_vma(current->mm, addr);
write = (vma->vm_flags & VM_WRITE) != 0;
while (addr < end) {
handle_mm_fault(current, vma, addr, write);
addr += PAGE_SIZE;
}
}
/* Low and high watermarks for page table cache.
The system should try to have pgt_water[0] <= cache elements <= pgt_water[1]
*/
......
......@@ -126,26 +126,7 @@ static int mlock_fixup(struct vm_area_struct * vma,
if (!(newflags & VM_LOCKED))
pages = -pages;
vma->vm_mm->locked_vm += pages;
#if 0
/*
* This is horribly broken. See the comment on the same
* brokenness in mm/mmap.c (essentially, this doesn't
* work anyway for PROT_NONE and writable pages, and now
* that we properly get the mmap semaphore it would just
* lock up on us).
*
* Fix the same way.
*/
if (newflags & VM_LOCKED) {
while (start < end) {
int c;
get_user(c,(int *) start);
__asm__ __volatile__("": :"r" (c));
start += PAGE_SIZE;
}
}
#endif
make_pages_present(start, end);
}
return retval;
}
......
......@@ -51,7 +51,7 @@ int sysctl_overcommit_memory;
/* Check that a process has enough memory to allocate a
* new virtual mapping.
*/
static inline int vm_enough_memory(long pages)
int vm_enough_memory(long pages)
{
/* Stupid algorithm to decide if we have enough memory: while
* simple, it hopefully works in most obvious cases.. Easy to
......@@ -318,27 +318,7 @@ unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len,
mm->total_vm += len >> PAGE_SHIFT;
if (flags & VM_LOCKED) {
mm->locked_vm += len >> PAGE_SHIFT;
/*
* This used to be just slightly broken, now it's just completely
* buggered. We can't take a page fault here, because we already
* hold the mm semaphore (as is proper). We should do this by hand
* by calling the appropriate fault-in routine.
*
* That would also fix this routine wrt writes and PROT_NONE
* areas, both of which can't be handled by the page fault
* approach anyway.
*/
#if 0
unsigned long start = addr;
do {
char c;
get_user(c,(char *) start);
len -= PAGE_SIZE;
start += PAGE_SIZE;
__asm__ __volatile__("": :"r" (c));
} while (len > 0);
#endif
make_pages_present(addr, addr + len);
}
return addr;
......
......@@ -21,6 +21,8 @@
#include <asm/system.h>
#include <asm/pgtable.h>
extern int vm_enough_memory(long pages);
static inline pte_t *get_one_pte(struct mm_struct *mm, unsigned long addr)
{
pgd_t * pgd;
......@@ -179,7 +181,7 @@ asmlinkage unsigned long sys_mremap(unsigned long addr,
* the unnecessary pages..
*/
ret = addr;
if (old_len > new_len) {
if (old_len >= new_len) {
do_munmap(addr+new_len, old_len - new_len);
goto out;
}
......@@ -205,6 +207,11 @@ asmlinkage unsigned long sys_mremap(unsigned long addr,
if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len)
> current->rlim[RLIMIT_AS].rlim_cur)
goto out;
/* Private writable mapping? Check memory availability.. */
if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE &&
!(flags & MAP_NORESERVE) &&
!vm_enough_memory((new_len - old_len) >> PAGE_SHIFT))
goto out;
/* old_len exactly to the end of the area.. */
if (old_len == vma->vm_end - addr &&
......
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