Commit 1b7a152c authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.62

parent a6614639
...@@ -733,6 +733,15 @@ S: 520 Edgemont Road ...@@ -733,6 +733,15 @@ S: 520 Edgemont Road
S: Charlottesville, Virginia 22903 S: Charlottesville, Virginia 22903
S: USA S: USA
N: Matthias Urlichs
E: urlichs@noris.de
E: urlichs@smurf.sub.org
D: Consultant, developer, kernel hacker
D: Playing with Streams, ISDN, and BSD networking code for Linux
S: Schleiermacherstrasse 12
S: 90491 Nuernberg
S: Germany
N: Patrick Volkerding N: Patrick Volkerding
E: volkerdi@ftp.cdrom.com E: volkerdi@ftp.cdrom.com
D: Produced the Slackware distribution, updated the SVGAlib D: Produced the Slackware distribution, updated the SVGAlib
...@@ -809,6 +818,7 @@ S: New York, New York 10025 ...@@ -809,6 +818,7 @@ S: New York, New York 10025
S: USA S: USA
N: Eric Youngdale N: Eric Youngdale
E: eric@aib.com
E: ericy@cais.com E: ericy@cais.com
D: General kernel hacker D: General kernel hacker
D: SCSI iso9660 and ELF D: SCSI iso9660 and ELF
...@@ -822,3 +832,10 @@ D: XFree86 and kernel development ...@@ -822,3 +832,10 @@ D: XFree86 and kernel development
S: 1507 145th Place SE #B5 S: 1507 145th Place SE #B5
S: Bellevue, Washington 98007 S: Bellevue, Washington 98007
S: USA S: USA
N: Leonard N. Zubkoff
E: lnz@dandelion.com
D: XFree86 and BusLogic driver additions
S: 3078 Sulphur Spring Court
S: San Jose, California 95148
S: USA
VERSION = 1 VERSION = 1
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 61 SUBLEVEL = 62
ARCH = i386 ARCH = i386
......
Linux kernel release 1.0 Linux kernel release 1.1.xx
These are the release notes for linux version 1.0. Read them carefully, These are the release notes for linux version 1.1. Read them carefully,
as they tell you what this is all about, explain how to install the as they tell you what this is all about, explain how to install the
kernel, and what to do if something goes wrong. kernel, and what to do if something goes wrong.
Warning: This is a work in progress. If you are not reasonably at ease with
the C programming language, GCC, installing Linux, and recovering from
system crashes, please use the 1.0 version, or wait for 1.2.
WHAT IS LINUX? WHAT IS LINUX?
Linux is a Unix clone for 386/486-based PCs written from scratch by Linux is a Unix clone for 386/486-based PCs written from scratch by
...@@ -24,20 +28,24 @@ INSTALLING the kernel: ...@@ -24,20 +28,24 @@ INSTALLING the kernel:
- If you install the full sources, do a - If you install the full sources, do a
cd /usr/src cd /usr/src
tar xvf linux-1.0.tar gzip -cd linux-1.1.XX.tar.gz | tar xfv -
to get it all put in place. to get it all put in place. Replace "XX" with the version number of the
latest kernel.
- if you install by patching, you need a *clean* 0.99.15 source tree, - Installing by patching is not worth the effort because the full set of
which presumably exists in /usr/src/linux. If so, to get the kernel patches is bigger than a new kernel distribution. Instead, get the
patched, just do a latest full source archive and install as above. Then, get all newer
patch files, and do
cd /usr/src cd /usr/src
patch -p0 < linux-1.0.patch gzip -cd patchXX.gz | patch -p0
and you should be ok. You may want to remove the backup files (xxx~ (repeat xx for all versions bigger than the version of your current
or xxx.orig), and make sure that there are no failed patches (xxx# or source tree, _in_order_) and you should be ok. You may want to remove
xxx.rej). the backup files (xxx~ or xxx.orig), and make sure that there are no
failed patches (xxx# or xxx.rej). If there are, either you or me has
made a mistake.
- make sure your /usr/include/linux and /usr/include/asm directories - make sure your /usr/include/linux and /usr/include/asm directories
are just symlinks to the kernel sources: are just symlinks to the kernel sources:
...@@ -88,10 +96,11 @@ CONFIGURING the kernel: ...@@ -88,10 +96,11 @@ CONFIGURING the kernel:
COMPILING the kernel: COMPILING the kernel:
- make sure you have gcc-2.4.5 or newer available. It seems older gcc - make sure you have gcc-2.5.8 or newer available. It seems older gcc
versions can have problems compiling newer versions of linux. If you versions can have problems compiling newer versions of linux. If you
upgrade your compiler, remember to get the new binutils package too upgrade your compiler, remember to get the new binutils package too
(for as/ld/nm and company) (for as/ld/nm and company). Do not use gcc-2.6.0; it has a few serious
bugs.
- do a "make zImage" to create a compressed kernel image. If you want - do a "make zImage" to create a compressed kernel image. If you want
to make a bootdisk (without root filesystem or lilo), insert a floppy to make a bootdisk (without root filesystem or lilo), insert a floppy
...@@ -148,7 +157,7 @@ IF SOMETHING GOES WRONG: ...@@ -148,7 +157,7 @@ IF SOMETHING GOES WRONG:
unable to handle kernel paging request at address C0000010 unable to handle kernel paging request at address C0000010
Oops: 0002 Oops: 0002
EIP: 0010:xxxxxxxx EIP: 0010:XXXXXXXX
eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx
esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx
ds: xxxx es: xxxx fs: xxxx gs: xxxx ds: xxxx es: xxxx fs: xxxx gs: xxxx
...@@ -194,3 +203,16 @@ IF SOMETHING GOES WRONG: ...@@ -194,3 +203,16 @@ IF SOMETHING GOES WRONG:
kernel image or similar), telling me as much about your setup as kernel image or similar), telling me as much about your setup as
possible will help. possible will help.
- alternately, you can use gdb on a running kernel. (read-only; i.e. you
cannot change values or set break points.) To do this, first compile the
kernel with -g; edit arch/i386/Makefile appropriately, then do a "make
clean". You'll also need to enable CONFIG_PROC_FS (via "make config").
After you've rebooted with the new kernel, do "gdb tools/zSystem
/proc/kcore". You can now use all the usual gdb commands. The command to
look up the point where your system crashed is "l *0xXXXXXXXX". (Replace
the XXXes with the EIP value.)
gdb'ing a non-running kernel currently fails because gdb (wrongly)
disregards the starting offset for which the kernel is compiled.
...@@ -107,6 +107,7 @@ if [ "$CONFIG_NET_ISA" = "y" ]; then ...@@ -107,6 +107,7 @@ if [ "$CONFIG_NET_ISA" = "y" ]; then
bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n
bool 'Cabletron E21xx support (not recommended)' CONFIG_E2100 n bool 'Cabletron E21xx support (not recommended)' CONFIG_E2100 n
bool 'DEPCA support' CONFIG_DEPCA n bool 'DEPCA support' CONFIG_DEPCA n
bool 'EtherWorks 3 support' CONFIG_EWRK3 n
if [ "$CONFIG_NET_ALPHA" = "y" ]; then if [ "$CONFIG_NET_ALPHA" = "y" ]; then
bool 'EtherExpress support' CONFIG_EEXPRESS n bool 'EtherExpress support' CONFIG_EEXPRESS n
bool 'AT1700 support' CONFIG_AT1700 n bool 'AT1700 support' CONFIG_AT1700 n
......
...@@ -2787,6 +2787,9 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end) ...@@ -2787,6 +2787,9 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end)
} }
else if (sony_cd_base_io != 0) else if (sony_cd_base_io != 0)
{ {
tmp_irq = irq_used; /* Need IRQ 0 because we can't sleep here. */
irq_used = 0;
get_drive_configuration(sony_cd_base_io, get_drive_configuration(sony_cd_base_io,
drive_config.exec_status, drive_config.exec_status,
&res_size); &res_size);
...@@ -2794,9 +2797,12 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end) ...@@ -2794,9 +2797,12 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end)
{ {
drive_found = 1; drive_found = 1;
} }
irq_used = tmp_irq;
} }
else else
{ {
irq_used = 0;
i = 0; i = 0;
while ( (cdu31a_addresses[i].base != 0) while ( (cdu31a_addresses[i].base != 0)
&& (!drive_found)) && (!drive_found))
...@@ -2844,12 +2850,18 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end) ...@@ -2844,12 +2850,18 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end)
tmp_irq = autoirq_report(10); tmp_irq = autoirq_report(10);
disable_interrupts(); disable_interrupts();
irq_used = 0;
set_drive_params(); set_drive_params();
irq_used = tmp_irq; irq_used = tmp_irq;
} }
else else
{ {
tmp_irq = irq_used; /* Need IRQ 0 because we can't sleep here. */
irq_used = 0;
set_drive_params(); set_drive_params();
irq_used = tmp_irq;
} }
if (irq_used > 0) if (irq_used > 0)
......
...@@ -2628,7 +2628,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -2628,7 +2628,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
case FDCLRPRM: case FDCLRPRM:
LOCK_FDC(drive,1); LOCK_FDC(drive,1);
current_type[drive] = NULL; current_type[drive] = NULL;
floppy_sizes[drive] = 2; floppy_sizes[drive] = MAX_DISK_SIZE;
UDRS->keep_data = 0; UDRS->keep_data = 0;
return invalidate_drive(device); return invalidate_drive(device);
case FDFMTEND: case FDFMTEND:
...@@ -3159,7 +3159,6 @@ static int floppy_grab_irq_and_dma(void) ...@@ -3159,7 +3159,6 @@ static int floppy_grab_irq_and_dma(void)
static void floppy_release_irq_and_dma(void) static void floppy_release_irq_and_dma(void)
{ {
int i;
cli(); cli();
if (--usage_count){ if (--usage_count){
sti(); sti();
...@@ -3170,7 +3169,9 @@ static void floppy_release_irq_and_dma(void) ...@@ -3170,7 +3169,9 @@ static void floppy_release_irq_and_dma(void)
free_dma(FLOPPY_DMA); free_dma(FLOPPY_DMA);
disable_irq(FLOPPY_IRQ); disable_irq(FLOPPY_IRQ);
free_irq(FLOPPY_IRQ); free_irq(FLOPPY_IRQ);
/* switch off dma gates */ set_dor(0, ~0, 8);
for(i=0; i< N_FDC; i++) #if N_FDC > 1
set_dor(i, ~8, 0); if(fdc.address != -1)
set_dor(1, ~8, 0);
#endif
} }
Wed Nov 2 10:32:36 1994 Theodore Y. Ts'o (tytso@rt-11)
* n_tty.c (n_tty_receive_room): Only allow excess characters
through if we are in ICANON mode *and* there are other no
pending lines in the buffer. Otherwise cut and paste over
4k breaks.
Sat Oct 29 18:17:34 1994 Theodore Y. Ts'o (tytso@rt-11) Sat Oct 29 18:17:34 1994 Theodore Y. Ts'o (tytso@rt-11)
* serial.c (rs_ioctl, get_lsr_info): Added patch suggested by Arne * serial.c (rs_ioctl, get_lsr_info): Added patch suggested by Arne
......
...@@ -585,11 +585,12 @@ static int n_tty_receive_room(struct tty_struct *tty) ...@@ -585,11 +585,12 @@ static int n_tty_receive_room(struct tty_struct *tty)
int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
/* /*
* If we are doing input canonicalization, let as many * If we are doing input canonicalization, and there are no
* characters through as possible, so that the excess * pending newlines, let characters through without limit, so
* characters can be "beeped". * that erase characters will be handled. Other excess
* characters will be beeped.
*/ */
if (L_ICANON(tty)) if (tty->icanon && !tty->canon_data)
return N_TTY_BUF_SIZE; return N_TTY_BUF_SIZE;
if (left > 0) if (left > 0)
......
...@@ -1009,6 +1009,12 @@ static void release_dev(struct file * filp) ...@@ -1009,6 +1009,12 @@ static void release_dev(struct file * filp)
(tty->ldisc.close)(tty); (tty->ldisc.close)(tty);
tty->ldisc = ldiscs[N_TTY]; tty->ldisc = ldiscs[N_TTY];
tty->termios->c_line = N_TTY; tty->termios->c_line = N_TTY;
if (o_tty) {
if (o_tty->ldisc.close)
(o_tty->ldisc.close)(o_tty);
o_tty->ldisc = ldiscs[N_TTY];
o_tty->termios->c_line = N_TTY;
}
tty->driver.table[idx] = NULL; tty->driver.table[idx] = NULL;
if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) { if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) {
......
This file contains brief information about the SCSI tape driver. This file contains brief information about the SCSI tape driver.
Last modified: Wed Jun 22 23:38:47 1994 by root@kai.home Last modified: Sun Oct 16 19:20:03 1994 by root@kai.home
BASICS BASICS
...@@ -78,7 +78,10 @@ MTBSF Space backward over count filemarks. Tape positioned before ...@@ -78,7 +78,10 @@ MTBSF Space backward over count filemarks. Tape positioned before
MTBSFM As above but ape positioned after filemark. MTBSFM As above but ape positioned after filemark.
MTFSR Space forward over count records. MTFSR Space forward over count records.
MTBSR Space backward over count records. MTBSR Space backward over count records.
MTFSS Space forward over count setmarks.
MTBSS Space backward over coutn setmarks.
MTWEOF Write count filemarks. MTWEOF Write count filemarks.
MTWSM Write count setmarks.
MTREW Rewind tape. MTREW Rewind tape.
MTOFFL Set device off line (often rewind plus eject). MTOFFL Set device off line (often rewind plus eject).
MTNOP Do nothing except flush the buffers. MTNOP Do nothing except flush the buffers.
...@@ -125,9 +128,8 @@ MTIOCGET Returns some status information. ...@@ -125,9 +128,8 @@ MTIOCGET Returns some status information.
The current block size and the density code are stored in the field The current block size and the density code are stored in the field
mt_dsreg (shifts for the subfields are MT_ST_BLKSIZE_SHIFT and mt_dsreg (shifts for the subfields are MT_ST_BLKSIZE_SHIFT and
MT_ST_DENSITY_SHIFT). MT_ST_DENSITY_SHIFT).
The write protect bit in mt_gstat is set if the tape is write The WR_PROT, BOT, EOF, EOT, EOD, and D_[800,1600,6250]_BPI
protected. status bits reflect the tape status. The other bits are not used.
The other fields are empty.
MISCELLANEOUS COMPILE OPTIONS MISCELLANEOUS COMPILE OPTIONS
......
/* fdomain.c -- Future Domain TMC-16x0 SCSI driver /* fdomain.c -- Future Domain TMC-16x0 SCSI driver
* Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu
* Revised: Sat Jul 30 22:06:37 1994 by faith@cs.unc.edu * Revised: Wed Nov 2 16:37:58 1994 by faith@cs.unc.edu
* Author: Rickard E. Faith, faith@cs.unc.edu * Author: Rickard E. Faith, faith@cs.unc.edu
* Copyright 1992, 1993, 1994 Rickard E. Faith * Copyright 1992, 1993, 1994 Rickard E. Faith
* *
* $Id: fdomain.c,v 5.18 1994/07/31 03:09:15 faith Exp $ * $Id: fdomain.c,v 5.20 1994/11/02 21:38:33 root Exp $
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
...@@ -38,10 +38,20 @@ ...@@ -38,10 +38,20 @@
signature, then the driver may fail to function after the board is signature, then the driver may fail to function after the board is
detected. detected.
The following BIOS versions are supported: 2.0, 3.0, 3.2, and 3.4. The following BIOS versions are supported: 2.0, 3.0, 3.2, 3.4, and 3.5.
The following chips are supported: TMC-1800, TMC-18C50, TMC-18C30. The following chips are supported: TMC-1800, TMC-18C50, TMC-18C30.
Reports suggest that the driver will also work with the 36C70 chip. Reports suggest that the driver will also work with the 36C70 chip.
Please note that the drive ordering that Future Domain implemented in BIOS
versions 3.4 and 3.5 is the opposite of the order (currently) used by the
rest of the SCSI industry. If you have BIOS version 3.4 or 3.5, and have
more then one drive, then the drive ordering will be the reverse of that
which you see under DOS. For example, under DOS SCSI ID 0 will be D: and
SCSI ID 1 will be C: (the boot device). Under Linux, SCSI ID 0 will be
/dev/sda and SCSI ID 1 will be /dev/sdb. The Linux ordering is consistent
with that provided by all the other SCSI drivers for Linux. If you want
this changed, send me patches that are protected by #ifdefs.
If you have a TMC-8xx or TMC-9xx board, then this is not the driver for If you have a TMC-8xx or TMC-9xx board, then this is not the driver for
your board. Please refer to the Seagate driver for more information and your board. Please refer to the Seagate driver for more information and
possible support. possible support.
...@@ -120,6 +130,9 @@ ...@@ -120,6 +130,9 @@
patches that support the TMC-3260, a PCI bus card with the 36C70 chip. patches that support the TMC-3260, a PCI bus card with the 36C70 chip.
The 36C70 chip appears to be "completely compatible" with the 18C30 chip. The 36C70 chip appears to be "completely compatible" with the 18C30 chip.
Thanks to Eric Kasten (tigger@petroglyph.cl.msu.edu) for providing the
patch for the version 3.5 BIOS.
All of the alpha testers deserve much thanks. All of the alpha testers deserve much thanks.
...@@ -133,14 +146,14 @@ ...@@ -133,14 +146,14 @@
devices support parity, then you can probably get the driver to work by devices support parity, then you can probably get the driver to work by
turning this option off. I have no way of testing this, however. turning this option off. I have no way of testing this, however.
FIFO_COUNT: The host adapter has an 8K cache. When this many 512 byte FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the
blocks are filled by the SCSI device, an interrupt will be raised. 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by
Therefore, this could be as low as 0, or as high as 16. Note, however, the SCSI device, an interrupt will be raised. Therefore, this could be as
that values which are too high or too low seem to prevent any interrupts low as 0, or as high as 16. Note, however, that values which are too high
from occuring, and thereby lock up the machine. I have found that 2 is a or too low seem to prevent any interrupts from occuring, and thereby lock
good number, but throughput may be increased by changing this value to up the machine. I have found that 2 is a good number, but throughput may
values which are close to 2. Please let me know if you try any different be increased by changing this value to values which are close to 2.
values. Please let me know if you try any different values.
DO_DETECT: This activates some old scan code which was needed before the DO_DETECT: This activates some old scan code which was needed before the
high level drivers got fixed. If you are having trouble with the driver, high level drivers got fixed. If you are having trouble with the driver,
...@@ -150,11 +163,11 @@ ...@@ -150,11 +163,11 @@
RESELECTION: This is no longer an option, since I gave up trying to RESELECTION: This is no longer an option, since I gave up trying to
implement it in version 4.x of this driver. It did not improve implement it in version 4.x of this driver. It did not improve
performance at all and made the driver unstable (because I never found one performance at all and made the driver unstable (because I never found one
of the two race conditions which were introduced by multiple outstanding of the two race conditions which were introduced by the multiple
commands). The instability seems a very high price to pay just so that outstanding command code). The instability seems a very high price to pay
you don't have to wait for the tape to rewind. When I have time, I will just so that you don't have to wait for the tape to rewind. If you want
work on this again. In the interim, if anyone wants to work on the code, this feature implemented, send me patches. I'll be happy to send a copy
I can give them my latest version. of my (broken) driver to anyone who would like to see a copy.
**************************************************************************/ **************************************************************************/
...@@ -169,7 +182,7 @@ ...@@ -169,7 +182,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#define VERSION "$Revision: 5.18 $" #define VERSION "$Revision: 5.20 $"
/* START OF USER DEFINABLE OPTIONS */ /* START OF USER DEFINABLE OPTIONS */
...@@ -292,7 +305,9 @@ static void *addresses[] = { ...@@ -292,7 +305,9 @@ static void *addresses[] = {
(void *)0xc8000, (void *)0xc8000,
(void *)0xca000, (void *)0xca000,
(void *)0xce000, (void *)0xce000,
(void *)0xde000 }; (void *)0xde000,
(void *)0xd0000, /* Extra addresses for PCI boards */
};
#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
...@@ -341,6 +356,7 @@ struct signature { ...@@ -341,6 +356,7 @@ struct signature {
{ "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 }, { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
{ "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 }, { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
{ "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 }, { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
{ "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
{ "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 }, { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
{ "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 }, { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
...@@ -459,11 +475,15 @@ static int fdomain_is_valid_port( int port ) ...@@ -459,11 +475,15 @@ static int fdomain_is_valid_port( int port )
#endif #endif
/* Check for board with lowest bios_base -- /* Check for board with lowest bios_base --
this isn't valid for the 18c30, so just this isn't valid for the 18c30 or for
assume we have the right board. */ boards on the PCI bus, so just assume we
have the right board. */
if (chip != tmc18c30 && addresses[ (options & 0xc0) >> 6 ] != bios_base) if (chip != tmc18c30
return 0; && !PCI_bus
&& addresses[ (options & 0xc0) >> 6 ] != bios_base) return 0;
/* Get the IRQ from the options. */
interrupt_level = ints[ (options & 0x0e) >> 1 ]; interrupt_level = ints[ (options & 0x0e) >> 1 ];
...@@ -587,18 +607,15 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) ...@@ -587,18 +607,15 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
} }
} else { } else {
/* The proper way of doing this is to use the PCI BIOS call /* The proper way of doing this is to use ask the PCI bus for the
(interrupt 0x1a) to determine the device IRQ and interrupt device IRQ and interrupt level.
level. Then the port_base will be in configuration register
0x10 (and configuration register 0x30 will contain the value of
bios_base).
Until the Linux kernel supports this sort of PCI bus query, we Until the Linux kernel supports this sort of PCI bus query, we
scan down a bunch of addresses (Future Domain folks say we scan down a bunch of addresses (Future Domain tech support says
should find the address before we get to 0xf800). This works we will probably find the address before we get to 0xf800).
fine on some systems -- other systems may have to scan more This works fine on some systems -- other systems may have to
addresses. If you have to modify this section for your scan more addresses. If you have to modify this section for
installation, please send mail to faith@cs.unc.edu. */ your installation, please send mail to faith@cs.unc.edu. */
for (i = 0xff00; !flag && i > 0xf000; i -= 8) { for (i = 0xff00; !flag && i > 0xf000; i -= 8) {
port_base = i; port_base = i;
...@@ -798,6 +815,7 @@ static int fdomain_select( int target ) ...@@ -798,6 +815,7 @@ static int fdomain_select( int target )
{ {
int status; int status;
unsigned long timeout; unsigned long timeout;
static int flag = 0;
outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
...@@ -806,11 +824,9 @@ static int fdomain_select( int target ) ...@@ -806,11 +824,9 @@ static int fdomain_select( int target )
/* Stop arbitration and enable parity */ /* Stop arbitration and enable parity */
outb( PARITY_MASK, TMC_Cntl_port ); outb( PARITY_MASK, TMC_Cntl_port );
#if 0 timeout = jiffies + 35; /* 350mS -- because of timeouts
timeout = jiffies + 25; /* 250mS */ (was 250mS) */
#else
timeout = jiffies + 35; /* 350mS -- because of timeouts */
#endif
while (jiffies < timeout) { while (jiffies < timeout) {
status = inb( SCSI_Status_port ); /* Read adapter status */ status = inb( SCSI_Status_port ); /* Read adapter status */
if (status & 1) { /* Busy asserted */ if (status & 1) { /* Busy asserted */
...@@ -825,7 +841,12 @@ static int fdomain_select( int target ) ...@@ -825,7 +841,12 @@ static int fdomain_select( int target )
if (!target) printk( "Selection failed\n" ); if (!target) printk( "Selection failed\n" );
#endif #endif
#if ERRORS_ONLY #if ERRORS_ONLY
if (!target) printk( "Future Domain: Selection failed\n" ); if (!target) {
if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */
++flag;
else
printk( "Future Domain: Selection failed\n" );
}
#endif #endif
return 1; return 1;
} }
......
...@@ -157,6 +157,7 @@ static struct blist blacklist[] = ...@@ -157,6 +157,7 @@ static struct blist blacklist[] =
* controller, which causes SCSI code to reset bus.*/ * controller, which causes SCSI code to reset bus.*/
{"QUANTUM","LPS525S","3110"},/* Locks sometimes if polled for lun != 0 */ {"QUANTUM","LPS525S","3110"},/* Locks sometimes if polled for lun != 0 */
{"QUANTUM","PD1225S","3110"},/* Locks sometimes if polled for lun != 0 */ {"QUANTUM","PD1225S","3110"},/* Locks sometimes if polled for lun != 0 */
{"MEDIAVIS","CDR-H93MV","1.31"}, /* Locks up if polled for lun != 0 */
{NULL, NULL, NULL}}; {NULL, NULL, NULL}};
static int blacklisted(unsigned char * response_data){ static int blacklisted(unsigned char * response_data){
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
Copyright 1992, 1993, 1994 Kai Makisara Copyright 1992, 1993, 1994 Kai Makisara
email makisara@vtinsx.ins.vtt.fi or Kai.Makisara@vtt.fi email makisara@vtinsx.ins.vtt.fi or Kai.Makisara@vtt.fi
Last modified: Wed Jun 22 23:37:10 1994 by root@kai.home Last modified: Tue Oct 25 19:37:33 1994 by root@kai.home
*/ */
#include <linux/fs.h> #include <linux/fs.h>
...@@ -415,6 +415,7 @@ scsi_tape_open(struct inode * inode, struct file * filp) ...@@ -415,6 +415,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
STp->dirty = 0; STp->dirty = 0;
STp->rw = ST_IDLE; STp->rw = ST_IDLE;
if (STp->eof != ST_EOD) /* Save EOD across opens */
STp->eof = ST_NOEOF; STp->eof = ST_NOEOF;
STp->eof_hit = 0; STp->eof_hit = 0;
STp->recover_count = 0; STp->recover_count = 0;
...@@ -450,6 +451,7 @@ scsi_tape_open(struct inode * inode, struct file * filp) ...@@ -450,6 +451,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) ); if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
(STp->mt_status)->mt_fileno = STp->drv_block = 0; (STp->mt_status)->mt_fileno = STp->drv_block = 0;
STp->eof = ST_NOEOF;
} }
if ((STp->buffer)->last_result_fatal != 0) { if ((STp->buffer)->last_result_fatal != 0) {
...@@ -601,7 +603,7 @@ scsi_tape_close(struct inode * inode, struct file * filp) ...@@ -601,7 +603,7 @@ scsi_tape_close(struct inode * inode, struct file * filp)
#ifdef DEBUG #ifdef DEBUG
if (debugging) if (debugging)
printk("st%d: File length %ld bytes.\n", dev, filp->f_pos); printk("st%d: File length %ld bytes.\n", dev, (long)(filp->f_pos));
#endif #endif
if (result == 0 || result == (-ENOSPC)) { if (result == 0 || result == (-ENOSPC)) {
...@@ -1053,6 +1055,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -1053,6 +1055,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
printk("st%d: Zero returned for first BLANK CHECK after EOF.\n", printk("st%d: Zero returned for first BLANK CHECK after EOF.\n",
dev); dev);
#endif #endif
STp->eof = ST_EOD;
return 0; /* First BLANK_CHECK after EOF */ return 0; /* First BLANK_CHECK after EOF */
} }
else else
...@@ -1098,7 +1101,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -1098,7 +1101,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
STp->eof_hit = 1; STp->eof_hit = 1;
SCpnt->request.dev = -1; /* Mark as not busy */ SCpnt->request.dev = -1; /* Mark as not busy */
if (total == 0 && STp->eof == ST_FM) { if (total == 0 && STp->eof == ST_FM) {
STp->eof = 0; STp->eof = ST_NOEOF;
STp->drv_block = 0; STp->drv_block = 0;
if (STp->moves_after_eof > 1) if (STp->moves_after_eof > 1)
STp->moves_after_eof = 0; STp->moves_after_eof = 0;
...@@ -1253,18 +1256,58 @@ st_int_ioctl(struct inode * inode,struct file * file, ...@@ -1253,18 +1256,58 @@ st_int_ioctl(struct inode * inode,struct file * file,
if (blkno >= 0) if (blkno >= 0)
blkno -= arg; blkno -= arg;
break; break;
case MTFSS:
cmd[0] = SPACE;
cmd[1] = 0x04; /* Space Setmarks */
cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8);
cmd[4] = arg;
#ifdef DEBUG
if (debugging)
printk("st%d: Spacing tape forward %d setmarks.\n", dev,
cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
#endif
if (arg != 0)
blkno = fileno = (-1);
break;
case MTBSS:
cmd[0] = SPACE;
cmd[1] = 0x04; /* Space Setmarks */
ltmp = (-arg);
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
#ifdef DEBUG
if (debugging) {
if (cmd[2] & 0x80)
ltmp = 0xff000000;
ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
printk("st%d: Spacing tape backward %ld setmarks.\n", dev, (-ltmp));
}
#endif
if (arg != 0)
blkno = fileno = (-1);
break;
case MTWEOF: case MTWEOF:
case MTWSM:
if (STp->write_prot) if (STp->write_prot)
return (-EACCES); return (-EACCES);
cmd[0] = WRITE_FILEMARKS; cmd[0] = WRITE_FILEMARKS;
if (cmd_in == MTWSM)
cmd[1] = 2;
cmd[2] = (arg >> 16); cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8); cmd[3] = (arg >> 8);
cmd[4] = arg; cmd[4] = arg;
timeout = ST_TIMEOUT; timeout = ST_TIMEOUT;
#ifdef DEBUG #ifdef DEBUG
if (debugging) if (debugging) {
if (cmd_in == MTWEOF)
printk("st%d: Writing %d filemarks.\n", dev, printk("st%d: Writing %d filemarks.\n", dev,
cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
else
printk("st%d: Writing %d setmarks.\n", dev,
cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
}
#endif #endif
fileno += arg; fileno += arg;
blkno = 0; blkno = 0;
...@@ -1503,9 +1546,12 @@ st_int_ioctl(struct inode * inode,struct file * file, ...@@ -1503,9 +1546,12 @@ st_int_ioctl(struct inode * inode,struct file * file,
else else
STp->drv_block = (-1); STp->drv_block = (-1);
} }
if (STp->eof == ST_NOEOF &&
(SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK)
STp->eof = ST_EOD;
} }
return ioctl_result ; return ioctl_result;
} }
...@@ -1576,9 +1622,26 @@ st_ioctl(struct inode * inode,struct file * file, ...@@ -1576,9 +1622,26 @@ st_ioctl(struct inode * inode,struct file * file,
(STp->mt_status)->mt_blkno -= ((STp->buffer)->buffer_bytes + (STp->mt_status)->mt_blkno -= ((STp->buffer)->buffer_bytes +
STp->block_size - 1) / STp->block_size; STp->block_size - 1) / STp->block_size;
} }
(STp->mt_status)->mt_gstat = 0; (STp->mt_status)->mt_gstat = 0;
if (STp->drv_write_prot) if (STp->drv_write_prot)
(STp->mt_status)->mt_gstat |= GMT_WR_PROT(0xffffffff); (STp->mt_status)->mt_gstat |= GMT_WR_PROT(0xffffffff);
if ((STp->mt_status)->mt_blkno == 0) {
if ((STp->mt_status)->mt_fileno == 0)
(STp->mt_status)->mt_gstat |= GMT_BOT(0xffffffff);
else
(STp->mt_status)->mt_gstat |= GMT_EOF(0xffffffff);
}
if (STp->eof == ST_EOM_OK || STp->eof == ST_EOM_ERROR)
(STp->mt_status)->mt_gstat |= GMT_EOT(0xffffffff);
else if (STp->eof == ST_EOD)
(STp->mt_status)->mt_gstat |= GMT_EOD(0xffffffff);
if (STp->density == 1)
(STp->mt_status)->mt_gstat |= GMT_D_800(0xffffffff);
else if (STp->density == 2)
(STp->mt_status)->mt_gstat |= GMT_D_1600(0xffffffff);
else if (STp->density == 3)
(STp->mt_status)->mt_gstat |= GMT_D_6250(0xffffffff);
memcpy_tofs((char *)arg, (char *)(STp->mt_status), memcpy_tofs((char *)arg, (char *)(STp->mt_status),
sizeof(struct mtget)); sizeof(struct mtget));
......
...@@ -55,6 +55,7 @@ typedef struct { ...@@ -55,6 +55,7 @@ typedef struct {
#define ST_FM 1 #define ST_FM 1
#define ST_EOM_OK 2 #define ST_EOM_OK 2
#define ST_EOM_ERROR 3 #define ST_EOM_ERROR 3
#define ST_EOD 4
/* Values of rw */ /* Values of rw */
#define ST_IDLE 0 #define ST_IDLE 0
......
...@@ -112,7 +112,7 @@ hw_entry hw_table[] = ...@@ -112,7 +112,7 @@ hw_entry hw_table[] =
{B (OPT_SB), B (OPT_PAS), "SBPRO", 1, 0, 1}, {B (OPT_SB), B (OPT_PAS), "SBPRO", 1, 0, 1},
{B (OPT_SB) | B (OPT_SBPRO), B (OPT_PAS), "SB16", 1, 0, 1}, {B (OPT_SB) | B (OPT_SBPRO), B (OPT_PAS), "SB16", 1, 0, 1},
{B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_GUS), 0, "AUDIO", 1, 0, 1}, {B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_GUS) | B (OPT_MSS), 0, "AUDIO", 1, 0, 1},
{B (OPT_MPU401), 0, "MIDI_AUTO", 0, OPT_MIDI, 0}, {B (OPT_MPU401), 0, "MIDI_AUTO", 0, OPT_MIDI, 0},
{B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_MPU401) | B (OPT_GUS), 0, "MIDI", 1, 0, 1}, {B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_MPU401) | B (OPT_GUS), 0, "MIDI", 1, 0, 1},
{B (OPT_ADLIB), 0, "YM3812_AUTO", 0, OPT_YM3812, 0}, {B (OPT_ADLIB), 0, "YM3812_AUTO", 0, OPT_YM3812, 0},
......
...@@ -43,9 +43,15 @@ static struct fileinfo files[SND_NDEVS]; ...@@ -43,9 +43,15 @@ static struct fileinfo files[SND_NDEVS];
int int
snd_ioctl_return (int *addr, int value) snd_ioctl_return (int *addr, int value)
{ {
int error;
if (value < 0) if (value < 0)
return value; return value;
error = verify_area(VERIFY_WRITE, addr, sizeof(int));
if (error)
return error;
PUT_WORD_TO_USER (addr, 0, value); PUT_WORD_TO_USER (addr, 0, value);
return 0; return 0;
} }
......
...@@ -31,6 +31,7 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -31,6 +31,7 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
unsigned int dev; unsigned int dev;
struct buffer_head * bh, *bufferlist[NBUF]; struct buffer_head * bh, *bufferlist[NBUF];
register char * p; register char * p;
int excess;
write_error = buffercount = 0; write_error = buffercount = 0;
dev = inode->i_rdev; dev = inode->i_rdev;
...@@ -86,8 +87,9 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -86,8 +87,9 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2; blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2;
if (block + blocks > size) blocks = size - block; if (block + blocks > size) blocks = size - block;
if (blocks > NBUF) blocks=NBUF; if (blocks > NBUF) blocks=NBUF;
blocks -= (block % blocks_per_cluster); excess = (block + blocks) % blocks_per_cluster;
if(!blocks) blocks = 1; if ( blocks > excess )
blocks -= excess;
bhlist[0] = bh; bhlist[0] = bh;
for(i=1; i<blocks; i++){ for(i=1; i<blocks; i++){
if(((i+block) % blocks_per_cluster) == 0) { if(((i+block) % blocks_per_cluster) == 0) {
...@@ -102,6 +104,7 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -102,6 +104,7 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
}; };
ll_rw_block(READ, blocks, bhlist); ll_rw_block(READ, blocks, bhlist);
for(i=1; i<blocks; i++) brelse(bhlist[i]); for(i=1; i<blocks; i++) brelse(bhlist[i]);
wait_on_buffer(bh);
}; };
}; };
...@@ -168,6 +171,7 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -168,6 +171,7 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
loff_t size; loff_t size;
unsigned int dev; unsigned int dev;
int read; int read;
int excess;
dev = inode->i_rdev; dev = inode->i_rdev;
blocksize = BLOCK_SIZE; blocksize = BLOCK_SIZE;
...@@ -205,7 +209,9 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -205,7 +209,9 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
if (filp->f_reada) { if (filp->f_reada) {
if (blocks < read_ahead[MAJOR(dev)] / (blocksize >> 9)) if (blocks < read_ahead[MAJOR(dev)] / (blocksize >> 9))
blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9); blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9);
blocks -= (block % blocks_per_cluster); excess = (block + blocks) % blocks_per_cluster;
if ( blocks > excess )
blocks -= excess;
if (rblocks > blocks) if (rblocks > blocks)
blocks = rblocks; blocks = rblocks;
......
...@@ -50,8 +50,6 @@ ...@@ -50,8 +50,6 @@
asmlinkage int sys_exit(int exit_code); asmlinkage int sys_exit(int exit_code);
asmlinkage int sys_brk(unsigned long); asmlinkage int sys_brk(unsigned long);
extern void shm_exit (void);
static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(int fd); static int load_aout_library(int fd);
static int aout_core_dump(long signr, struct pt_regs * regs); static int aout_core_dump(long signr, struct pt_regs * regs);
...@@ -197,6 +195,8 @@ static int aout_core_dump(long signr, struct pt_regs * regs) ...@@ -197,6 +195,8 @@ static int aout_core_dump(long signr, struct pt_regs * regs)
goto end_coredump; goto end_coredump;
if (!inode->i_op || !inode->i_op->default_file_ops) if (!inode->i_op || !inode->i_op->default_file_ops)
goto end_coredump; goto end_coredump;
if (get_write_access(inode))
goto end_coredump;
file.f_mode = 3; file.f_mode = 3;
file.f_flags = 0; file.f_flags = 0;
file.f_count = 1; file.f_count = 1;
...@@ -206,7 +206,7 @@ static int aout_core_dump(long signr, struct pt_regs * regs) ...@@ -206,7 +206,7 @@ static int aout_core_dump(long signr, struct pt_regs * regs)
file.f_op = inode->i_op->default_file_ops; file.f_op = inode->i_op->default_file_ops;
if (file.f_op->open) if (file.f_op->open)
if (file.f_op->open(inode,&file)) if (file.f_op->open(inode,&file))
goto end_coredump; goto done_coredump;
if (!file.f_op->write) if (!file.f_op->write)
goto close_coredump; goto close_coredump;
has_dumped = 1; has_dumped = 1;
...@@ -273,6 +273,8 @@ static int aout_core_dump(long signr, struct pt_regs * regs) ...@@ -273,6 +273,8 @@ static int aout_core_dump(long signr, struct pt_regs * regs)
close_coredump: close_coredump:
if (file.f_op->release) if (file.f_op->release)
file.f_op->release(inode,&file); file.f_op->release(inode,&file);
done_coredump:
put_write_access(inode);
end_coredump: end_coredump:
set_fs(fs); set_fs(fs);
iput(inode); iput(inode);
...@@ -529,8 +531,6 @@ void flush_old_exec(struct linux_binprm * bprm) ...@@ -529,8 +531,6 @@ void flush_old_exec(struct linux_binprm * bprm)
current->comm[i++] = ch; current->comm[i++] = ch;
} }
current->comm[i] = '\0'; current->comm[i] = '\0';
if (current->shm)
shm_exit();
/* Release all of the old mmap stuff. */ /* Release all of the old mmap stuff. */
mpnt = current->mm->mmap; mpnt = current->mm->mmap;
...@@ -636,6 +636,11 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs ...@@ -636,6 +636,11 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
retval = -EACCES; retval = -EACCES;
goto exec_error2; goto exec_error2;
} }
/* better not execute files which are being written to */
if (bprm.inode->i_wcount > 0) {
retval = -ETXTBSY;
goto exec_error2;
}
memset(bprm.buf,0,sizeof(bprm.buf)); memset(bprm.buf,0,sizeof(bprm.buf));
old_fs = get_fs(); old_fs = get_fs();
set_fs(get_ds()); set_fs(get_ds());
...@@ -844,17 +849,15 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -844,17 +849,15 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
goto beyond_if; goto beyond_if;
} }
if (ex.a_text) {
error = do_mmap(file, N_TXTADDR(ex), ex.a_text, error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_SHARED | MAP_DENYWRITE | MAP_EXECUTABLE, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset); fd_offset);
if (error != N_TXTADDR(ex)) { if (error != N_TXTADDR(ex)) {
sys_close(fd); sys_close(fd);
send_sig(SIGSEGV, current, 0); send_sig(SIGKILL, current, 0);
return -EINVAL; return error;
}
} }
error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data, error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data,
...@@ -863,8 +866,8 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -863,8 +866,8 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
fd_offset + ex.a_text); fd_offset + ex.a_text);
sys_close(fd); sys_close(fd);
if (error != N_TXTADDR(ex) + ex.a_text) { if (error != N_TXTADDR(ex) + ex.a_text) {
send_sig(SIGSEGV, current, 0); send_sig(SIGKILL, current, 0);
return -EINVAL; return error;
} }
} }
beyond_if: beyond_if:
......
...@@ -6,6 +6,12 @@ Changes from version 0.5 to version 0.5a ...@@ -6,6 +6,12 @@ Changes from version 0.5 to version 0.5a
- The famous readdir() bug has been fixed by Stephen Tweedie. - The famous readdir() bug has been fixed by Stephen Tweedie.
- Added a revision level in the superblock. - Added a revision level in the superblock.
- Full support for O_SYNC flag of the open system call. - Full support for O_SYNC flag of the open system call.
- New mount options: `resuid=#uid' and `resgid=#gid'. `resuid' causes
ext2fs to consider user #uid like root for the reserved blocks.
`resgid' acts the same way with group #gid. New fields in the
superblock contain default values for resuid and resgid and can
be modified by tune2fs.
Idea comes from Rene Cougnenc <cougnenc@renux.frmug.fr.net>.
- New mount options: `bsddf' and `minixdf'. `bsddf' causes ext2fs - New mount options: `bsddf' and `minixdf'. `bsddf' causes ext2fs
to remove the blocks used for FS structures from the total block to remove the blocks used for FS structures from the total block
count in statfs. With `minixdf', ext2fs mimics Minix behavior count in statfs. With `minixdf', ext2fs mimics Minix behavior
......
...@@ -270,7 +270,10 @@ int ext2_new_block (struct super_block * sb, unsigned long goal, ...@@ -270,7 +270,10 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
} }
lock_super (sb); lock_super (sb);
es = sb->u.ext2_sb.s_es; es = sb->u.ext2_sb.s_es;
if (es->s_free_blocks_count <= es->s_r_blocks_count && !fsuser()) { if (es->s_free_blocks_count <= es->s_r_blocks_count &&
(!fsuser() && (sb->u.ext2_sb.s_resuid != current->fsuid) &&
(sb->u.ext2_sb.s_resgid == 0 ||
!in_group_p (sb->u.ext2_sb.s_resgid)))) {
unlock_super (sb); unlock_super (sb);
return 0; return 0;
} }
......
...@@ -173,6 +173,7 @@ static int convert_pre_02b_fs (struct super_block * sb, ...@@ -173,6 +173,7 @@ static int convert_pre_02b_fs (struct super_block * sb,
* This function has been shamelessly adapted from the msdos fs * This function has been shamelessly adapted from the msdos fs
*/ */
static int parse_options (char * options, unsigned long * sb_block, static int parse_options (char * options, unsigned long * sb_block,
unsigned short *resuid, unsigned short * resgid,
unsigned long * mount_options) unsigned long * mount_options)
{ {
char * this_char; char * this_char;
...@@ -247,6 +248,32 @@ static int parse_options (char * options, unsigned long * sb_block, ...@@ -247,6 +248,32 @@ static int parse_options (char * options, unsigned long * sb_block,
else if (!strcmp (this_char, "nogrpid") || else if (!strcmp (this_char, "nogrpid") ||
!strcmp (this_char, "sysvgroups")) !strcmp (this_char, "sysvgroups"))
clear_opt (*mount_options, GRPID); clear_opt (*mount_options, GRPID);
else if (!strcmp (this_char, "resgid")) {
if (!value || !*value) {
printk ("EXT2-fs: the resgid option requires "
"an argument");
return 0;
}
*resgid = simple_strtoul (value, &value, 0);
if (*value) {
printk ("EXT2-fs: Invalid resgid option: %s\n",
value);
return 0;
}
}
else if (!strcmp (this_char, "resuid")) {
if (!value || !*value) {
printk ("EXT2-fs: the resuid option requires "
"an argument");
return 0;
}
*resuid = simple_strtoul (value, &value, 0);
if (*value) {
printk ("EXT2-fs: Invalid resuid option: %s\n",
value);
return 0;
}
}
else if (!strcmp (this_char, "sb")) { else if (!strcmp (this_char, "sb")) {
if (!value || !*value) { if (!value || !*value) {
printk ("EXT2-fs: the sb option requires " printk ("EXT2-fs: the sb option requires "
...@@ -367,6 +394,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, ...@@ -367,6 +394,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
struct buffer_head * bh; struct buffer_head * bh;
struct ext2_super_block * es; struct ext2_super_block * es;
unsigned long sb_block = 1; unsigned long sb_block = 1;
unsigned short resuid = EXT2_DEF_RESUID;
unsigned short resgid = EXT2_DEF_RESGID;
unsigned long logic_sb_block = 1; unsigned long logic_sb_block = 1;
int dev = sb->s_dev; int dev = sb->s_dev;
int db_count; int db_count;
...@@ -376,7 +405,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, ...@@ -376,7 +405,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
#endif #endif
set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL); set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
if (!parse_options ((char *) data, &sb_block, if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
&sb->u.ext2_sb.s_mount_opt)) { &sb->u.ext2_sb.s_mount_opt)) {
sb->s_dev = 0; sb->s_dev = 0;
return NULL; return NULL;
...@@ -452,6 +481,14 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, ...@@ -452,6 +481,14 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
sizeof (struct ext2_group_desc); sizeof (struct ext2_group_desc);
sb->u.ext2_sb.s_sbh = bh; sb->u.ext2_sb.s_sbh = bh;
sb->u.ext2_sb.s_es = es; sb->u.ext2_sb.s_es = es;
if (resuid != EXT2_DEF_RESUID)
sb->u.ext2_sb.s_resuid = resuid;
else
sb->u.ext2_sb.s_resuid = es->s_def_resuid;
if (resgid != EXT2_DEF_RESGID)
sb->u.ext2_sb.s_resgid = resgid;
else
sb->u.ext2_sb.s_resgid = es->s_def_resgid;
sb->u.ext2_sb.s_mount_state = es->s_state; sb->u.ext2_sb.s_mount_state = es->s_state;
sb->u.ext2_sb.s_rename_lock = 0; sb->u.ext2_sb.s_rename_lock = 0;
sb->u.ext2_sb.s_rename_wait = NULL; sb->u.ext2_sb.s_rename_wait = NULL;
...@@ -633,14 +670,22 @@ void ext2_write_super (struct super_block * sb) ...@@ -633,14 +670,22 @@ void ext2_write_super (struct super_block * sb)
int ext2_remount (struct super_block * sb, int * flags, char * data) int ext2_remount (struct super_block * sb, int * flags, char * data)
{ {
struct ext2_super_block * es; struct ext2_super_block * es;
unsigned short resuid = sb->u.ext2_sb.s_resuid;
unsigned short resgid = sb->u.ext2_sb.s_resgid;
unsigned long new_mount_opt;
unsigned long tmp; unsigned long tmp;
/* /*
* Allow the "check" option to be passed as a remount option. * Allow the "check" option to be passed as a remount option.
*/ */
set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL); set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
parse_options (data, &tmp, &sb->u.ext2_sb.s_mount_opt); if (!parse_options (data, &tmp, &resuid, &resgid,
&new_mount_opt))
return -EINVAL;
sb->u.ext2_sb.s_mount_opt = new_mount_opt;
sb->u.ext2_sb.s_resuid = resuid;
sb->u.ext2_sb.s_resgid = resgid;
es = sb->u.ext2_sb.s_es; es = sb->u.ext2_sb.s_es;
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0; return 0;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define PRINTK(x) #define PRINTK(x)
#define Printk(x) printk x
static struct file_operations msdos_file_operations = { static struct file_operations msdos_file_operations = {
NULL, /* lseek - default */ NULL, /* lseek - default */
...@@ -66,13 +67,14 @@ int msdos_file_read( ...@@ -66,13 +67,14 @@ int msdos_file_read(
{ {
char *start; char *start;
int left,offset,size,cnt; int left,offset,size,cnt;
#define MSDOS_PREFETCH 48
struct { struct {
int to_reada; /* How many block to read all at once */ int file_sector;/* Next sector to read in the prefetch table */
struct buffer_head *bhreq[64]; /* Buffers not already read */ /* This is relative to the file, not the disk */
int nbreq; /* Number of buffers to read */ struct buffer_head *bhlist[MSDOS_PREFETCH]; /* All buffers needed */
struct buffer_head *bhlist[64]; /* All buffers needed */
int nblist; /* Number of buffers in bhlist */ int nblist; /* Number of buffers in bhlist */
int nolist; int nolist; /* index in bhlist */
int fetched_max; /* End of pre fetch area */
}pre; }pre;
int i; int i;
...@@ -89,59 +91,83 @@ int msdos_file_read( ...@@ -89,59 +91,83 @@ int msdos_file_read(
if (filp->f_pos >= inode->i_size || count <= 0) return 0; if (filp->f_pos >= inode->i_size || count <= 0) return 0;
/* /*
Tell the buffer cache which block we expect to read in advance Tell the buffer cache which block we expect to read in advance
Since we are limited with the stack, we preread only 64 Since we are limited with the stack, we preread only MSDOS_PREFETCH
because we have to keep the result into the local because we have to keep the result into the local
arrays pre.bhlist and pre.bhreq. arrays pre.bhlist and bhreq.
Each time we process one block in bhlist, we replace
it by a new prefetch block if needed.
*/ */
PRINTK (("#### ino %ld pos %ld size %ld count %d\n",inode->i_ino,filp->f_pos,inode->i_size,count));
{ {
int file_sector = filp->f_pos >> SECTOR_BITS; struct buffer_head *bhreq[MSDOS_PREFETCH]; /* Buffers not */
pre.to_reada = count / SECTOR_SIZE; /* already read */
int nbreq; /* Number of buffers in bhreq */
/*
We must prefetch complete block, so we must
take in account the offset in the first block.
*/
int count_max = (filp->f_pos & (SECTOR_SIZE-1)) + count;
int to_reada; /* How many block to read all at once */
pre.file_sector = filp->f_pos >> SECTOR_BITS;
to_reada = count_max / SECTOR_SIZE;
if (count_max & (SECTOR_SIZE-1)) to_reada++;
if (filp->f_reada){ if (filp->f_reada){
int min_read = read_ahead[MAJOR(inode->i_dev)]; int min_read = read_ahead[MAJOR(inode->i_dev)];
if (min_read > pre.to_reada) pre.to_reada = min_read; if (min_read > to_reada) to_reada = min_read;
} }
if (pre.to_reada > 64) pre.to_reada = 64; if (to_reada > MSDOS_PREFETCH) to_reada = MSDOS_PREFETCH;
pre.nbreq = pre.nblist = 0; nbreq = pre.nblist = 0;
for (i=0; i<pre.to_reada; i++){ for (i=0; i<to_reada; i++){
int sector; int sector;
struct buffer_head *bh; struct buffer_head *bh;
if (!(sector = msdos_smap(inode,file_sector++))) break; if (!(sector = msdos_smap(inode,pre.file_sector++))) break;
PRINTK (("fsector1 %d -> %d\n",pre.file_sector-1,sector));
bh = getblk(inode->i_dev,sector,SECTOR_SIZE); bh = getblk(inode->i_dev,sector,SECTOR_SIZE);
if (bh == NULL) break; if (bh == NULL) break;
pre.bhlist[pre.nblist++] = bh; pre.bhlist[pre.nblist++] = bh;
if (!bh->b_uptodate){ if (!bh->b_uptodate){
pre.bhreq[pre.nbreq++] = bh; bhreq[nbreq++] = bh;
} }
} }
if (pre.nbreq > 0) ll_rw_block (READ,pre.nbreq,pre.bhreq); pre.fetched_max = pre.file_sector * SECTOR_SIZE;
if (nbreq > 0) ll_rw_block (READ,nbreq,bhreq);
} }
start = buf; start = buf;
pre.nolist = 0; pre.nolist = 0;
while ((left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) > 0){ while ((left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) > 0){
struct buffer_head *bh; struct buffer_head *bh = pre.bhlist[pre.nolist];
void *data; char *data;
PRINTK (("file_read pos %d\n",filp->f_pos)); if (bh == NULL) break;
if (pre.nolist >= pre.nblist){ PRINTK (("file_read pos %ld nblist %d %d %d\n",filp->f_pos,pre.nblist,pre.fetched,count));
/* This code is executed when more than 64 sectors */ pre.bhlist[pre.nolist] = NULL;
/* are request at once */ if (left + filp->f_pos > pre.fetched_max){
int sector; int sector;
if (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS))) if ((sector = msdos_smap(inode,pre.file_sector++))){
break; struct buffer_head *bhreq[1];
if (!(bh = msdos_sread(inode->i_dev,sector))) PRINTK (("fsector2 %d -> %d\n",pre.file_sector-1,sector));
break; bhreq[0] = getblk(inode->i_dev,sector,SECTOR_SIZE);
if (bhreq[0] == NULL) break;
pre.bhlist[pre.nolist] = bhreq[0];
if (!bhreq[0]->b_uptodate)
ll_rw_block (READ,1,bhreq);
pre.fetched_max += SECTOR_SIZE;
}else{ }else{
bh = pre.bhlist[pre.nolist]; /* Stop prefetching further, we have reached eof */
pre.bhlist[pre.nolist++] = NULL; pre.fetched_max = 2000000000l;
}
}
pre.nolist++;
if (pre.nolist >= pre.nblist) pre.nolist = 0;
wait_on_buffer(bh); wait_on_buffer(bh);
if (!bh->b_uptodate){ if (!bh->b_uptodate){
/* read error ? */ /* read error ? */
brelse (bh); brelse (bh);
break; break;
} }
}
data = bh->b_data;
offset = filp->f_pos & (SECTOR_SIZE-1); offset = filp->f_pos & (SECTOR_SIZE-1);
filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left)); filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left));
data = bh->b_data;
if (MSDOS_I(inode)->i_binary) { if (MSDOS_I(inode)->i_binary) {
memcpy_tofs(buf,data+offset,size); memcpy_tofs(buf,data+offset,size);
buf += size; buf += size;
...@@ -161,6 +187,7 @@ int msdos_file_read( ...@@ -161,6 +187,7 @@ int msdos_file_read(
} }
brelse(bh); brelse(bh);
} }
PRINTK (("--- %d -> %d\n",count,(int)(buf-start)));
for (i=0; i<pre.nblist; i++) brelse (pre.bhlist[i]); for (i=0; i<pre.nblist; i++) brelse (pre.bhlist[i]);
if (start == buf) return -EIO; if (start == buf) return -EIO;
if (!IS_RDONLY(inode)) if (!IS_RDONLY(inode))
......
...@@ -117,6 +117,38 @@ int permission(struct inode * inode,int mask) ...@@ -117,6 +117,38 @@ int permission(struct inode * inode,int mask)
return 0; return 0;
} }
/*
* get_write_access() gets write permission for a file.
* put_write_access() releases this write permission.
* This is used for regular files.
* We cannot support write (and maybe mmap read-write shared) accesses and
* MAP_DENYWRITE mmapings simultaneously.
*/
int get_write_access(struct inode * inode)
{
struct task_struct ** p;
if ((inode->i_count > 1) && S_ISREG(inode->i_mode)) /* shortcut */
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
struct vm_area_struct * mpnt;
if (!*p)
continue;
for(mpnt = (*p)->mm->mmap; mpnt; mpnt = mpnt->vm_next) {
if (inode != mpnt->vm_inode)
continue;
if (mpnt->vm_flags & VM_DENYWRITE)
return -ETXTBSY;
}
}
inode->i_wcount++;
return 0;
}
void put_write_access(struct inode * inode)
{
inode->i_wcount--;
}
/* /*
* lookup() looks up one part of a pathname, using the fs-dependent * lookup() looks up one part of a pathname, using the fs-dependent
* routines (currently minix_lookup) for it. It also checks for * routines (currently minix_lookup) for it. It also checks for
...@@ -308,7 +340,6 @@ int open_namei(const char * pathname, int flag, int mode, ...@@ -308,7 +340,6 @@ int open_namei(const char * pathname, int flag, int mode,
const char * basename; const char * basename;
int namelen,error; int namelen,error;
struct inode * dir, *inode; struct inode * dir, *inode;
struct task_struct ** p;
mode &= S_IALLUGO & ~current->fs->umask; mode &= S_IALLUGO & ~current->fs->umask;
mode |= S_IFREG; mode |= S_IFREG;
...@@ -380,23 +411,6 @@ int open_namei(const char * pathname, int flag, int mode, ...@@ -380,23 +411,6 @@ int open_namei(const char * pathname, int flag, int mode,
return -EROFS; return -EROFS;
} }
} }
if ((inode->i_count > 1) && (flag & 2)) {
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
struct vm_area_struct * mpnt;
if (!*p)
continue;
for(mpnt = (*p)->mm->mmap; mpnt; mpnt = mpnt->vm_next) {
if (inode != mpnt->vm_inode)
continue;
if (mpnt->vm_page_prot & PAGE_RW)
continue;
if (mpnt->vm_flags & VM_DENYWRITE) {
iput(inode);
return -ETXTBSY;
}
}
}
}
/* /*
* An append-only file must be opened in append mode for writing * An append-only file must be opened in append mode for writing
*/ */
...@@ -407,9 +421,14 @@ int open_namei(const char * pathname, int flag, int mode, ...@@ -407,9 +421,14 @@ int open_namei(const char * pathname, int flag, int mode,
if (flag & O_TRUNC) { if (flag & O_TRUNC) {
struct iattr newattrs; struct iattr newattrs;
if ((error = get_write_access(inode))) {
iput(inode);
return error;
}
newattrs.ia_size = 0; newattrs.ia_size = 0;
newattrs.ia_valid = ATTR_SIZE; newattrs.ia_valid = ATTR_SIZE;
if ((error = notify_change(inode, &newattrs))) { if ((error = notify_change(inode, &newattrs))) {
put_write_access(inode);
iput(inode); iput(inode);
return error; return error;
} }
...@@ -417,6 +436,7 @@ int open_namei(const char * pathname, int flag, int mode, ...@@ -417,6 +436,7 @@ int open_namei(const char * pathname, int flag, int mode,
if (inode->i_op && inode->i_op->truncate) if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode); inode->i_op->truncate(inode);
inode->i_dirt = 1; inode->i_dirt = 1;
put_write_access(inode);
} }
*res_inode = inode; *res_inode = inode;
return 0; return 0;
......
...@@ -77,25 +77,12 @@ static int nfs_stat_to_errno(int stat); ...@@ -77,25 +77,12 @@ static int nfs_stat_to_errno(int stat);
static inline int *nfs_rpc_alloc(int size) static inline int *nfs_rpc_alloc(int size)
{ {
#if 0
/* Allow for the NFS crap as well as buffer */
return (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_KERNEL);
#else
/* If kmalloc fails, then we will give an EIO to user level.
(Please correct me, I am wron here... ??) This is not
desirable, but it is also not desirable to execute the
following code: Just loop until we get memory, call schedule(),
so that other processes are run inbetween (and hopefully give
some memory back). Florian
*/
int *i; int *i;
while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_KERNEL))) { while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_NFS))) {
/* printk("NFS: call schedule\n"); */
schedule(); schedule();
} }
return i; return i;
#endif
} }
static inline void nfs_rpc_free(int *p) static inline void nfs_rpc_free(int *p)
......
...@@ -71,16 +71,9 @@ static int nfs_follow_link(struct inode *dir, struct inode *inode, ...@@ -71,16 +71,9 @@ static int nfs_follow_link(struct inode *dir, struct inode *inode,
} }
error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem, error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
&res, &len, NFS_MAXPATHLEN); &res, &len, NFS_MAXPATHLEN);
#if 0 while ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_NFS)) == NULL) {
if ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) {
printk("NFS: no memory in nfs_follow_link\n");
error = -EIO;
}
#else
while ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) {
schedule(); schedule();
} }
#endif
if (error) { if (error) {
iput(inode); iput(inode);
iput(dir); iput(dir);
......
...@@ -86,6 +86,11 @@ asmlinkage int sys_truncate(const char * path, unsigned int length) ...@@ -86,6 +86,11 @@ asmlinkage int sys_truncate(const char * path, unsigned int length)
iput(inode); iput(inode);
return -EPERM; return -EPERM;
} }
error = get_write_access(inode);
if (error) {
iput(inode);
return error;
}
inode->i_size = newattrs.ia_size = length; inode->i_size = newattrs.ia_size = length;
if (inode->i_op && inode->i_op->truncate) if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode); inode->i_op->truncate(inode);
...@@ -93,6 +98,7 @@ asmlinkage int sys_truncate(const char * path, unsigned int length) ...@@ -93,6 +98,7 @@ asmlinkage int sys_truncate(const char * path, unsigned int length)
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME;
inode->i_dirt = 1; inode->i_dirt = 1;
error = notify_change(inode, &newattrs); error = notify_change(inode, &newattrs);
put_write_access(inode);
iput(inode); iput(inode);
return error; return error;
} }
...@@ -320,14 +326,14 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group) ...@@ -320,14 +326,14 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
/* /*
* If the owner has been changed, remove the setuid bit * If the owner has been changed, remove the setuid bit
*/ */
if (user != inode->i_uid && inode->i_mode & S_ISUID) { if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
newattrs.ia_mode &= ~S_ISUID; newattrs.ia_mode &= ~S_ISUID;
newattrs.ia_valid |= ATTR_MODE; newattrs.ia_valid |= ATTR_MODE;
} }
/* /*
* If the group has been changed, remove the setgid bit * If the group has been changed, remove the setgid bit
*/ */
if (group != inode->i_gid && inode->i_mode & S_ISGID) { if (group != inode->i_gid && (inode->i_mode & S_ISGID)) {
newattrs.ia_mode &= ~S_ISGID; newattrs.ia_mode &= ~S_ISGID;
newattrs.ia_valid |= ATTR_MODE; newattrs.ia_valid |= ATTR_MODE;
} }
...@@ -352,6 +358,7 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group) ...@@ -352,6 +358,7 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
user = inode->i_uid; user = inode->i_uid;
if (group == (gid_t) -1) if (group == (gid_t) -1)
group = inode->i_gid; group = inode->i_gid;
newattrs.ia_mode = inode->i_mode;
newattrs.ia_uid = user; newattrs.ia_uid = user;
newattrs.ia_gid = group; newattrs.ia_gid = group;
newattrs.ia_ctime = CURRENT_TIME; newattrs.ia_ctime = CURRENT_TIME;
...@@ -359,15 +366,15 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group) ...@@ -359,15 +366,15 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
/* /*
* If the owner has been changed, remove the setuid bit * If the owner has been changed, remove the setuid bit
*/ */
if (user != inode->i_uid && inode->i_mode & S_ISUID) { if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
newattrs.ia_mode = inode->i_mode & ~S_ISUID; newattrs.ia_mode &= ~S_ISUID;
newattrs.ia_valid |= ATTR_MODE; newattrs.ia_valid |= ATTR_MODE;
} }
/* /*
* If the group has been changed, remove the setgid bit * If the group has been changed, remove the setgid bit
*/ */
if (group != inode->i_gid && inode->i_mode & S_ISGID) { if (group != inode->i_gid && (inode->i_mode & S_ISGID)) {
newattrs.ia_mode = inode->i_mode & ~S_ISGID; newattrs.ia_mode &= ~S_ISGID;
newattrs.ia_valid |= ATTR_MODE; newattrs.ia_valid |= ATTR_MODE;
} }
inode->i_dirt = 1; inode->i_dirt = 1;
...@@ -413,6 +420,8 @@ int do_open(const char * filename,int flags,int mode) ...@@ -413,6 +420,8 @@ int do_open(const char * filename,int flags,int mode)
if (flag & (O_TRUNC | O_CREAT)) if (flag & (O_TRUNC | O_CREAT))
flag |= 2; flag |= 2;
error = open_namei(filename,flag,mode,&inode,NULL); error = open_namei(filename,flag,mode,&inode,NULL);
if (!error && (f->f_mode & 2))
error = get_write_access(inode);
if (error) { if (error) {
current->files->fd[fd]=NULL; current->files->fd[fd]=NULL;
f->f_count--; f->f_count--;
...@@ -428,6 +437,7 @@ int do_open(const char * filename,int flags,int mode) ...@@ -428,6 +437,7 @@ int do_open(const char * filename,int flags,int mode)
if (f->f_op && f->f_op->open) { if (f->f_op && f->f_op->open) {
error = f->f_op->open(inode,f); error = f->f_op->open(inode,f);
if (error) { if (error) {
if (f->f_mode & 2) put_write_access(inode);
iput(inode); iput(inode);
f->f_count--; f->f_count--;
current->files->fd[fd]=NULL; current->files->fd[fd]=NULL;
...@@ -475,6 +485,7 @@ int close_fp(struct file *filp, unsigned int fd) ...@@ -475,6 +485,7 @@ int close_fp(struct file *filp, unsigned int fd)
filp->f_op->release(inode,filp); filp->f_op->release(inode,filp);
filp->f_count--; filp->f_count--;
filp->f_inode = NULL; filp->f_inode = NULL;
if (filp->f_mode & 2) put_write_access(inode);
iput(inode); iput(inode);
return 0; return 0;
} }
......
...@@ -178,12 +178,6 @@ These filesystems are rather similar. Here is a comparison with Minix FS: ...@@ -178,12 +178,6 @@ These filesystems are rather similar. Here is a comparison with Minix FS:
Notation: We often speak of a "block" but mean a zone (the allocation unit) Notation: We often speak of a "block" but mean a zone (the allocation unit)
and not the disk driver's notion of "block". and not the disk driver's notion of "block".
Because the block size may be smaller than 1024 (which is the unit used by
the disk drivers and the buffer code), many functions must return a pointer
to the buffer data additionally to the buffer head pointer. One must not
assume that the entire buffer is occupied by this single block. This makes
the implementation of truncate() difficult.
Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de> Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de>
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
$(AS) -o $*.o $< $(AS) -o $*.o $<
OBJS= ialloc.o balloc.o inode.o file.o dir.o symlink.o namei.o \ OBJS= ialloc.o balloc.o inode.o file.o dir.o symlink.o namei.o \
fsync.o truncate.o mmap.o fsync.o truncate.o
sysv.o: $(OBJS) sysv.o: $(OBJS)
$(LD) -r -o sysv.o $(OBJS) $(LD) -r -o sysv.o $(OBJS)
......
...@@ -4,7 +4,7 @@ It implements all of ...@@ -4,7 +4,7 @@ It implements all of
- SystemV/386 FS, - SystemV/386 FS,
- Coherent FS. - Coherent FS.
This is version beta 3. This is version beta 4.
To install: To install:
* Answer the 'System V and Coherent filesystem support' question with 'y' * Answer the 'System V and Coherent filesystem support' question with 'y'
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <linux/locks.h> #include <linux/locks.h>
/* We don't trust the value of /* We don't trust the value of
sb->sv_sbd->s_tfree = *sb->sv_sb_total_free_blocks sb->sv_sbd2->s_tfree = *sb->sv_sb_total_free_blocks
but we nevertheless keep it up to date. */ but we nevertheless keep it up to date. */
void sysv_free_block(struct super_block * sb, unsigned int block) void sysv_free_block(struct super_block * sb, unsigned int block)
...@@ -55,16 +55,13 @@ void sysv_free_block(struct super_block * sb, unsigned int block) ...@@ -55,16 +55,13 @@ void sysv_free_block(struct super_block * sb, unsigned int block)
unsigned short * flc_count; unsigned short * flc_count;
unsigned long * flc_blocks; unsigned long * flc_blocks;
if (sb->sv_block_size_ratio_bits > 0) /* block_size < BLOCK_SIZE ? */ bh = sv_getblk(sb, sb->s_dev, block);
bh = bread(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
else
bh = getblk(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
if (!bh) { if (!bh) {
printk("sysv_free_block: getblk() or bread() failed\n"); printk("sysv_free_block: getblk() failed\n");
unlock_super(sb); unlock_super(sb);
return; return;
} }
bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits); bh_data = bh->b_data;
switch (sb->sv_type) { switch (sb->sv_type) {
case FSTYPE_XENIX: case FSTYPE_XENIX:
flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree; flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
...@@ -95,31 +92,25 @@ void sysv_free_block(struct super_block * sb, unsigned int block) ...@@ -95,31 +92,25 @@ void sysv_free_block(struct super_block * sb, unsigned int block)
* in this block being freed: * in this block being freed:
*/ */
if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */ if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */
if (sb->sv_block_size_ratio_bits > 0) /* block_size < BLOCK_SIZE ? */ bh = sv_getblk(sb, sb->s_dev, block);
bh = bread(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
else
bh = getblk(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
if (!bh) { if (!bh) {
printk("sysv_free_block: getblk() or bread() failed\n"); printk("sysv_free_block: getblk() failed\n");
unlock_super(sb); unlock_super(sb);
return; return;
} }
bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits); memset(bh->b_data, 0, sb->sv_block_size);
memset(bh_data, 0, sb->sv_block_size); /* this implies ((struct ..._freelist_chunk *) bh->b_data)->flc_count = 0; */
/* this implies ((struct ..._freelist_chunk *) bh_data)->flc_count = 0; */
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
bh->b_uptodate = 1; bh->b_uptodate = 1;
brelse(bh); brelse(bh);
/* still *sb->sv_sb_flc_count = 0 */ /* still *sb->sv_sb_flc_count = 0 */
} else { } else {
if (sb->sv_block_size_ratio_bits == 0) { /* block_size == BLOCK_SIZE ? */
/* Throw away block's contents */ /* Throw away block's contents */
bh = get_hash_table(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE); bh = sv_get_hash_table(sb, sb->s_dev, block);
if (bh) if (bh)
bh->b_dirt = 0; bh->b_dirt = 0;
brelse(bh); brelse(bh);
} }
}
if (sb->sv_convert) if (sb->sv_convert)
block = to_coh_ulong(block); block = to_coh_ulong(block);
sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)++] = block; sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)++] = block;
...@@ -128,7 +119,8 @@ void sysv_free_block(struct super_block * sb, unsigned int block) ...@@ -128,7 +119,8 @@ void sysv_free_block(struct super_block * sb, unsigned int block)
to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1); to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1);
else else
*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1; *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1;
mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */ mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
sb->s_dirt = 1; /* and needs time stamp */ sb->s_dirt = 1; /* and needs time stamp */
unlock_super(sb); unlock_super(sb);
} }
...@@ -165,13 +157,14 @@ int sysv_new_block(struct super_block * sb) ...@@ -165,13 +157,14 @@ int sysv_new_block(struct super_block * sb)
unsigned short * flc_count; unsigned short * flc_count;
unsigned long * flc_blocks; unsigned long * flc_blocks;
if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) { if (!(bh = sv_bread(sb, sb->s_dev, block))) {
printk("sysv_new_block: cannot read free-list block\n"); printk("sysv_new_block: cannot read free-list block\n");
/* retry this same block next time */ /* retry this same block next time */
(*sb->sv_sb_flc_count)++; (*sb->sv_sb_flc_count)++;
unlock_super(sb); unlock_super(sb);
return 0; return 0;
} }
bh_data = bh->b_data;
switch (sb->sv_type) { switch (sb->sv_type) {
case FSTYPE_XENIX: case FSTYPE_XENIX:
flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree; flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
...@@ -202,23 +195,18 @@ int sysv_new_block(struct super_block * sb) ...@@ -202,23 +195,18 @@ int sysv_new_block(struct super_block * sb)
brelse(bh); brelse(bh);
} }
/* Now the free list head in the superblock is valid again. */ /* Now the free list head in the superblock is valid again. */
if (sb->sv_block_size_ratio_bits > 0) /* block_size < BLOCK_SIZE ? */ bh = sv_getblk(sb, sb->s_dev, block);
bh = bread(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
else
bh = getblk(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
if (!bh) { if (!bh) {
printk("sysv_new_block: getblk() or bread() failed\n"); printk("sysv_new_block: getblk() failed\n");
unlock_super(sb); unlock_super(sb);
return 0; return 0;
} }
bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
if (sb->sv_block_size_ratio_bits == 0) /* block_size == BLOCK_SIZE ? */
if (bh->b_count != 1) { if (bh->b_count != 1) {
printk("sysv_new_block: block already in use\n"); printk("sysv_new_block: block already in use\n");
unlock_super(sb); unlock_super(sb);
return 0; return 0;
} }
memset(bh_data, 0, sb->sv_block_size); memset(bh->b_data, 0, sb->sv_block_size);
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
bh->b_uptodate = 1; bh->b_uptodate = 1;
brelse(bh); brelse(bh);
...@@ -227,7 +215,8 @@ int sysv_new_block(struct super_block * sb) ...@@ -227,7 +215,8 @@ int sysv_new_block(struct super_block * sb)
to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1); to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1);
else else
*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1; *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1;
mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */ mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
sb->s_dirt = 1; /* and needs time stamp */ sb->s_dirt = 1; /* and needs time stamp */
unlock_super(sb); unlock_super(sb);
return block; return block;
...@@ -265,10 +254,11 @@ unsigned long sysv_count_free_blocks(struct super_block * sb) ...@@ -265,10 +254,11 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
printk("sysv_count_free_blocks: new block %d is not in data zone\n",block); printk("sysv_count_free_blocks: new block %d is not in data zone\n",block);
break; break;
} }
if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) { if (!(bh = sv_bread(sb, sb->s_dev, block))) {
printk("sysv_count_free_blocks: cannot read free-list block\n"); printk("sysv_count_free_blocks: cannot read free-list block\n");
break; break;
} }
bh_data = bh->b_data;
switch (sb->sv_type) { switch (sb->sv_type) {
case FSTYPE_XENIX: case FSTYPE_XENIX:
flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree; flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
...@@ -321,7 +311,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb) ...@@ -321,7 +311,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count); printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count);
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
*sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count); *sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count);
mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */ mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified */
sb->s_dirt = 1; /* and needs time stamp */ sb->s_dirt = 1; /* and needs time stamp */
} }
} }
......
...@@ -80,11 +80,12 @@ static int sysv_readdir1 (struct inode * inode, struct file * filp, ...@@ -80,11 +80,12 @@ static int sysv_readdir1 (struct inode * inode, struct file * filp,
return -EBADF; return -EBADF;
while (filp->f_pos < inode->i_size) { while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & sb->sv_block_size_1; offset = filp->f_pos & sb->sv_block_size_1;
bh = sysv_file_bread(inode, filp->f_pos >> sb->sv_block_size_bits, 0, &bh_data); bh = sysv_file_bread(inode, filp->f_pos >> sb->sv_block_size_bits, 0);
if (!bh) { if (!bh) {
filp->f_pos += sb->sv_block_size - offset; filp->f_pos += sb->sv_block_size - offset;
continue; continue;
} }
bh_data = bh->b_data;
while (offset < sb->sv_block_size && filp->f_pos < inode->i_size) { while (offset < sb->sv_block_size && filp->f_pos < inode->i_size) {
de = (struct sysv_dir_entry *) (offset + bh_data); de = (struct sysv_dir_entry *) (offset + bh_data);
offset += SYSV_DIRSIZE; offset += SYSV_DIRSIZE;
...@@ -128,10 +129,6 @@ static int sysv_readdir(struct inode * inode, struct file * filp, ...@@ -128,10 +129,6 @@ static int sysv_readdir(struct inode * inode, struct file * filp,
if (count==1) if (count==1)
return sysv_readdir1(inode,filp,dirent); return sysv_readdir1(inode,filp,dirent);
retval = verify_area(VERIFY_WRITE, dirent, count);
if (retval)
return retval;
stored = 0; stored = 0;
while (count >= sizeof(struct dirent)) { while (count >= sizeof(struct dirent)) {
retval = sysv_readdir1(inode,filp,dirent); retval = sysv_readdir1(inode,filp,dirent);
......
...@@ -39,19 +39,6 @@ static int sysv_file_write(struct inode *, struct file *, char *, int); ...@@ -39,19 +39,6 @@ static int sysv_file_write(struct inode *, struct file *, char *, int);
* the coh filesystem. * the coh filesystem.
*/ */
static struct file_operations sysv_file_operations = { static struct file_operations sysv_file_operations = {
NULL, /* lseek - default */
sysv_file_read, /* read */
sysv_file_write, /* write */
NULL, /* readdir - bad */
NULL, /* select - default */
NULL, /* ioctl - default */
sysv_mmap, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
sysv_sync_file /* fsync */
};
static struct file_operations sysv_file_operations_with_bmap = {
NULL, /* lseek - default */ NULL, /* lseek - default */
sysv_file_read, /* read */ sysv_file_read, /* read */
sysv_file_write, /* write */ sysv_file_write, /* write */
...@@ -77,44 +64,21 @@ struct inode_operations sysv_file_inode_operations = { ...@@ -77,44 +64,21 @@ struct inode_operations sysv_file_inode_operations = {
NULL, /* rename */ NULL, /* rename */
NULL, /* readlink */ NULL, /* readlink */
NULL, /* follow_link */ NULL, /* follow_link */
NULL, /* bmap */
sysv_truncate, /* truncate */
NULL /* permission */
};
struct inode_operations sysv_file_inode_operations_with_bmap = {
&sysv_file_operations_with_bmap, /* default file operations */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
sysv_bmap, /* bmap */ sysv_bmap, /* bmap */
sysv_truncate, /* truncate */ sysv_truncate, /* truncate */
NULL /* permission */ NULL /* permission */
}; };
struct sysv_buffer {
struct buffer_head * bh;
char * bh_data;
};
int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int count) int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int count)
{ {
struct super_block * sb = inode->i_sb; struct super_block * sb = inode->i_sb;
int read,left,chars; int read,left,chars;
unsigned int block; unsigned int block;
int blocks, offset; int blocks, offset;
int bhrequest, bhreqi, uptodate; int bhrequest, uptodate;
struct sysv_buffer * bhb, * bhe; struct buffer_head ** bhb, ** bhe;
struct buffer_head * bhreq[NBUF]; struct buffer_head * bhreq[NBUF];
struct sysv_buffer buflist[NBUF]; struct buffer_head * buflist[NBUF];
unsigned int size; unsigned int size;
if (!inode) { if (!inode) {
...@@ -156,9 +120,6 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou ...@@ -156,9 +120,6 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou
This routine is optimized to make maximum use of the various This routine is optimized to make maximum use of the various
buffers and caches. buffers and caches.
We must remove duplicates from the bhreq array as ll_rw_block
doesn't like duplicate requests (it hangs in wait_on_buffer...).
*/ */
do { do {
...@@ -166,15 +127,10 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou ...@@ -166,15 +127,10 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou
uptodate = 1; uptodate = 1;
while (blocks) { while (blocks) {
--blocks; --blocks;
bhb->bh = sysv_getblk(inode, block++, 0, &bhb->bh_data); *bhb = sysv_getblk(inode, block++, 0);
if (bhb->bh && !bhb->bh->b_uptodate) { if (*bhb && !(*bhb)->b_uptodate) {
uptodate = 0; uptodate = 0;
if (sb->sv_block_size_ratio_bits > 0) /* block_size < BLOCK_SIZE ? */ bhreq[bhrequest++] = *bhb;
for (bhreqi = 0; bhreqi < bhrequest; bhreqi++)
if (bhreq[bhreqi] == bhb->bh)
goto notreq;
bhreq[bhrequest++] = bhb->bh;
notreq: ;
} }
if (++bhb == &buflist[NBUF]) if (++bhb == &buflist[NBUF])
...@@ -193,10 +149,10 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou ...@@ -193,10 +149,10 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou
ll_rw_block(READ, bhrequest, bhreq); ll_rw_block(READ, bhrequest, bhreq);
do { /* Finish off all I/O that has actually completed */ do { /* Finish off all I/O that has actually completed */
if (bhe->bh) { if (*bhe) {
wait_on_buffer(bhe->bh); wait_on_buffer(*bhe);
if (!bhe->bh->b_uptodate) { /* read error? */ if (!(*bhe)->b_uptodate) { /* read error? */
brelse(bhe->bh); brelse(*bhe);
if (++bhe == &buflist[NBUF]) if (++bhe == &buflist[NBUF])
bhe = buflist; bhe = buflist;
left = 0; left = 0;
...@@ -210,9 +166,9 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou ...@@ -210,9 +166,9 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou
filp->f_pos += chars; filp->f_pos += chars;
left -= chars; left -= chars;
read += chars; read += chars;
if (bhe->bh) { if (*bhe) {
memcpy_tofs(buf,offset+bhe->bh_data,chars); memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
brelse(bhe->bh); brelse(*bhe);
buf += chars; buf += chars;
} else { } else {
while (chars-- > 0) while (chars-- > 0)
...@@ -221,12 +177,12 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou ...@@ -221,12 +177,12 @@ int sysv_file_read(struct inode * inode, struct file * filp, char * buf, int cou
offset = 0; offset = 0;
if (++bhe == &buflist[NBUF]) if (++bhe == &buflist[NBUF])
bhe = buflist; bhe = buflist;
} while (left > 0 && bhe != bhb && (!bhe->bh || !bhe->bh->b_lock)); } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
} while (left > 0); } while (left > 0);
/* Release the read-ahead blocks */ /* Release the read-ahead blocks */
while (bhe != bhb) { while (bhe != bhb) {
brelse(bhe->bh); brelse(*bhe);
if (++bhe == &buflist[NBUF]) if (++bhe == &buflist[NBUF])
bhe = buflist; bhe = buflist;
}; };
...@@ -244,7 +200,6 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf, ...@@ -244,7 +200,6 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf,
off_t pos; off_t pos;
int written,c; int written,c;
struct buffer_head * bh; struct buffer_head * bh;
char * bh_data;
char * p; char * p;
if (!inode) { if (!inode) {
...@@ -262,15 +217,13 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf, ...@@ -262,15 +217,13 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf,
* writing our data into blocks that have meanwhile been incorporated into * writing our data into blocks that have meanwhile been incorporated into
* the freelist, thereby trashing the freelist. * the freelist, thereby trashing the freelist.
*/ */
if (sb->sv_block_size_ratio_bits > 0) /* block_size < BLOCK_SIZE ? */
coh_lock_inode(inode);
if (filp->f_flags & O_APPEND) if (filp->f_flags & O_APPEND)
pos = inode->i_size; pos = inode->i_size;
else else
pos = filp->f_pos; pos = filp->f_pos;
written = 0; written = 0;
while (written<count) { while (written<count) {
bh = sysv_getblk (inode, pos >> sb->sv_block_size_bits, 1, &bh_data); bh = sysv_getblk (inode, pos >> sb->sv_block_size_bits, 1);
if (!bh) { if (!bh) {
if (!written) if (!written)
written = -ENOSPC; written = -ENOSPC;
...@@ -279,7 +232,7 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf, ...@@ -279,7 +232,7 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf,
c = sb->sv_block_size - (pos & sb->sv_block_size_1); c = sb->sv_block_size - (pos & sb->sv_block_size_1);
if (c > count-written) if (c > count-written)
c = count-written; c = count-written;
if (c != BLOCK_SIZE && !bh->b_uptodate) { if (c != sb->sv_block_size && !bh->b_uptodate) {
ll_rw_block(READ, 1, &bh); ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh); wait_on_buffer(bh);
if (!bh->b_uptodate) { if (!bh->b_uptodate) {
...@@ -289,8 +242,8 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf, ...@@ -289,8 +242,8 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf,
break; break;
} }
} }
/* now either c==BLOCK_SIZE or bh->b_uptodate */ /* now either c==sb->sv_block_size or bh->b_uptodate */
p = (pos & sb->sv_block_size_1) + bh_data; p = (pos & sb->sv_block_size_1) + bh->b_data;
pos += c; pos += c;
if (pos > inode->i_size) { if (pos > inode->i_size) {
inode->i_size = pos; inode->i_size = pos;
...@@ -306,7 +259,5 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf, ...@@ -306,7 +259,5 @@ static int sysv_file_write(struct inode * inode, struct file * filp, char * buf,
inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_ctime = CURRENT_TIME;
filp->f_pos = pos; filp->f_pos = pos;
inode->i_dirt = 1; inode->i_dirt = 1;
if (sb->sv_block_size_ratio_bits > 0) /* block_size < BLOCK_SIZE ? */
coh_unlock_inode(inode);
return written; return written;
} }
...@@ -38,7 +38,7 @@ static int sync_block (struct inode * inode, unsigned long * blockp, int convert ...@@ -38,7 +38,7 @@ static int sync_block (struct inode * inode, unsigned long * blockp, int convert
if (!block) if (!block)
return 0; return 0;
sb = inode->i_sb; sb = inode->i_sb;
bh = get_hash_table(inode->i_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE); bh = sv_get_hash_table(sb, inode->i_dev, block);
if (!bh) if (!bh)
return 0; return 0;
if (*blockp != tmp) { if (*blockp != tmp) {
...@@ -60,7 +60,7 @@ static int sync_block (struct inode * inode, unsigned long * blockp, int convert ...@@ -60,7 +60,7 @@ static int sync_block (struct inode * inode, unsigned long * blockp, int convert
/* Sync one block full of indirect pointers and read it because we'll need it. */ /* Sync one block full of indirect pointers and read it because we'll need it. */
static int sync_iblock (struct inode * inode, unsigned long * iblockp, int convert, static int sync_iblock (struct inode * inode, unsigned long * iblockp, int convert,
struct buffer_head * *bh, char * *bh_data, int wait) struct buffer_head * *bh, int wait)
{ {
int rc; int rc;
unsigned long tmp, block; unsigned long tmp, block;
...@@ -74,7 +74,7 @@ static int sync_iblock (struct inode * inode, unsigned long * iblockp, int conve ...@@ -74,7 +74,7 @@ static int sync_iblock (struct inode * inode, unsigned long * iblockp, int conve
rc = sync_block (inode, iblockp, convert, wait); rc = sync_block (inode, iblockp, convert, wait);
if (rc) if (rc)
return rc; return rc;
*bh = sysv_bread(inode->i_sb, inode->i_dev, block, bh_data); *bh = sv_bread(inode->i_sb, inode->i_dev, block);
if (tmp != *iblockp) { if (tmp != *iblockp) {
brelse(*bh); brelse(*bh);
*bh = NULL; *bh = NULL;
...@@ -105,18 +105,17 @@ static int sync_indirect(struct inode *inode, unsigned long *iblockp, int conver ...@@ -105,18 +105,17 @@ static int sync_indirect(struct inode *inode, unsigned long *iblockp, int conver
{ {
int i; int i;
struct buffer_head * ind_bh; struct buffer_head * ind_bh;
char * ind_bh_data;
int rc, err = 0; int rc, err = 0;
struct super_block * sb; struct super_block * sb;
rc = sync_iblock (inode, iblockp, convert, &ind_bh, &ind_bh_data, wait); rc = sync_iblock (inode, iblockp, convert, &ind_bh, wait);
if (rc || !ind_bh) if (rc || !ind_bh)
return rc; return rc;
sb = inode->i_sb; sb = inode->i_sb;
for (i = 0; i < sb->sv_ind_per_block; i++) { for (i = 0; i < sb->sv_ind_per_block; i++) {
rc = sync_block (inode, rc = sync_block (inode,
((unsigned long *) ind_bh_data) + i, sb->sv_convert, ((unsigned long *) ind_bh->b_data) + i, sb->sv_convert,
wait); wait);
if (rc > 0) if (rc > 0)
break; break;
...@@ -132,18 +131,17 @@ static int sync_dindirect(struct inode *inode, unsigned long *diblockp, int conv ...@@ -132,18 +131,17 @@ static int sync_dindirect(struct inode *inode, unsigned long *diblockp, int conv
{ {
int i; int i;
struct buffer_head * dind_bh; struct buffer_head * dind_bh;
char * dind_bh_data;
int rc, err = 0; int rc, err = 0;
struct super_block * sb; struct super_block * sb;
rc = sync_iblock (inode, diblockp, convert, &dind_bh, &dind_bh_data, wait); rc = sync_iblock (inode, diblockp, convert, &dind_bh, wait);
if (rc || !dind_bh) if (rc || !dind_bh)
return rc; return rc;
sb = inode->i_sb; sb = inode->i_sb;
for (i = 0; i < sb->sv_ind_per_block; i++) { for (i = 0; i < sb->sv_ind_per_block; i++) {
rc = sync_indirect (inode, rc = sync_indirect (inode,
((unsigned long *) dind_bh_data) + i, sb->sv_convert, ((unsigned long *) dind_bh->b_data) + i, sb->sv_convert,
wait); wait);
if (rc > 0) if (rc > 0)
break; break;
...@@ -159,18 +157,17 @@ static int sync_tindirect(struct inode *inode, unsigned long *tiblockp, int conv ...@@ -159,18 +157,17 @@ static int sync_tindirect(struct inode *inode, unsigned long *tiblockp, int conv
{ {
int i; int i;
struct buffer_head * tind_bh; struct buffer_head * tind_bh;
char * tind_bh_data;
int rc, err = 0; int rc, err = 0;
struct super_block * sb; struct super_block * sb;
rc = sync_iblock (inode, tiblockp, convert, &tind_bh, &tind_bh_data, wait); rc = sync_iblock (inode, tiblockp, convert, &tind_bh, wait);
if (rc || !tind_bh) if (rc || !tind_bh)
return rc; return rc;
sb = inode->i_sb; sb = inode->i_sb;
for (i = 0; i < sb->sv_ind_per_block; i++) { for (i = 0; i < sb->sv_ind_per_block; i++) {
rc = sync_dindirect (inode, rc = sync_dindirect (inode,
((unsigned long *) tind_bh_data) + i, sb->sv_convert, ((unsigned long *) tind_bh->b_data) + i, sb->sv_convert,
wait); wait);
if (rc > 0) if (rc > 0)
break; break;
......
...@@ -23,22 +23,37 @@ ...@@ -23,22 +23,37 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/sysv_fs.h> #include <linux/sysv_fs.h>
#include <linux/stddef.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/locks.h> #include <linux/locks.h>
/* We don't trust the value of /* We don't trust the value of
sb->sv_sbd->s_tinode = *sb->sv_sb_total_free_inodes sb->sv_sbd2->s_tinode = *sb->sv_sb_total_free_inodes
but we nevertheless keep it up to date. */ but we nevertheless keep it up to date. */
/* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */ /* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */
/* return &sb->sv_sb_fic_inodes[i] = &sbd->s_inode[i]; */
static inline sysv_ino_t * sv_sb_fic_inode (struct super_block * sb, unsigned int i)
{
if (sb->sv_bh1 == sb->sv_bh2)
return &sb->sv_sb_fic_inodes[i];
else {
/* 512 byte Xenix FS */
unsigned int offset = offsetof(struct xenix_super_block, s_inode[i]);
if (offset < 512)
return (sysv_ino_t*)(sb->sv_sbd1 + offset);
else
return (sysv_ino_t*)(sb->sv_sbd2 + offset);
}
}
void sysv_free_inode(struct inode * inode) void sysv_free_inode(struct inode * inode)
{ {
struct super_block * sb; struct super_block * sb;
unsigned int ino; unsigned int ino;
struct buffer_head * bh; struct buffer_head * bh;
char * bh_data;
struct sysv_inode * raw_inode; struct sysv_inode * raw_inode;
if (!inode) if (!inode)
...@@ -64,17 +79,18 @@ void sysv_free_inode(struct inode * inode) ...@@ -64,17 +79,18 @@ void sysv_free_inode(struct inode * inode)
printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n"); printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n");
return; return;
} }
if (!(bh = sysv_bread(sb, inode->i_dev, sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits), &bh_data))) { if (!(bh = sv_bread(sb, inode->i_dev, sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits)))) {
printk("sysv_free_inode: unable to read inode block on device %d/%d\n",MAJOR(inode->i_dev),MINOR(inode->i_dev)); printk("sysv_free_inode: unable to read inode block on device %d/%d\n",MAJOR(inode->i_dev),MINOR(inode->i_dev));
clear_inode(inode); clear_inode(inode);
return; return;
} }
raw_inode = (struct sysv_inode *) bh_data + ((ino-1) & sb->sv_inodes_per_block_1); raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1);
lock_super(sb); lock_super(sb);
if (*sb->sv_sb_fic_count < sb->sv_fic_size) if (*sb->sv_sb_fic_count < sb->sv_fic_size)
sb->sv_sb_fic_inodes[(*sb->sv_sb_fic_count)++] = ino; *sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)++) = ino;
(*sb->sv_sb_total_free_inodes)++; (*sb->sv_sb_total_free_inodes)++;
mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */ mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
sb->s_dirt = 1; /* and needs time stamp */ sb->s_dirt = 1; /* and needs time stamp */
memset(raw_inode, 0, sizeof(struct sysv_inode)); memset(raw_inode, 0, sizeof(struct sysv_inode));
mark_buffer_dirty(bh, 1); mark_buffer_dirty(bh, 1);
...@@ -88,7 +104,6 @@ struct inode * sysv_new_inode(const struct inode * dir) ...@@ -88,7 +104,6 @@ struct inode * sysv_new_inode(const struct inode * dir)
struct inode * inode; struct inode * inode;
struct super_block * sb; struct super_block * sb;
struct buffer_head * bh; struct buffer_head * bh;
char * bh_data;
struct sysv_inode * raw_inode; struct sysv_inode * raw_inode;
int i,j,ino,block; int i,j,ino,block;
...@@ -99,7 +114,7 @@ struct inode * sysv_new_inode(const struct inode * dir) ...@@ -99,7 +114,7 @@ struct inode * sysv_new_inode(const struct inode * dir)
inode->i_flags = inode->i_sb->s_flags; inode->i_flags = inode->i_sb->s_flags;
lock_super(sb); /* protect against task switches */ lock_super(sb); /* protect against task switches */
if ((*sb->sv_sb_fic_count == 0) if ((*sb->sv_sb_fic_count == 0)
|| (sb->sv_sb_fic_inodes[(*sb->sv_sb_fic_count)-1] == 0) /* Applies only to SystemV2 FS */ || (*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)-1) == 0) /* Applies only to SystemV2 FS */
) { ) {
/* Rebuild cache of free inodes: */ /* Rebuild cache of free inodes: */
/* i : index into cache slot being filled */ /* i : index into cache slot being filled */
...@@ -109,15 +124,15 @@ struct inode * sysv_new_inode(const struct inode * dir) ...@@ -109,15 +124,15 @@ struct inode * sysv_new_inode(const struct inode * dir)
/* bh : buffer for block */ /* bh : buffer for block */
/* raw_inode : pointer to inode ino in the block */ /* raw_inode : pointer to inode ino in the block */
for (i = 0, ino = SYSV_ROOT_INO+1, block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; i < sb->sv_fic_size && block < sb->sv_firstdatazone ; block++, j = 0) { for (i = 0, ino = SYSV_ROOT_INO+1, block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; i < sb->sv_fic_size && block < sb->sv_firstdatazone ; block++, j = 0) {
if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) { if (!(bh = sv_bread(sb, sb->s_dev, block))) {
printk("sysv_new_inode: unable to read inode table\n"); printk("sysv_new_inode: unable to read inode table\n");
break; /* go with what we've got */ break; /* go with what we've got */
/* FIXME: Perhaps try the next block? */ /* FIXME: Perhaps try the next block? */
} }
raw_inode = (struct sysv_inode *) bh_data + j; raw_inode = (struct sysv_inode *) bh->b_data + j;
for (; j < sb->sv_inodes_per_block && i < sb->sv_fic_size; ino++, j++, raw_inode++) { for (; j < sb->sv_inodes_per_block && i < sb->sv_fic_size; ino++, j++, raw_inode++) {
if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
sb->sv_sb_fic_inodes[i++] = ino; *sv_sb_fic_inode(sb,i++) = ino;
} }
brelse(bh); brelse(bh);
} }
...@@ -129,8 +144,9 @@ struct inode * sysv_new_inode(const struct inode * dir) ...@@ -129,8 +144,9 @@ struct inode * sysv_new_inode(const struct inode * dir)
*sb->sv_sb_fic_count = i; *sb->sv_sb_fic_count = i;
} }
/* Now *sb->sv_sb_fic_count > 0. */ /* Now *sb->sv_sb_fic_count > 0. */
ino = sb->sv_sb_fic_inodes[--(*sb->sv_sb_fic_count)]; ino = *sv_sb_fic_inode(sb,--(*sb->sv_sb_fic_count));
mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */ mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
sb->s_dirt = 1; /* and needs time stamp */ sb->s_dirt = 1; /* and needs time stamp */
inode->i_count = 1; inode->i_count = 1;
inode->i_nlink = 1; inode->i_nlink = 1;
...@@ -142,7 +158,6 @@ struct inode * sysv_new_inode(const struct inode * dir) ...@@ -142,7 +158,6 @@ struct inode * sysv_new_inode(const struct inode * dir)
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = NULL; inode->i_op = NULL;
inode->i_blocks = inode->i_blksize = 0; inode->i_blocks = inode->i_blksize = 0;
inode->u.sysv_i.i_lock = 0; inode->u.sysv_i.i_wait = NULL;
insert_inode_hash(inode); insert_inode_hash(inode);
/* Change directory entry: */ /* Change directory entry: */
inode->i_mode = 0; /* for sysv_write_inode() */ inode->i_mode = 0; /* for sysv_write_inode() */
...@@ -152,7 +167,7 @@ struct inode * sysv_new_inode(const struct inode * dir) ...@@ -152,7 +167,7 @@ struct inode * sysv_new_inode(const struct inode * dir)
inode->i_dirt = 1; /* cleared by sysv_write_inode() */ inode->i_dirt = 1; /* cleared by sysv_write_inode() */
/* That's it. */ /* That's it. */
(*sb->sv_sb_total_free_inodes)--; (*sb->sv_sb_total_free_inodes)--;
mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified again */ mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified again */
sb->s_dirt = 1; /* and needs time stamp again */ sb->s_dirt = 1; /* and needs time stamp again */
unlock_super(sb); unlock_super(sb);
return inode; return inode;
...@@ -162,7 +177,6 @@ unsigned long sysv_count_free_inodes(struct super_block * sb) ...@@ -162,7 +177,6 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
{ {
#if 1 /* test */ #if 1 /* test */
struct buffer_head * bh; struct buffer_head * bh;
char * bh_data;
struct sysv_inode * raw_inode; struct sysv_inode * raw_inode;
int j,block,count; int j,block,count;
...@@ -176,12 +190,12 @@ unsigned long sysv_count_free_inodes(struct super_block * sb) ...@@ -176,12 +190,12 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
/* bh : buffer for block */ /* bh : buffer for block */
/* raw_inode : pointer to inode ino in the block */ /* raw_inode : pointer to inode ino in the block */
for (block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; block < sb->sv_firstdatazone ; block++, j = 0) { for (block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; block < sb->sv_firstdatazone ; block++, j = 0) {
if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) { if (!(bh = sv_bread(sb, sb->s_dev, block))) {
printk("sysv_count_free_inodes: unable to read inode table\n"); printk("sysv_count_free_inodes: unable to read inode table\n");
break; /* go with what we've got */ break; /* go with what we've got */
/* FIXME: Perhaps try the next block? */ /* FIXME: Perhaps try the next block? */
} }
raw_inode = (struct sysv_inode *) bh_data + j; raw_inode = (struct sysv_inode *) bh->b_data + j;
for (; j < sb->sv_inodes_per_block ; j++, raw_inode++) for (; j < sb->sv_inodes_per_block ; j++, raw_inode++)
if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
count++; count++;
...@@ -191,7 +205,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb) ...@@ -191,7 +205,7 @@ unsigned long sysv_count_free_inodes(struct super_block * sb)
printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count); printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count);
if (!(sb->s_flags & MS_RDONLY)) { if (!(sb->s_flags & MS_RDONLY)) {
*sb->sv_sb_total_free_inodes = count; *sb->sv_sb_total_free_inodes = count;
mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */ mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified */
sb->s_dirt = 1; /* and needs time stamp */ sb->s_dirt = 1; /* and needs time stamp */
} }
} }
......
This diff is collapsed.
...@@ -63,7 +63,6 @@ static struct buffer_head * sysv_find_entry(struct inode * dir, ...@@ -63,7 +63,6 @@ static struct buffer_head * sysv_find_entry(struct inode * dir,
struct super_block * sb; struct super_block * sb;
unsigned long pos, block, offset; /* pos = block * block_size + offset */ unsigned long pos, block, offset; /* pos = block * block_size + offset */
struct buffer_head * bh; struct buffer_head * bh;
char * bh_data;
*res_dir = NULL; *res_dir = NULL;
if (!dir) if (!dir)
...@@ -78,7 +77,7 @@ static struct buffer_head * sysv_find_entry(struct inode * dir, ...@@ -78,7 +77,7 @@ static struct buffer_head * sysv_find_entry(struct inode * dir,
pos = block = offset = 0; pos = block = offset = 0;
while (pos < dir->i_size) { while (pos < dir->i_size) {
if (!bh) { if (!bh) {
bh = sysv_file_bread(dir,block,0,&bh_data); bh = sysv_file_bread(dir,block,0);
if (!bh) { if (!bh) {
/* offset = 0; */ block++; /* offset = 0; */ block++;
pos += sb->sv_block_size; pos += sb->sv_block_size;
...@@ -86,7 +85,7 @@ static struct buffer_head * sysv_find_entry(struct inode * dir, ...@@ -86,7 +85,7 @@ static struct buffer_head * sysv_find_entry(struct inode * dir,
} }
} }
if (sysv_match(namelen, name, if (sysv_match(namelen, name,
*res_dir = (struct sysv_dir_entry *) (bh_data + offset) )) *res_dir = (struct sysv_dir_entry *) (bh->b_data + offset) ))
return bh; return bh;
pos += SYSV_DIRSIZE; pos += SYSV_DIRSIZE;
offset += SYSV_DIRSIZE; offset += SYSV_DIRSIZE;
...@@ -148,7 +147,6 @@ static int sysv_add_entry(struct inode * dir, ...@@ -148,7 +147,6 @@ static int sysv_add_entry(struct inode * dir,
int i; int i;
unsigned long pos, block, offset; /* pos = block * block_size + offset */ unsigned long pos, block, offset; /* pos = block * block_size + offset */
struct buffer_head * bh; struct buffer_head * bh;
char * bh_data;
struct sysv_dir_entry * de; struct sysv_dir_entry * de;
*res_buf = NULL; *res_buf = NULL;
...@@ -167,11 +165,11 @@ static int sysv_add_entry(struct inode * dir, ...@@ -167,11 +165,11 @@ static int sysv_add_entry(struct inode * dir,
pos = block = offset = 0; pos = block = offset = 0;
while (1) { while (1) {
if (!bh) { if (!bh) {
bh = sysv_file_bread(dir,block,1,&bh_data); bh = sysv_file_bread(dir,block,1);
if (!bh) if (!bh)
return -ENOSPC; return -ENOSPC;
} }
de = (struct sysv_dir_entry *) (bh_data + offset); de = (struct sysv_dir_entry *) (bh->b_data + offset);
pos += SYSV_DIRSIZE; pos += SYSV_DIRSIZE;
offset += SYSV_DIRSIZE; offset += SYSV_DIRSIZE;
if (pos > dir->i_size) { if (pos > dir->i_size) {
...@@ -218,9 +216,6 @@ int sysv_create(struct inode * dir,const char * name, int len, int mode, ...@@ -218,9 +216,6 @@ int sysv_create(struct inode * dir,const char * name, int len, int mode,
iput(dir); iput(dir);
return -ENOSPC; return -ENOSPC;
} }
if (inode->i_sb->sv_block_size_ratio_bits == 0) /* block_size == BLOCK_SIZE ? */
inode->i_op = &sysv_file_inode_operations_with_bmap;
else
inode->i_op = &sysv_file_inode_operations; inode->i_op = &sysv_file_inode_operations;
inode->i_mode = mode; inode->i_mode = mode;
inode->i_dirt = 1; inode->i_dirt = 1;
...@@ -264,9 +259,6 @@ int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rde ...@@ -264,9 +259,6 @@ int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rde
inode->i_mode = mode; inode->i_mode = mode;
inode->i_op = NULL; inode->i_op = NULL;
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode))
if (inode->i_sb->sv_block_size_ratio_bits == 0) /* block_size == BLOCK_SIZE ? */
inode->i_op = &sysv_file_inode_operations_with_bmap;
else
inode->i_op = &sysv_file_inode_operations; inode->i_op = &sysv_file_inode_operations;
else if (S_ISDIR(inode->i_mode)) { else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &sysv_dir_inode_operations; inode->i_op = &sysv_dir_inode_operations;
...@@ -305,7 +297,6 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) ...@@ -305,7 +297,6 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
int error; int error;
struct inode * inode; struct inode * inode;
struct buffer_head * bh, *dir_block; struct buffer_head * bh, *dir_block;
char * bh_data;
struct sysv_dir_entry * de; struct sysv_dir_entry * de;
if (!dir) { if (!dir) {
...@@ -329,7 +320,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) ...@@ -329,7 +320,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
} }
inode->i_op = &sysv_dir_inode_operations; inode->i_op = &sysv_dir_inode_operations;
inode->i_size = 2 * SYSV_DIRSIZE; inode->i_size = 2 * SYSV_DIRSIZE;
dir_block = sysv_file_bread(inode,0,1,&bh_data); dir_block = sysv_file_bread(inode,0,1);
if (!dir_block) { if (!dir_block) {
iput(dir); iput(dir);
inode->i_nlink--; inode->i_nlink--;
...@@ -337,10 +328,10 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) ...@@ -337,10 +328,10 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
iput(inode); iput(inode);
return -ENOSPC; return -ENOSPC;
} }
de = (struct sysv_dir_entry *) (bh_data + 0*SYSV_DIRSIZE); de = (struct sysv_dir_entry *) (dir_block->b_data + 0*SYSV_DIRSIZE);
de->inode = inode->i_ino; de->inode = inode->i_ino;
strcpy(de->name,"."); /* rest of de->name is zero, see sysv_new_block */ strcpy(de->name,"."); /* rest of de->name is zero, see sysv_new_block */
de = (struct sysv_dir_entry *) (bh_data + 1*SYSV_DIRSIZE); de = (struct sysv_dir_entry *) (dir_block->b_data + 1*SYSV_DIRSIZE);
de->inode = dir->i_ino; de->inode = dir->i_ino;
strcpy(de->name,".."); /* rest of de->name is zero, see sysv_new_block */ strcpy(de->name,".."); /* rest of de->name is zero, see sysv_new_block */
inode->i_nlink = 2; inode->i_nlink = 2;
...@@ -375,7 +366,6 @@ static int empty_dir(struct inode * inode) ...@@ -375,7 +366,6 @@ static int empty_dir(struct inode * inode)
struct super_block * sb; struct super_block * sb;
unsigned long pos, block, offset; /* pos = block * block_size + offset */ unsigned long pos, block, offset; /* pos = block * block_size + offset */
struct buffer_head * bh; struct buffer_head * bh;
char * bh_data;
struct sysv_dir_entry * de; struct sysv_dir_entry * de;
if (!inode) if (!inode)
...@@ -387,26 +377,26 @@ static int empty_dir(struct inode * inode) ...@@ -387,26 +377,26 @@ static int empty_dir(struct inode * inode)
goto bad_dir; goto bad_dir;
if (inode->i_size < pos) if (inode->i_size < pos)
goto bad_dir; goto bad_dir;
bh = sysv_file_bread(inode,0,0,&bh_data); bh = sysv_file_bread(inode,0,0);
if (!bh) if (!bh)
goto bad_dir; goto bad_dir;
de = (struct sysv_dir_entry *) (bh_data + 0*SYSV_DIRSIZE); de = (struct sysv_dir_entry *) (bh->b_data + 0*SYSV_DIRSIZE);
if (!de->inode || strcmp(de->name,".")) if (!de->inode || strcmp(de->name,"."))
goto bad_dir; goto bad_dir;
de = (struct sysv_dir_entry *) (bh_data + 1*SYSV_DIRSIZE); de = (struct sysv_dir_entry *) (bh->b_data + 1*SYSV_DIRSIZE);
if (!de->inode || strcmp(de->name,"..")) if (!de->inode || strcmp(de->name,".."))
goto bad_dir; goto bad_dir;
sb = inode->i_sb; sb = inode->i_sb;
while (pos < inode->i_size) { while (pos < inode->i_size) {
if (!bh) { if (!bh) {
bh = sysv_file_bread(inode,block,0,&bh_data); bh = sysv_file_bread(inode,block,0);
if (!bh) { if (!bh) {
/* offset = 0; */ block++; /* offset = 0; */ block++;
pos += sb->sv_block_size; pos += sb->sv_block_size;
continue; continue;
} }
} }
de = (struct sysv_dir_entry *) (bh_data + offset); de = (struct sysv_dir_entry *) (bh->b_data + offset);
pos += SYSV_DIRSIZE; pos += SYSV_DIRSIZE;
offset += SYSV_DIRSIZE; offset += SYSV_DIRSIZE;
if (de->inode) { if (de->inode) {
...@@ -553,7 +543,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy ...@@ -553,7 +543,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy
} }
inode->i_mode = S_IFLNK | 0777; inode->i_mode = S_IFLNK | 0777;
inode->i_op = &sysv_symlink_inode_operations; inode->i_op = &sysv_symlink_inode_operations;
name_block = sysv_file_bread(inode,0,1,&name_block_data); name_block = sysv_file_bread(inode,0,1);
if (!name_block) { if (!name_block) {
iput(dir); iput(dir);
inode->i_nlink--; inode->i_nlink--;
...@@ -562,6 +552,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy ...@@ -562,6 +552,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy
return -ENOSPC; return -ENOSPC;
} }
sb = inode->i_sb; sb = inode->i_sb;
name_block_data = name_block->b_data;
i = 0; i = 0;
while (i < sb->sv_block_size_1 && (c = *(symname++))) while (i < sb->sv_block_size_1 && (c = *(symname++)))
name_block_data[i++] = c; name_block_data[i++] = c;
...@@ -678,7 +669,6 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old ...@@ -678,7 +669,6 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old
{ {
struct inode * old_inode, * new_inode; struct inode * old_inode, * new_inode;
struct buffer_head * old_bh, * new_bh, * dir_bh; struct buffer_head * old_bh, * new_bh, * dir_bh;
char * dir_bh_data;
struct sysv_dir_entry * old_de, * new_de; struct sysv_dir_entry * old_de, * new_de;
int retval; int retval;
...@@ -745,10 +735,10 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old ...@@ -745,10 +735,10 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old
if (subdir(new_dir, old_inode)) if (subdir(new_dir, old_inode))
goto end_rename; goto end_rename;
retval = -EIO; retval = -EIO;
dir_bh = sysv_file_bread(old_inode,0,0,&dir_bh_data); dir_bh = sysv_file_bread(old_inode,0,0);
if (!dir_bh) if (!dir_bh)
goto end_rename; goto end_rename;
if (PARENT_INO(dir_bh_data) != old_dir->i_ino) if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
goto end_rename; goto end_rename;
retval = -EMLINK; retval = -EMLINK;
if (!new_inode && new_dir->i_nlink >= new_dir->i_sb->sv_link_max) if (!new_inode && new_dir->i_nlink >= new_dir->i_sb->sv_link_max)
...@@ -781,7 +771,7 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old ...@@ -781,7 +771,7 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old
mark_buffer_dirty(old_bh, 1); mark_buffer_dirty(old_bh, 1);
mark_buffer_dirty(new_bh, 1); mark_buffer_dirty(new_bh, 1);
if (dir_bh) { if (dir_bh) {
PARENT_INO(dir_bh_data) = new_dir->i_ino; PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
mark_buffer_dirty(dir_bh, 1); mark_buffer_dirty(dir_bh, 1);
old_dir->i_nlink--; old_dir->i_nlink--;
old_dir->i_dirt = 1; old_dir->i_dirt = 1;
......
...@@ -49,7 +49,6 @@ static int sysv_follow_link(struct inode * dir, struct inode * inode, ...@@ -49,7 +49,6 @@ static int sysv_follow_link(struct inode * dir, struct inode * inode,
{ {
int error; int error;
struct buffer_head * bh; struct buffer_head * bh;
char * bh_data;
*res_inode = NULL; *res_inode = NULL;
if (!dir) { if (!dir) {
...@@ -70,14 +69,14 @@ static int sysv_follow_link(struct inode * dir, struct inode * inode, ...@@ -70,14 +69,14 @@ static int sysv_follow_link(struct inode * dir, struct inode * inode,
iput(dir); iput(dir);
return -ELOOP; return -ELOOP;
} }
if (!(bh = sysv_file_bread(inode, 0, 0, &bh_data))) { /* is reading 1 block enough ?? */ if (!(bh = sysv_file_bread(inode, 0, 0))) { /* is reading 1 block enough ?? */
iput(inode); iput(inode);
iput(dir); iput(dir);
return -EIO; return -EIO;
} }
iput(inode); iput(inode);
current->link_count++; current->link_count++;
error = open_namei(bh_data,flag,mode,res_inode,dir); error = open_namei(bh->b_data,flag,mode,res_inode,dir);
current->link_count--; current->link_count--;
brelse(bh); brelse(bh);
return error; return error;
...@@ -96,10 +95,11 @@ static int sysv_readlink(struct inode * inode, char * buffer, int buflen) ...@@ -96,10 +95,11 @@ static int sysv_readlink(struct inode * inode, char * buffer, int buflen)
} }
if (buflen > inode->i_sb->sv_block_size_1) if (buflen > inode->i_sb->sv_block_size_1)
buflen = inode->i_sb->sv_block_size_1; buflen = inode->i_sb->sv_block_size_1;
bh = sysv_file_bread(inode, 0, 0, &bh_data); bh = sysv_file_bread(inode, 0, 0);
iput(inode); iput(inode);
if (!bh) if (!bh)
return 0; return 0;
bh_data = bh->b_data;
i = 0; i = 0;
while (i<buflen && (c = bh_data[i])) { while (i<buflen && (c = bh_data[i])) {
i++; i++;
......
This diff is collapsed.
...@@ -349,7 +349,9 @@ struct ext2_super_block { ...@@ -349,7 +349,9 @@ struct ext2_super_block {
unsigned long s_checkinterval; /* max. time between checks */ unsigned long s_checkinterval; /* max. time between checks */
unsigned long s_creator_os; /* OS */ unsigned long s_creator_os; /* OS */
unsigned long s_rev_level; /* Revision level */ unsigned long s_rev_level; /* Revision level */
unsigned long s_reserved[236]; /* Padding to the end of the block */ unsigned short s_def_resuid; /* Default uid for reserved blocks */
unsigned short s_def_resgid; /* Default gid for reserved blocks */
unsigned long s_reserved[235]; /* Padding to the end of the block */
}; };
#define EXT2_OS_LINUX 0 #define EXT2_OS_LINUX 0
...@@ -358,6 +360,9 @@ struct ext2_super_block { ...@@ -358,6 +360,9 @@ struct ext2_super_block {
#define EXT2_CURRENT_REV 0 #define EXT2_CURRENT_REV 0
#define EXT2_DEF_RESUID 0
#define EXT2_DEF_RESGID 0
/* /*
* Structure of a directory entry * Structure of a directory entry
*/ */
......
...@@ -49,6 +49,8 @@ struct ext2_sb_info { ...@@ -49,6 +49,8 @@ struct ext2_sb_info {
int s_rename_lock; int s_rename_lock;
struct wait_queue * s_rename_wait; struct wait_queue * s_rename_wait;
unsigned long s_mount_opt; unsigned long s_mount_opt;
unsigned short s_resuid;
unsigned short s_resgid;
unsigned short s_mount_state; unsigned short s_mount_state;
}; };
......
...@@ -226,6 +226,7 @@ struct inode { ...@@ -226,6 +226,7 @@ struct inode {
struct inode * i_mount; struct inode * i_mount;
struct socket * i_socket; struct socket * i_socket;
unsigned short i_count; unsigned short i_count;
unsigned short i_wcount;
unsigned short i_flags; unsigned short i_flags;
unsigned char i_lock; unsigned char i_lock;
unsigned char i_dirt; unsigned char i_dirt;
...@@ -464,6 +465,8 @@ extern int notify_change(struct inode *, struct iattr *); ...@@ -464,6 +465,8 @@ extern int notify_change(struct inode *, struct iattr *);
extern int namei(const char * pathname, struct inode ** res_inode); extern int namei(const char * pathname, struct inode ** res_inode);
extern int lnamei(const char * pathname, struct inode ** res_inode); extern int lnamei(const char * pathname, struct inode ** res_inode);
extern int permission(struct inode * inode,int mask); extern int permission(struct inode * inode,int mask);
extern int get_write_access(struct inode * inode);
extern void put_write_access(struct inode * inode);
extern int open_namei(const char * pathname, int flag, int mode, extern int open_namei(const char * pathname, int flag, int mode,
struct inode ** res_inode, struct inode * base); struct inode ** res_inode, struct inode * base);
extern int do_mknod(const char * filename, int mode, dev_t dev); extern int do_mknod(const char * filename, int mode, dev_t dev);
......
...@@ -20,6 +20,7 @@ enum { ...@@ -20,6 +20,7 @@ enum {
TQUEUE_BH, TQUEUE_BH,
SERIAL_BH, SERIAL_BH,
NET_BH, NET_BH,
IMMEDIATE_BH,
KEYBOARD_BH KEYBOARD_BH
}; };
......
...@@ -196,6 +196,7 @@ extern int do_mmap(struct file * file, unsigned long addr, unsigned long len, ...@@ -196,6 +196,7 @@ extern int do_mmap(struct file * file, unsigned long addr, unsigned long len,
extern void merge_segments(struct vm_area_struct *); extern void merge_segments(struct vm_area_struct *);
extern void insert_vm_struct(struct task_struct *, struct vm_area_struct *); extern void insert_vm_struct(struct task_struct *, struct vm_area_struct *);
extern int do_munmap(unsigned long, size_t); extern int do_munmap(unsigned long, size_t);
extern unsigned long get_unmapped_area(unsigned long);
#define read_swap_page(nr,buf) \ #define read_swap_page(nr,buf) \
rw_swap_page(READ,(nr),(buf)) rw_swap_page(READ,(nr),(buf))
...@@ -232,7 +233,7 @@ extern unsigned short * mem_map; ...@@ -232,7 +233,7 @@ extern unsigned short * mem_map;
#define GFP_USER 0x02 #define GFP_USER 0x02
#define GFP_KERNEL 0x03 #define GFP_KERNEL 0x03
#define GFP_NOBUFFER 0x04 #define GFP_NOBUFFER 0x04
#define GFP_NFS 0x05
/* /*
* vm_ops not present page codes for shared memory. * vm_ops not present page codes for shared memory.
......
...@@ -50,7 +50,9 @@ struct mtop { ...@@ -50,7 +50,9 @@ struct mtop {
#define MTTELL 23 /* tell block (Tandberg, etc.) */ #define MTTELL 23 /* tell block (Tandberg, etc.) */
#define MTSETDRVBUFFER 24 /* set the drive buffering according to SCSI-2 */ #define MTSETDRVBUFFER 24 /* set the drive buffering according to SCSI-2 */
/* ordinary buffered operation with code 1 */ /* ordinary buffered operation with code 1 */
#define MTFSS 25 /* space forward over setmarks */
#define MTBSS 26 /* space backward over setmarks */
#define MTWSM 27 /* write setmarks */
/* structure for MTIOCGET - mag tape get status command */ /* structure for MTIOCGET - mag tape get status command */
......
...@@ -288,8 +288,7 @@ struct task_struct { ...@@ -288,8 +288,7 @@ struct task_struct {
/* file system info */ /* file system info */
int link_count; int link_count;
struct tty_struct *tty; /* NULL if no tty */ struct tty_struct *tty; /* NULL if no tty */
/* shm stuff */ /* ipc stuff */
struct shm_desc *shm;
struct sem_undo *semundo; struct sem_undo *semundo;
/* ldt for this task - used by Wine. If NULL, default_ldt is used */ /* ldt for this task - used by Wine. If NULL, default_ldt is used */
struct desc_struct *ldt; struct desc_struct *ldt;
...@@ -343,7 +342,7 @@ struct task_struct { ...@@ -343,7 +342,7 @@ struct task_struct {
/* comm */ "swapper", \ /* comm */ "swapper", \
/* vm86_info */ NULL, 0, 0, 0, 0, \ /* vm86_info */ NULL, 0, 0, 0, 0, \
/* fs info */ 0,NULL, \ /* fs info */ 0,NULL, \
/* ipc */ NULL, NULL, \ /* ipc */ NULL, \
/* ldt */ NULL, \ /* ldt */ NULL, \
/* tss */ INIT_TSS, \ /* tss */ INIT_TSS, \
/* fs */ { INIT_FS }, \ /* fs */ { INIT_FS }, \
......
...@@ -14,9 +14,13 @@ struct shmid_ds { ...@@ -14,9 +14,13 @@ struct shmid_ds {
/* the following are private */ /* the following are private */
unsigned short shm_npages; /* size of segment (pages) */ unsigned short shm_npages; /* size of segment (pages) */
unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */ unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */
struct shm_desc *attaches; /* descriptors for attaches */ struct vm_area_struct *attaches; /* descriptors for attaches */
}; };
/* permission flag for shmget */
#define SHM_R 0400 /* or S_IRUGO from <linux/stat.h> */
#define SHM_W 0200 /* or S_IWUGO from <linux/stat.h> */
/* mode for attach */ /* mode for attach */
#define SHM_RDONLY 010000 /* read-only access */ #define SHM_RDONLY 010000 /* read-only access */
#define SHM_RND 020000 /* round attach address to SHMLBA boundary */ #define SHM_RND 020000 /* round attach address to SHMLBA boundary */
...@@ -35,7 +39,7 @@ struct shminfo { ...@@ -35,7 +39,7 @@ struct shminfo {
}; };
/* address range for shared memory attaches if no address passed to shmat() */ /* address range for shared memory attaches if no address passed to shmat() */
#define SHM_RANGE_START 0x40000000 #define SHM_RANGE_START 0x50000000
#define SHM_RANGE_END 0x60000000 #define SHM_RANGE_END 0x60000000
/* format of page table entries that correspond to shared memory pages /* format of page table entries that correspond to shared memory pages
...@@ -89,20 +93,6 @@ struct shm_info { ...@@ -89,20 +93,6 @@ struct shm_info {
ulong swap_successes; ulong swap_successes;
}; };
/*
* Per process internal structure for managing segments.
* A shmat will add to and shmdt will remove from the list.
*/
struct shm_desc {
struct task_struct *task; /* attacher */
unsigned long shm_sgn; /* signature for this attach */
unsigned long start; /* virt addr of attach, multiple of SHMLBA */
unsigned long end; /* multiple of SHMLBA */
struct shm_desc *task_next; /* next attach for task */
struct shm_desc *seg_next; /* next attach for segment */
};
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_SHM_H_ */ #endif /* _LINUX_SHM_H_ */
......
...@@ -335,54 +335,25 @@ struct sysv_dir_entry { ...@@ -335,54 +335,25 @@ struct sysv_dir_entry {
#define SYSV2_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_SYSV2) #define SYSV2_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_SYSV2)
#define COH_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_COH) #define COH_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_COH)
/* Because the block size may be smaller than 1024 (which is the unit used by /* sv_get_hash_table(sb,dev,block) is equivalent to get_hash_table(dev,block,block_size) */
the disk drivers and the buffer code), many functions must return a pointer
to the buffer data additionally to the buffer head pointer.
*/
#if 0
struct bh_data {
struct buffer_head * bh;
char * bh_data;
};
#endif
/* sysv_bread(sb,dev,block,...) would be equivalent to
bread(dev,block,BLOCK_SIZE)
if the block size were always 1024, which is the only one bread() supports.
*/
static inline struct buffer_head * static inline struct buffer_head *
sysv_bread (struct super_block *sb, int dev, unsigned int block, char* * data) sv_get_hash_table (struct super_block *sb, int dev, unsigned int block)
{
struct buffer_head *bh;
if (!(bh = bread (dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE)))
return NULL;
*data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
return bh;
}
/* locks - protect against simultaneous write and truncate */
extern void _coh_wait_on_inode (struct inode * inode);
extern inline void coh_wait_on_inode (struct inode * inode)
{ {
if (inode->u.sysv_i.i_lock) return get_hash_table (dev, block + sb->sv_block_base, sb->sv_block_size);
_coh_wait_on_inode(inode);
} }
extern inline void coh_lock_inode (struct inode * inode) /* sv_getblk(sb,dev,block) is equivalent to getblk(dev,block,block_size) */
static inline struct buffer_head *
sv_getblk (struct super_block *sb, int dev, unsigned int block)
{ {
if (inode->u.sysv_i.i_lock) return getblk (dev, block + sb->sv_block_base, sb->sv_block_size);
_coh_wait_on_inode(inode);
inode->u.sysv_i.i_lock = 1;
} }
extern inline void coh_unlock_inode (struct inode * inode) /* sv_bread(sb,dev,block) is equivalent to bread(dev,block,block_size) */
static inline struct buffer_head *
sv_bread (struct super_block *sb, int dev, unsigned int block)
{ {
inode->u.sysv_i.i_lock = 0; return bread (dev, block + sb->sv_block_base, sb->sv_block_size);
wake_up(&inode->u.sysv_i.i_wait);
} }
...@@ -412,8 +383,8 @@ extern unsigned long sysv_count_free_blocks(struct super_block *sb); ...@@ -412,8 +383,8 @@ extern unsigned long sysv_count_free_blocks(struct super_block *sb);
extern int sysv_bmap(struct inode *,int); extern int sysv_bmap(struct inode *,int);
extern struct buffer_head * sysv_getblk(struct inode *, unsigned int, int, char* *); extern struct buffer_head * sysv_getblk(struct inode *, unsigned int, int);
extern struct buffer_head * sysv_file_bread(struct inode *, int, int, char* *); extern struct buffer_head * sysv_file_bread(struct inode *, int, int);
extern int sysv_file_read(struct inode *, struct file *, char *, int); extern int sysv_file_read(struct inode *, struct file *, char *, int);
extern void sysv_truncate(struct inode *); extern void sysv_truncate(struct inode *);
......
...@@ -10,10 +10,6 @@ struct sysv_inode_info { ...@@ -10,10 +10,6 @@ struct sysv_inode_info {
* then 1 double indirection block, * then 1 double indirection block,
* then 1 triple indirection block. * then 1 triple indirection block.
*/ */
/* the following are only used if block_size < BLOCK_SIZE */
int i_lock; /* lock to protect against simultaneous */
struct wait_queue * i_wait; /* write and truncate */
/* */
}; };
#endif #endif
......
...@@ -16,7 +16,6 @@ struct sysv_sb_info { ...@@ -16,7 +16,6 @@ struct sysv_sb_info {
unsigned int s_block_size_1; /* block_size - 1 */ unsigned int s_block_size_1; /* block_size - 1 */
unsigned int s_block_size_bits; /* log2(block_size) */ unsigned int s_block_size_bits; /* log2(block_size) */
unsigned int s_block_size_ratio; /* BLOCK_SIZE / block_size */ unsigned int s_block_size_ratio; /* BLOCK_SIZE / block_size */
unsigned int s_block_size_ratio_1; /* block_size_ratio - 1 */
unsigned int s_block_size_ratio_bits; /* log2(block_size_ratio) */ unsigned int s_block_size_ratio_bits; /* log2(block_size_ratio) */
char s_convert; /* flag whether byte ordering requires conversion */ char s_convert; /* flag whether byte ordering requires conversion */
char s_kludge_symlinks; /* flag whether symlinks have a kludgey mode */ char s_kludge_symlinks; /* flag whether symlinks have a kludgey mode */
...@@ -33,15 +32,24 @@ struct sysv_sb_info { ...@@ -33,15 +32,24 @@ struct sysv_sb_info {
unsigned int s_ind_per_block_2_1; /* ind_per_block ^ 2 - 1 */ unsigned int s_ind_per_block_2_1; /* ind_per_block ^ 2 - 1 */
unsigned int s_ind_per_block_2_bits; /* log2(ind_per_block^2) */ unsigned int s_ind_per_block_2_bits; /* log2(ind_per_block^2) */
unsigned int s_ind_per_block_3; /* ind_per_block ^ 3 */ unsigned int s_ind_per_block_3; /* ind_per_block ^ 3 */
unsigned int s_ind_per_block_block_size_1; /* ind_per_block*block_size - 1 */
unsigned int s_ind_per_block_block_size_bits; /* log2(ind_per_block*block_size) */
unsigned int s_ind_per_block_2_block_size_1; /* ind_per_block^2 * block_size - 1 */
unsigned int s_ind_per_block_2_block_size_bits; /* log2(ind_per_block^2 * block_size) */
unsigned int s_ind0_size; /* 10 * block_size */
unsigned int s_ind1_size; /* (10 + ipb) * block_size */
unsigned int s_ind2_size; /* (10 + ipb + ipb^2) * block_size */
unsigned int s_toobig_block; /* 10 + ipb + ipb^2 + ipb^3 */ unsigned int s_toobig_block; /* 10 + ipb + ipb^2 + ipb^3 */
unsigned int s_block_base; /* physical block number of block 0 */ unsigned int s_block_base; /* physical block number of block 0 */
unsigned short s_fic_size; /* free inode cache size, NICINOD */ unsigned short s_fic_size; /* free inode cache size, NICINOD */
unsigned short s_flc_size; /* free block list chunk size, NICFREE */ unsigned short s_flc_size; /* free block list chunk size, NICFREE */
/* The superblock is kept in a disk buffer: */ /* The superblock is kept in one or two disk buffers: */
struct buffer_head *s_bh; struct buffer_head *s_bh1;
struct buffer_head *s_bh2;
/* These are pointers into the disk buffer, to compensate for /* These are pointers into the disk buffer, to compensate for
different superblock layout. */ different superblock layout. */
char * s_sbd; /* entire superblock data */ char * s_sbd1; /* entire superblock data, for part 1 */
char * s_sbd2; /* entire superblock data, for part 2 */
unsigned short *s_sb_fic_count; /* pointer to s_sbd->s_ninode */ unsigned short *s_sb_fic_count; /* pointer to s_sbd->s_ninode */
unsigned short *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */ unsigned short *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
unsigned short *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */ unsigned short *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
...@@ -57,7 +65,7 @@ struct sysv_sb_info { ...@@ -57,7 +65,7 @@ struct sysv_sb_info {
unsigned long s_ndatazones; /* total number of data zones */ unsigned long s_ndatazones; /* total number of data zones */
unsigned long s_nzones; /* same as s_sbd->s_fsize */ unsigned long s_nzones; /* same as s_sbd->s_fsize */
}; };
/* The fields s_block_size_ratio, s_toobig_block, s_sbd are currently unused. */ /* The fields s_block_size_ratio, s_ind_per_block_2_1, s_toobig_block are currently unused. */
/* sv_ == u.sysv_sb.s_ */ /* sv_ == u.sysv_sb.s_ */
#define sv_type u.sysv_sb.s_type #define sv_type u.sysv_sb.s_type
...@@ -65,7 +73,6 @@ struct sysv_sb_info { ...@@ -65,7 +73,6 @@ struct sysv_sb_info {
#define sv_block_size_1 u.sysv_sb.s_block_size_1 #define sv_block_size_1 u.sysv_sb.s_block_size_1
#define sv_block_size_bits u.sysv_sb.s_block_size_bits #define sv_block_size_bits u.sysv_sb.s_block_size_bits
#define sv_block_size_ratio u.sysv_sb.s_block_size_ratio #define sv_block_size_ratio u.sysv_sb.s_block_size_ratio
#define sv_block_size_ratio_1 u.sysv_sb.s_block_size_ratio_1
#define sv_block_size_ratio_bits u.sysv_sb.s_block_size_ratio_bits #define sv_block_size_ratio_bits u.sysv_sb.s_block_size_ratio_bits
#define sv_convert u.sysv_sb.s_convert #define sv_convert u.sysv_sb.s_convert
#define sv_kludge_symlinks u.sysv_sb.s_kludge_symlinks #define sv_kludge_symlinks u.sysv_sb.s_kludge_symlinks
...@@ -81,12 +88,21 @@ struct sysv_sb_info { ...@@ -81,12 +88,21 @@ struct sysv_sb_info {
#define sv_ind_per_block_2_1 u.sysv_sb.s_ind_per_block_2_1 #define sv_ind_per_block_2_1 u.sysv_sb.s_ind_per_block_2_1
#define sv_ind_per_block_2_bits u.sysv_sb.s_ind_per_block_2_bits #define sv_ind_per_block_2_bits u.sysv_sb.s_ind_per_block_2_bits
#define sv_ind_per_block_3 u.sysv_sb.s_ind_per_block_3 #define sv_ind_per_block_3 u.sysv_sb.s_ind_per_block_3
#define sv_ind_per_block_block_size_1 u.sysv_sb.s_ind_per_block_block_size_1
#define sv_ind_per_block_block_size_bits u.sysv_sb.s_ind_per_block_block_size_bits
#define sv_ind_per_block_2_block_size_1 u.sysv_sb.s_ind_per_block_2_block_size_1
#define sv_ind_per_block_2_block_size_bits u.sysv_sb.s_ind_per_block_2_block_size_bits
#define sv_ind0_size u.sysv_sb.s_ind0_size
#define sv_ind1_size u.sysv_sb.s_ind1_size
#define sv_ind2_size u.sysv_sb.s_ind2_size
#define sv_toobig_block u.sysv_sb.s_toobig_block #define sv_toobig_block u.sysv_sb.s_toobig_block
#define sv_block_base u.sysv_sb.s_block_base #define sv_block_base u.sysv_sb.s_block_base
#define sv_fic_size u.sysv_sb.s_fic_size #define sv_fic_size u.sysv_sb.s_fic_size
#define sv_flc_size u.sysv_sb.s_flc_size #define sv_flc_size u.sysv_sb.s_flc_size
#define sv_bh u.sysv_sb.s_bh #define sv_bh1 u.sysv_sb.s_bh1
#define sv_sbd u.sysv_sb.s_sbd #define sv_bh2 u.sysv_sb.s_bh2
#define sv_sbd1 u.sysv_sb.s_sbd1
#define sv_sbd2 u.sysv_sb.s_sbd2
#define sv_sb_fic_count u.sysv_sb.s_sb_fic_count #define sv_sb_fic_count u.sysv_sb.s_sb_fic_count
#define sv_sb_fic_inodes u.sysv_sb.s_sb_fic_inodes #define sv_sb_fic_inodes u.sysv_sb.s_sb_fic_inodes
#define sv_sb_total_free_inodes u.sysv_sb.s_sb_total_free_inodes #define sv_sb_total_free_inodes u.sysv_sb.s_sb_total_free_inodes
......
...@@ -57,7 +57,7 @@ typedef struct tq_struct * task_queue; ...@@ -57,7 +57,7 @@ typedef struct tq_struct * task_queue;
#define DECLARE_TASK_QUEUE(q) task_queue q = &tq_last #define DECLARE_TASK_QUEUE(q) task_queue q = &tq_last
extern struct tq_struct tq_last; extern struct tq_struct tq_last;
extern task_queue tq_timer; extern task_queue tq_timer, tq_immediate;
#ifdef INCLUDE_INLINE_FUNCS #ifdef INCLUDE_INLINE_FUNCS
struct tq_struct tq_last = { struct tq_struct tq_last = {
......
This diff is collapsed.
...@@ -132,21 +132,11 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr) ...@@ -132,21 +132,11 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
return -ENOSYS; return -ENOSYS;
} }
int shm_fork (struct task_struct *p1, struct task_struct *p2)
{
return 0;
}
void sem_exit (void) void sem_exit (void)
{ {
return; return;
} }
void shm_exit (void)
{
return;
}
int shm_swap (int prio) int shm_swap (int prio)
{ {
return 0; return 0;
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/malloc.h> #include <linux/malloc.h>
#include <asm/segment.h> #include <asm/segment.h>
extern void shm_exit (void);
extern void sem_exit (void); extern void sem_exit (void);
int getrusage(struct task_struct *, int, struct rusage *); int getrusage(struct task_struct *, int, struct rusage *);
...@@ -413,8 +412,6 @@ NORET_TYPE void do_exit(long code) ...@@ -413,8 +412,6 @@ NORET_TYPE void do_exit(long code)
fake_volatile: fake_volatile:
if (current->semundo) if (current->semundo)
sem_exit(); sem_exit();
if (current->shm)
shm_exit();
exit_mm(); exit_mm();
exit_files(); exit_files();
exit_fs(); exit_fs();
......
...@@ -32,7 +32,6 @@ asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call"); ...@@ -32,7 +32,6 @@ asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
#define MAX_TASKS_PER_USER (NR_TASKS/2) #define MAX_TASKS_PER_USER (NR_TASKS/2)
#define MIN_TASKS_LEFT_FOR_ROOT 4 #define MIN_TASKS_LEFT_FOR_ROOT 4
extern int shm_fork(struct task_struct *, struct task_struct *);
long last_pid=0; long last_pid=0;
static int find_empty_process(void) static int find_empty_process(void)
...@@ -104,6 +103,8 @@ static int dup_mmap(struct task_struct * tsk) ...@@ -104,6 +103,8 @@ static int dup_mmap(struct task_struct * tsk)
tmp->vm_next = NULL; tmp->vm_next = NULL;
if (tmp->vm_inode) if (tmp->vm_inode)
tmp->vm_inode->i_count++; tmp->vm_inode->i_count++;
if (tmp->vm_ops && tmp->vm_ops->open)
tmp->vm_ops->open(tmp);
*p = tmp; *p = tmp;
p = &tmp->vm_next; p = &tmp->vm_next;
} }
...@@ -141,13 +142,12 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * p) ...@@ -141,13 +142,12 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * p)
p->mm->cmin_flt = p->mm->cmaj_flt = 0; p->mm->cmin_flt = p->mm->cmaj_flt = 0;
if (copy_page_tables(p)) if (copy_page_tables(p))
return 1; return 1;
dup_mmap(p); return dup_mmap(p);
} else { } else {
if (clone_page_tables(p)) if (clone_page_tables(p))
return 1; return 1;
dup_mmap(p); /* wrong.. */ return dup_mmap(p); /* wrong.. */
} }
return shm_fork(current, p);
} }
static void copy_fs(unsigned long clone_flags, struct task_struct * p) static void copy_fs(unsigned long clone_flags, struct task_struct * p)
...@@ -243,6 +243,7 @@ asmlinkage int sys_fork(struct pt_regs regs) ...@@ -243,6 +243,7 @@ asmlinkage int sys_fork(struct pt_regs regs)
__asm__("clts ; fnsave %0 ; frstor %0":"=m" (p->tss.i387)); __asm__("clts ; fnsave %0 ; frstor %0":"=m" (p->tss.i387));
if (copy_mm(clone_flags, p)) if (copy_mm(clone_flags, p))
goto bad_fork_cleanup; goto bad_fork_cleanup;
p->semundo = NULL;
copy_files(clone_flags, p); copy_files(clone_flags, p);
copy_fs(clone_flags, p); copy_fs(clone_flags, p);
set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/locks.h> #include <linux/locks.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/delay.h>
#ifdef CONFIG_INET #ifdef CONFIG_INET
#include <linux/net.h> #include <linux/net.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
...@@ -143,6 +144,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */ ...@@ -143,6 +144,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
X(bh_mask), X(bh_mask),
X(add_timer), X(add_timer),
X(del_timer), X(del_timer),
X(tq_immediate),
/* dma handling */ /* dma handling */
X(request_dma), X(request_dma),
...@@ -157,6 +159,10 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */ ...@@ -157,6 +159,10 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
X(current), X(current),
X(jiffies), X(jiffies),
X(xtime), X(xtime),
X(loops_per_sec),
X(kill_proc),
X(kill_pg),
X(kill_sl),
/* misc */ /* misc */
X(panic), X(panic),
......
...@@ -43,6 +43,7 @@ volatile struct timeval xtime; /* The current time */ ...@@ -43,6 +43,7 @@ volatile struct timeval xtime; /* The current time */
int tickadj = 500/HZ; /* microsecs */ int tickadj = 500/HZ; /* microsecs */
DECLARE_TASK_QUEUE(tq_timer); DECLARE_TASK_QUEUE(tq_timer);
DECLARE_TASK_QUEUE(tq_immediate);
/* /*
* phase-lock loop variables * phase-lock loop variables
...@@ -589,6 +590,11 @@ void tqueue_bh(void * unused) ...@@ -589,6 +590,11 @@ void tqueue_bh(void * unused)
run_task_queue(&tq_timer); run_task_queue(&tq_timer);
} }
void immediate_bh(void * unused)
{
run_task_queue(&tq_immediate);
}
/* /*
* The int argument is really a (struct pt_regs *), in case the * The int argument is really a (struct pt_regs *), in case the
* interrupt wants to know from where it was called. The timer * interrupt wants to know from where it was called. The timer
...@@ -830,6 +836,7 @@ void sched_init(void) ...@@ -830,6 +836,7 @@ void sched_init(void)
bh_base[TIMER_BH].routine = timer_bh; bh_base[TIMER_BH].routine = timer_bh;
bh_base[TQUEUE_BH].routine = tqueue_bh; bh_base[TQUEUE_BH].routine = tqueue_bh;
bh_base[IMMEDIATE_BH].routine = immediate_bh;
if (sizeof(struct sigaction) != 16) if (sizeof(struct sigaction) != 16)
panic("Struct sigaction MUST be 16 bytes"); panic("Struct sigaction MUST be 16 bytes");
set_tss_desc(gdt+FIRST_TSS_ENTRY,&init_task.tss); set_tss_desc(gdt+FIRST_TSS_ENTRY,&init_task.tss);
......
...@@ -71,6 +71,8 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len, ...@@ -71,6 +71,8 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len,
default: default:
return -EINVAL; return -EINVAL;
} }
if ((flags & MAP_DENYWRITE) && (file->f_inode->i_wcount > 0))
return -ETXTBSY;
} else if ((flags & MAP_TYPE) == MAP_SHARED) } else if ((flags & MAP_TYPE) == MAP_SHARED)
return -EINVAL; return -EINVAL;
...@@ -85,23 +87,8 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len, ...@@ -85,23 +87,8 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len,
if (len > TASK_SIZE || addr > TASK_SIZE - len) if (len > TASK_SIZE || addr > TASK_SIZE - len)
return -EINVAL; return -EINVAL;
} else { } else {
struct vm_area_struct * vmm; addr = get_unmapped_area(len);
if (!addr)
/* Maybe this works.. Ugly it is. */
addr = SHM_RANGE_START;
while (addr+len < SHM_RANGE_END) {
for (vmm = current->mm->mmap ; vmm ; vmm = vmm->vm_next) {
if (addr >= vmm->vm_end)
continue;
if (addr + len <= vmm->vm_start)
continue;
addr = PAGE_ALIGN(vmm->vm_end);
break;
}
if (!vmm)
break;
}
if (addr+len >= SHM_RANGE_END)
return -ENOMEM; return -ENOMEM;
} }
...@@ -157,22 +144,45 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len, ...@@ -157,22 +144,45 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len,
if (error) { if (error) {
kfree(vma); kfree(vma);
if (!current->errno) return error;
current->errno = -error;
return -1;
} }
insert_vm_struct(current, vma); insert_vm_struct(current, vma);
merge_segments(current->mm->mmap); merge_segments(current->mm->mmap);
return addr; return addr;
} }
/*
* Get an address range which is currently unmapped.
* For mmap() without MAP_FIXED and shmat() with addr=0.
* Return value 0 means ENOMEM.
*/
unsigned long get_unmapped_area(unsigned long len)
{
struct vm_area_struct * vmm;
unsigned long gap_start = 0, gap_end;
for (vmm = current->mm->mmap; ; vmm = vmm->vm_next) {
if (gap_start < SHM_RANGE_START)
gap_start = SHM_RANGE_START;
if (!vmm || ((gap_end = vmm->vm_start) > SHM_RANGE_END))
gap_end = SHM_RANGE_END;
gap_start = PAGE_ALIGN(gap_start);
gap_end &= PAGE_MASK;
if ((gap_start <= gap_end) && (gap_end - gap_start >= len))
return gap_start;
if (!vmm)
return 0;
gap_start = vmm->vm_end;
}
}
asmlinkage int sys_mmap(unsigned long *buffer) asmlinkage int sys_mmap(unsigned long *buffer)
{ {
int error; int error;
unsigned long flags; unsigned long flags;
struct file * file = NULL; struct file * file = NULL;
error = verify_area(VERIFY_READ, buffer, 6*4); error = verify_area(VERIFY_READ, buffer, 6*sizeof(long));
if (error) if (error)
return error; return error;
flags = get_fs_long(buffer+3); flags = get_fs_long(buffer+3);
...@@ -252,6 +262,8 @@ void unmap_fixup(struct vm_area_struct *area, ...@@ -252,6 +262,8 @@ void unmap_fixup(struct vm_area_struct *area,
mpnt->vm_start = end; mpnt->vm_start = end;
if (mpnt->vm_inode) if (mpnt->vm_inode)
mpnt->vm_inode->i_count++; mpnt->vm_inode->i_count++;
if (mpnt->vm_ops && mpnt->vm_ops->open)
mpnt->vm_ops->open(mpnt);
area->vm_end = addr; /* Truncate area */ area->vm_end = addr; /* Truncate area */
insert_vm_struct(current, mpnt); insert_vm_struct(current, mpnt);
} }
...@@ -261,6 +273,12 @@ void unmap_fixup(struct vm_area_struct *area, ...@@ -261,6 +273,12 @@ void unmap_fixup(struct vm_area_struct *area,
if (!mpnt) if (!mpnt)
return; return;
*mpnt = *area; *mpnt = *area;
if (mpnt->vm_ops && mpnt->vm_ops->open)
mpnt->vm_ops->open(mpnt);
if (area->vm_ops && area->vm_ops->close) {
area->vm_end = area->vm_start;
area->vm_ops->close(area);
}
insert_vm_struct(current, mpnt); insert_vm_struct(current, mpnt);
} }
...@@ -416,7 +434,7 @@ void merge_segments(struct vm_area_struct *mpnt) ...@@ -416,7 +434,7 @@ void merge_segments(struct vm_area_struct *mpnt)
/* /*
* and if we have an inode, the offsets must be contiguous.. * and if we have an inode, the offsets must be contiguous..
*/ */
if (mpnt->vm_inode != NULL) { if ((mpnt->vm_inode != NULL) || (mpnt->vm_flags & VM_SHM)) {
if (prev->vm_offset + prev->vm_end - prev->vm_start != mpnt->vm_offset) if (prev->vm_offset + prev->vm_end - prev->vm_start != mpnt->vm_offset)
continue; continue;
} }
......
...@@ -76,6 +76,8 @@ static inline int mprotect_fixup_start(struct vm_area_struct * vma, ...@@ -76,6 +76,8 @@ static inline int mprotect_fixup_start(struct vm_area_struct * vma,
n->vm_page_prot = prot; n->vm_page_prot = prot;
if (n->vm_inode) if (n->vm_inode)
n->vm_inode->i_count++; n->vm_inode->i_count++;
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current, n); insert_vm_struct(current, n);
merge_segments(current->mm->mmap); merge_segments(current->mm->mmap);
return 0; return 0;
...@@ -98,6 +100,8 @@ static inline int mprotect_fixup_end(struct vm_area_struct * vma, ...@@ -98,6 +100,8 @@ static inline int mprotect_fixup_end(struct vm_area_struct * vma,
n->vm_page_prot = prot; n->vm_page_prot = prot;
if (n->vm_inode) if (n->vm_inode)
n->vm_inode->i_count++; n->vm_inode->i_count++;
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current, n); insert_vm_struct(current, n);
merge_segments(current->mm->mmap); merge_segments(current->mm->mmap);
return 0; return 0;
...@@ -129,6 +133,10 @@ static inline int mprotect_fixup_middle(struct vm_area_struct * vma, ...@@ -129,6 +133,10 @@ static inline int mprotect_fixup_middle(struct vm_area_struct * vma,
vma->vm_page_prot = prot; vma->vm_page_prot = prot;
if (vma->vm_inode) if (vma->vm_inode)
vma->vm_inode->i_count += 2; vma->vm_inode->i_count += 2;
if (vma->vm_ops && vma->vm_ops->open) {
vma->vm_ops->open(left);
vma->vm_ops->open(right);
}
insert_vm_struct(current, left); insert_vm_struct(current, left);
insert_vm_struct(current, right); insert_vm_struct(current, right);
merge_segments(current->mm->mmap); merge_segments(current->mm->mmap);
...@@ -210,6 +218,8 @@ asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot) ...@@ -210,6 +218,8 @@ asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot)
start = tmp; start = tmp;
if (vma->vm_end <= start) { if (vma->vm_end <= start) {
vma = vma->vm_next; vma = vma->vm_next;
if (vma && vma->vm_start < start)
vma = vma->vm_next;
if (!vma || vma->vm_start != start) if (!vma || vma->vm_start != start)
return -EFAULT; return -EFAULT;
} }
......
...@@ -616,6 +616,7 @@ do { unsigned long size = PAGE_SIZE << high; \ ...@@ -616,6 +616,7 @@ do { unsigned long size = PAGE_SIZE << high; \
unsigned long __get_free_pages(int priority, unsigned long order) unsigned long __get_free_pages(int priority, unsigned long order)
{ {
unsigned long flags; unsigned long flags;
int reserved_pages;
if (intr_count && priority != GFP_ATOMIC) { if (intr_count && priority != GFP_ATOMIC) {
static int count = 0; static int count = 0;
...@@ -625,10 +626,13 @@ unsigned long __get_free_pages(int priority, unsigned long order) ...@@ -625,10 +626,13 @@ unsigned long __get_free_pages(int priority, unsigned long order)
priority = GFP_ATOMIC; priority = GFP_ATOMIC;
} }
} }
reserved_pages = 5;
if (priority != GFP_NFS)
reserved_pages = min_free_pages;
save_flags(flags); save_flags(flags);
repeat: repeat:
cli(); cli();
if ((priority==GFP_ATOMIC) || nr_free_pages > min_free_pages) { if ((priority==GFP_ATOMIC) || nr_free_pages > reserved_pages) {
RMQUEUE(order); RMQUEUE(order);
restore_flags(flags); restore_flags(flags);
return 0; return 0;
......
...@@ -67,42 +67,6 @@ unsigned long ip_get_mask(unsigned long addr) ...@@ -67,42 +67,6 @@ unsigned long ip_get_mask(unsigned long addr)
return(0); return(0);
} }
/*
* Perform an IP address matching operation
*/
int ip_addr_match(unsigned long me, unsigned long him)
{
int i;
unsigned long mask=0xFFFFFFFF;
/*
* Simple case
*/
if (me == him)
return(1);
/*
* Look for a match ending in all 1's
*/
for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8)
{
if ((me & 0xFF) != (him & 0xFF))
{
/*
* The only way this could be a match is for
* the rest of addr1 to be 0 or 255.
*/
if (me != 0 && me != mask)
return(0);
return(1);
}
}
return(1);
}
/* /*
* Check the address for our address, broadcasts, etc. * Check the address for our address, broadcasts, etc.
* *
......
...@@ -176,8 +176,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev) ...@@ -176,8 +176,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
* Build Layer 2-3 headers for message back to source. * Build Layer 2-3 headers for message back to source.
*/ */
offset = ip_build_header(skb, dev->pa_addr, iph->saddr, { unsigned long our_addr = dev->pa_addr;
&ndev, IPPROTO_ICMP, NULL, len, skb_in->ip_hdr->tos,255); if (iph->daddr != our_addr && ip_chk_addr(iph->daddr) == IS_MYADDR)
our_addr = iph->daddr;
offset = ip_build_header(skb, our_addr, iph->saddr,
&ndev, IPPROTO_ICMP, NULL, len,
skb_in->ip_hdr->tos,255);
}
if (offset < 0) if (offset < 0)
{ {
......
...@@ -276,7 +276,7 @@ static int udp_send(struct sock *sk, struct sockaddr_in *sin, ...@@ -276,7 +276,7 @@ static int udp_send(struct sock *sk, struct sockaddr_in *sin,
*/ */
buff = skb->data; buff = skb->data;
saddr = 0; saddr = sk->saddr;
dev = NULL; dev = NULL;
tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr, tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
&dev, IPPROTO_UDP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl); &dev, IPPROTO_UDP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
......
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