Commit 9cb9f18b authored by Linus Torvalds's avatar Linus Torvalds

[PATCH] Linux-0.99.10 (June 7, 1993)

People finally gave up on net-1, Ross Biro grew tired of the flames, and
net-2 appears with Fred van Kempen as maintainer.  This is the big
switch-over version.

fsync() isn't just a stub any more, and System V IPC is also showing up.

The "struct file" filetable is made dynamic, instaed of a static
allocation.  For the first time you can have _lots_ of files open.

Stub for iBCS2 emulation code.

[original announcement below]

I've finally released an official version of linux-0.99 patchlevel 10:
there have been various alpha versions floating around which differ in
details (notably networking code), which shouldn't be used any more.
The new linux version is available only as full source code: the diffs
would have been too big to be useful.  You can find linux-0.99.10.tar.z
(along with keytables.tar.z) on nic.funet.fi: pub/OS/Linux/PEOPLE/Linus
and probably on tsx-11 and other linux archives within a day or two (so
check there first if you are in the states).

Linux-0.99 pl10 has a number of new features and changes in interface.
The most notable of these are:

 - the networking code is reorganized (generally called "net-2",
   although unrelated to the BSD release).  The new code implements a
   lot of standard features lacking in net-1, and also changes the user
   interface to be closer to the BSD standards.  Notably, the old
   configuration binaries won't work, so to get the new networking to
   work you'll have to get the net-2 binaries as well.  The networking
   binaries are available on tsx-11.mit.edu (and mirrors) under the
   directory pub/linux/packages/net/net-2 (and the setup syntax has
   changed somewhat..)

   The networking code has been mainly organized and rewritten by Fred
   van Kempen, with drivers by Donald Becker.

 - serial line setup has been changed: linux 0.99 pl10 does *not* try to
   autodetect serial ports very agressively.  If you have other serial
   ports than the standard com1/com2, or nonstandard IRQ etc values,
   this means that it's less likely to work without any help.  The
   solution is not to recompile the kernel - you should get the
   "setserial" program available from tsx-11.mit.edu in the directory
   pub/linux/sources/sbin/setserial-2.01.tar.z that allows you to
   dynamically configure your serial ports to suit your setup.

   The main organizer behind the serial line changes is tytso (Theodore
   Ts'o).

 - Keyboard setup has changed: it is no longer hardcoded at compile
   time, but instead you can use the new "loadkeys" program to load in a
   new keyboard map on the fly.  The default keyboard map is the normal
   US keyboard (yes, I should have used the Finnish one by default, but
   after thinking of all the problems that would have resulted in I
   forgot about that idea).  The loadkeys code can be found in the
   "keytables.tar.z" archive, which also contains keymaps for most
   normal keyboard types.  To create a custom keyboard table is very
   easy - just take a 5 minute look at the existing map files (they
   resemble the ones used by xmodmap, so if you are familiar with
   those..)

   The loadable keymaps were mostly implemented by Risto Kankkunen.

There are a lot of other internal kernel changes, but they should be
mostly transparent, and noticeable only indirectly due to new features
or (hopefully) better/faster/whatever operation.  These include:

 - the SysV IPC patches are in by default: Krishna Balasubramanian.
   If you need these, you know what it's about (notably, dosemu 0.49
   wants them).
 - inode handling is updated: inodes and files are now dynamically
   allocated within the kernel, and use a hash table for faster lookup
   (along with a NFU algorithm for the inode cache).  Steven Tweedie.
 - Updated FPU emulation: mostly exception handling changes, making the
   emulator handle most exceptions the same way a 486 does.  The
   emulator is written by Bill Metzenthen.
 - a few ext2-fs updates by Remy Card and Steven Tweedie.
 - support for the 'fsync()' function (Steven Tweedie)
 - various (minor) SCSI patches to catch some error conditions, add
   support for VLB adaptec controllers without DMA and so on (different
   people).
 - other changes - I forget.

In addition to patches sent in by others, I've naturally made my own
changes (often *to* the patches sent in by others :-).  Among other
things, the pl10 buffer cache code now also tries to share pages with
executables, resulting in better cacheing especially of binaries (giving
noticeable improvements in kernel recompilation speed on some machines).
Also, I've changed a lot of low-level things around to help the iBCS2
project: this includes things like internal segment handling and the
signal stack (which now looks the same as on SysV i386 unixes).  All in
all, pl10 has a disturbing amount of new code, but will hopefully work
well despite (due to?) the number of changes.

The new networking code in particular will change the network setup a
lot - it now looks more standard, but if you were used to the old way of
doing things..  On the other hand, most people actively using the
networking features have hopefully gotten warnings about this on the NET
channel for the last few weeks.  Also, the networking code still isn't
perfect: Fred is still working on it, but it seems to have reached a
reasonably stable platform on which it will be easier to build.  Look
out for the new-and-improved networking manual, hopefully out soon(?).

Standard request: please try it all out, give it a real shakedown, and
send comments/bug-reports to the appropriate place (I'm always
appropriate, but you may want to send the report to the mailing lists
and/or the newsgroup as well).  I apologize for the lateness of the
release (forcing hlu to make interim gcc releases that relied on
nonstandard kernels etc), and the changes are somewhat bigger than I'd
prefer, so the more testerts that try it out, the faster we can try to
fix any possible problems.  The new kernel has gone through various
stages of ALPHA-diffs and some late ALPHA-pl10's, so there shouldn't be
any major surprises, but alpha releases tend not to get even close to
the coverage a real release gets...

                    Linus
parent 3579bc6f
#! /bin/sh
# Configure This script is used to configure the Linux kernel.
#
# Usage: Configure [-pro]
#
# Version; @(#)Configure 1.3 04/05/93
#
# Author: Linus Torvalds, <torvalds@helsinki.fi>
#
# This script is used to configure the linux kernel.
# It's a fast hack - feel free to do something better.
CONFIG=.config~
CONFIG_H=include/linux/autoconf.h
> config.new
echo "#" > $CONFIG
echo "# Automatically generated make config: don't edit" >> $CONFIG
echo "#" >> $CONFIG
echo "/*" > $CONFIG_H
echo " * Automatically generated C config: don't edit" >> $CONFIG_H
echo " */" >> $CONFIG_H
# Set variables to initial state.
OPTS=""
CONFIG=.config~
CONFIG_H=include/linux/autoconf.h
next="y"
old="y"
next="y"
old="y"
# Check commandline arguments.
>config.new
while [ $# != 0 ]
do
case $1 in
-pro) OPTS="UTS_SYSNAME \"LINUX/Pro\""
;;
*) echo "Usage: Configure [-pro]"
exit 1
;;
esac
shift
done
echo "#" > $CONFIG
echo "# Automatically generated make config: don't edit" >> $CONFIG
echo "#" >> $CONFIG
while read i
do
echo "/*" > $CONFIG_H
echo " * Automatically generated C config: don't edit" >> $CONFIG_H
echo " */" >> $CONFIG_H
# First of all, emit the "special" features to <linux/autoconf.h>.
if [ "${OPTS}" ]
then
echo "#define ${OPTS}" >> $CONFIG_H
fi
# Read our standard input (which is the CONFIG.IN file).
while read i
do
echo $i >> config.new
echo >> $CONFIG
echo >> $CONFIG_H
echo
echo >> $CONFIG
echo >> $CONFIG_H
echo
echo "#" >> $CONFIG
echo "/*" >> $CONFIG_H
echo "**"
......@@ -69,15 +97,14 @@ do
then
next="n"
fi
done
mv config.new config.in
done
mv config.new config.in
echo
echo "The linux kernel is now hopefully configured for your setup."
echo "Check the top-level Makefile for additional configuration,"
echo "and do a 'make dep ; make clean' if you want to be sure all"
echo "the files are correctly re-made"
echo
echo
echo "The linux kernel is now hopefully configured for your setup."
echo "Check the top-level Makefile for additional configuration,"
echo "and do a 'make dep ; make clean' if you want to be sure all"
echo "the files are correctly re-made"
echo
exit 0
exit 0
all: Version Image
all: Version zImage
.EXPORT_ALL_VARIABLES:
......@@ -18,6 +18,13 @@ else
CONFIGURATION = config
endif
#
# This probably won't help at all...
#
ifndef CONFIG_CLUEFUL
CONFIGURATION = config
endif
ifdef CONFIGURATION
CONFIGURE = dummy
endif
......@@ -30,37 +37,6 @@ endif
ROOT_DEV = CURRENT
#
# uncomment the correct keyboard:
#
# The value of KBDFLAGS should be or'ed together from the following
# bits, depending on which features you want enabled.
#
# The least significant bits control if the following keys are "dead".
# The key is dead by default if the bit is on.
# 0x01 - backquote (`)
# 0x02 - accent acute
# 0x04 - circumflex (^)
# 0x08 - tilde (~)
# 0x10 - dieresis (umlaut)
KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
# KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_US -DKBDFLAGS=0
# KEYBOARD = -DKBD_GR -DKBDFLAGS=0
# KEYBOARD = -DKBD_GR_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_FR -DKBDFLAGS=0
# KEYBOARD = -DKBD_FR_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_UK -DKBDFLAGS=0
# KEYBOARD = -DKBD_DK -DKBDFLAGS=0
# KEYBOARD = -DKBD_DK_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_DVORAK -DKBDFLAGS=0
# KEYBOARD = -DKBD_SG -DKBDFLAGS=0
# KEYBOARD = -DKBD_SG_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_SF -DKBDFLAGS=0
# KEYBOARD = -DKBD_SF_LATIN1 -DKBDFLAGS=0x1F
# KEYBOARD = -DKBD_NO -DKBDFLAGS=0
#
# If you want to preset the SVGA mode, uncomment the next line and
# set SVGA_MODE to whatever number you want.
......@@ -70,6 +46,9 @@ KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
SVGA_MODE= -DSVGA_MODE=3
# Special options.
#OPTS = -pro
#
# standard CFLAGS
#
......@@ -93,19 +72,20 @@ LD86 =ld86 -0
AS =as
LD =ld
HOSTCC =gcc
CC =gcc -DKERNEL
CC =gcc -D__KERNEL__
MAKE =make
CPP =$(CC) -E
AR =ar
STRIP =strip
ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o net/net.o
ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o net/net.o ipc/ipc.o
FILESYSTEMS =fs/filesystems.a
DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \
kernel/blk_drv/scsi/scsi.a kernel/chr_drv/sound/sound.a
kernel/blk_drv/scsi/scsi.a kernel/chr_drv/sound/sound.a \
ibcs/ibcs.o
MATH =kernel/FPU-emu/math.a
LIBS =lib/lib.a
SUBDIRS =kernel mm fs net lib
SUBDIRS =kernel mm fs net ipc ibcs lib
KERNELHDRS =/usr/src/linux/include
......@@ -125,7 +105,7 @@ lilo: $(CONFIGURE) Image
/etc/lilo/install
config:
sh Configure < config.in
sh Configure $(OPTS) < config.in
mv .config~ .config
$(MAKE) soundconf
......@@ -139,11 +119,12 @@ tools/./version.h: tools/version.h
tools/version.h: $(CONFIGURE) Makefile
@./makever.sh
@echo \#define UTS_RELEASE \"0.99.pl9-`cat .version`\" > tools/version.h
@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
@echo \#define UTS_RELEASE \"0.99.10\" > tools/version.h
@echo \#define UTS_VERSION \"\#`cat .version` `date`\" >> tools/version.h
@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
@echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h
@echo \#define LINUX_COMPILE_DOMAIN \"`domainname`\" >> tools/version.h
Image: $(CONFIGURE) boot/bootsect boot/setup tools/system tools/build
tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) > Image
......@@ -200,6 +181,7 @@ zdisk: zImage
dd bs=8192 if=zImage of=/dev/fd0
zlilo: $(CONFIGURE) zImage
if [ -f /vmlinuz ]; then mv /vmlinuz /vmlinuz.old; fi
cat zImage > /vmlinuz
/etc/lilo/install
......@@ -249,7 +231,7 @@ depend dep:
ifdef CONFIGURATION
..$(CONFIGURATION):
@echo
@echo "You have no" .$(CONFIGURATION) ": running 'make" $(CONFIGURATION)"'"
@echo "You have a bad or nonexistent" .$(CONFIGURATION) ": running 'make" $(CONFIGURATION)"'"
@echo
$(MAKE) $(CONFIGURATION)
@echo
......
[ NOTE! As of linux-0.97.pl5, the linux kernel include-files have
finally been totally integrated with the normal headers. That means
no more "-nostdinc -I$(KERNELHDRS)" in the Makefiles etc, but it
also means that you /have/ to have the correct /usr/include/linux
and ../asm symlinks. See "Basic configuration 2" ]
VERY QUICK AND DIRTY README
by Lars Wirzenius
DON'T PANIC
This is the README for the Linux kernel sources. It tells a few small
things about kernel configuration and other things that can perhaps be
useful if you want to compile the kernel from scratch. It leaves out a
lot as well, probably because the person who wrote it doesn't understand
very much about operating systems. Linus did his best to help, but all
problems this causes are my fault.
LOT as well, but it shouldn't really be that hard to compile the kernel.
I hope.
In order to compile this version of the kernel you need GCC 2.2.2 or
newer. Some makefile targets require special commands which may not be
available on all machines (see below). Normal utilities like ls etc are
not explicitly listed, they are assumed to be available on all systems.
In order to compile this version of the kernel you need GCC 2.3.3 or
newer (older compiler versions may work, but I haven't tested it). Some
makefile targets require special commands which may not be available on
all machines (see below). Normal utilities like ls etc are not
explicitly listed, they are assumed to be available on all systems.
Kernel sources are usually kept in /usr/src/linux. If you have them
elsewhere, you will have to change path names in a few places.
Filenames that aren't absolute are supposed to be relative to the
toplevel kernel source directory.
Generally, if you aren't sure of what you are doing, make your life
easier by using the standard /usr/src/linux source tree. Filenames that
aren't absolute are supposed to be relative to the toplevel kernel
source directory.
* Basic configuration
1. Edit Makefile: Check the definitions of macros ROOTDEV, KEYBOARD,
RAMDISK and SVGA_MODE before you run make. They are explained in the
Makefile.
* SETUP
1. make sure /usr/include/asm and /usr/include/linux are symlinks to
the linux source tree include files. The output of
# ls -ld /usr/include/asm /usr/include/linux
2. Create the symlinks:
should look like this:
ln -fs /usr/src/linux/include/linux /usr/include/linux
ln -fs /usr/src/linux/include/asm /usr/include/asm
lrwxrwxrwx 1 root root 26 Apr 19 20:03 /usr/include/asm -> /usr/src/linux/include/asm
lrwxrwxrwx 1 root root 28 Apr 19 20:03 /usr/include/linux -> /usr/src/linux/include/linux
This is required so that the linux sources will correctly find their
header files - it is also used by the normal user-level header files to
get some system-specific information.
If it doesn't, create the appropriate symlinks with
[ Linus' note2: This is automatically done by the gcc-2.2.2d and newer
installation script, so if you have the new compiler, you should
already have these links ]
# cd /usr/include
# rm -rf linux asm
# ln -s /usr/src/linux/include/linux .
# ln -s /usr/src/linux/include/asm .
Also, if you are installing a new version of linux over the sources of
an old one (or have user kernel patches to get a new version), you
should probably do a "make mrproper" to remove any traces of old object
files or incorrect dependency information.
2. Edit Makefile: Check the definitions of macros ROOTDEV, RAMDISK and
SVGA_MODE before you run make. They are explained in the Makefile.
3. Run "make config" in /usr/src/linux, and answer the questions that
the config script asks you. It should hopefully set up most of the rest
......@@ -51,32 +55,37 @@ of the flags for your system.
4. Run "make dep" to set up all the dependencies correctly. The
default dependencies may not fit your system due to different compiler
versions or similar.
versions or similar. Also, you may wish to run "make clean" first to
make sure you don't have any old object files that mess things up if you
have changed or patched your kernel.
* Running make
[ Linus' note3: if you have problems with make not working correctly,
get a new copy of GNU make. The linux kernel makefiles are written
for GNU make and will not work for anything else ]
Unless you know what you're doing, don't ever run the makefiles in
subdirectories by hand. There is a bit of interaction between the
various makefiles, e.g. in the form of inherited macros and the like.
various makefiles, e.g. in the form of inherited macros and the like.
The following targets all apply for the makefile at the root of the
kernel source tree.
kernel source tree.
"make" or "make all" compiles everything.
"make" or "make all" compiles the kernel and makes a compressed kernel
image called "zImage". It also bumps compilation numbers to help you
keep track of different kernels.
"make Image" is like "make all", but it doesn't bump the number in
.version, which tells how many times this version has been compiled
(helps you differentiate between different configurations etc).
(helps you differentiate between different configurations etc).
"make disk" is like "make Image", but it additionally writes out a copy
of the boot image to a floppy in your first floppy drive (/dev/fd0;
change the filename if you want a different floppy). You need to have
a formatted, overwritable floppy in that drive when it is time to do the
copy. This requires dd.
change the filename if you want a different floppy). You need to have a
formatted, overwritable floppy in that drive when it is time to do the
copy. This requires dd.
"make zdisk" and "make zImage" are the same as their 'z-less'
counterparts, but create a compressed kernel that autodecompresses on
bootup. This is the preferred mode of operation, as it both allows for
a larger kernel and makes the images smaller.
"make dep" updates all dependencies. This requires sed. It modifies
the makefiles directly (the end of them, starting at the ###Dependencies
......@@ -84,7 +93,7 @@ the makefiles directly (the end of them, starting at the ###Dependencies
may not compile cleanly.
"make clean" will remove all object files and other files created by the
compilation. This requires basename.
compilation. This requires basename.
You may wish to redirect compiler error messages to a file so that you
can review them later and to ease problem fixing. You can do this with
......@@ -94,6 +103,6 @@ Bash with:
The tee part is so that you can check what is going on while the
compilation runs. If you have GNU emacs and use M-x compile you don't
need this, of course.
need this, of course.
Lars Wirzenius
Lars Wirzenius & Linus Torvalds
/*
* linux/boot/head.s
* linux/boot/head.S
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
/*
* head.s contains the 32-bit startup code.
*
* NOTE!!! Startup happens at absolute address 0x00000000, which is also where
* the page directory will exist. The startup code will be overwritten by
* the page directory.
* head.S contains the 32-bit startup code.
*/
.text
.globl _idt,_gdt,
.globl _swapper_pg_dir,_pg0
......@@ -20,13 +17,19 @@
.globl _tmp_floppy_area,_floppy_track_buffer
#include <linux/tasks.h>
#include <linux/segment.h>
#define CL_MAGIC_ADDR 0x90020
#define CL_MAGIC 0xA33F
#define CL_BASE_ADDR 0x90000
#define CL_OFFSET 0x90022
/*
* swapper_pg_dir is the main page directory, address 0x00001000
*/
startup_32:
cld
movl $0x10,%eax
movl $KERNEL_DS,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
......@@ -45,6 +48,40 @@ startup_32:
*/
pushl $0
popfl
/*
* Copy bootup parameters out of the way. First 2kB of
* _empty_zero_page is for boot parameters, second 2kB
* is for the command line.
*/
movl $0x90000,%esi
movl $_empty_zero_page,%edi
movl $512,%ecx
cld
rep
movsl
xorl %eax,%eax
movl $512,%ecx
rep
stosl
cmpw $CL_MAGIC,CL_MAGIC_ADDR
jne 1f
movl $_empty_zero_page+2048,%edi
movzwl CL_OFFSET,%esi
addl $CL_BASE_ADDR,%esi
movl $2048,%ecx
rep
movsb
1:
/*
* Clear BSS
*/
xorl %eax,%eax
movl $__edata,%edi
movl $__end,%ecx
subl %edi,%ecx
cld
rep
stosb
/* check if it is 486 or 386. */
/*
* XXX - this does a lot of unnecessary setup. Alignment checks don't
......@@ -90,8 +127,8 @@ startup_32:
call setup_paging
lgdt gdt_descr
lidt idt_descr
ljmp $0x08,$1f
1: movl $0x10,%eax # reload all the segment registers
ljmp $KERNEL_CS,$1f
1: movl $KERNEL_DS,%eax # reload all the segment registers
mov %ax,%ds # after changing gdt.
mov %ax,%es
mov %ax,%fs
......@@ -132,13 +169,12 @@ check_x87:
* idt - that can be done only after paging has been enabled
* and the kernel moved to 0xC0000000. Interrupts
* are enabled elsewhere, when we can be relatively
* sure everything is ok. This routine will be over-
* written by the page tables.
* sure everything is ok.
*/
setup_idt:
lea ignore_int,%edx
movl $0x00080000,%eax
movw %dx,%ax /* selector = 0x0008 = cs */
movl $(KERNEL_CS << 16),%eax
movw %dx,%ax /* selector = 0x0010 = cs */
movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
lea _idt,%edi
......@@ -238,7 +274,7 @@ ignore_int:
push %ds
push %es
push %fs
movl $0x10,%eax
movl $KERNEL_DS,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
......@@ -266,13 +302,10 @@ idt_descr:
_idt:
.fill 256,8,0 # idt is uninitialized
/*
* The real GDT is also 256 entries long - no real reason
*/
.align 4
.word 0
gdt_descr:
.word (4+2*NR_TASKS)*8-1
.word (8+2*NR_TASKS)*8-1
.long 0xc0000000+_gdt
/*
......@@ -282,7 +315,11 @@ gdt_descr:
.align 4
_gdt:
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0xc0c39a000000ffff /* 1GB at 0xC0000000 */
.quad 0xc0c392000000ffff /* 1GB */
.quad 0x0000000000000000 /* TEMPORARY - don't use */
.quad 0x0000000000000000 /* not used */
.quad 0xc0c39a000000ffff /* 0x10 kernel 1GB code at 0xC0000000 */
.quad 0xc0c392000000ffff /* 0x18 kernel 1GB data at 0xC0000000 */
.quad 0x00cbfa000000ffff /* 0x23 user 3GB code at 0x00000000 */
.quad 0x00cbf2000000ffff /* 0x2b user 3GB data at 0x00000000 */
.quad 0x0000000000000000 /* not used */
.quad 0x0000000000000000 /* not used */
.fill 2*NR_TASKS,8,0 /* space for LDT's and TSS's etc */
......@@ -20,6 +20,7 @@
! NOTE! These had better be the same as in bootsect.s!
#include <linux/config.h>
#include <linux/segment.h>
#ifndef SVGA_MODE
#define SVGA_MODE ASK_VGA
......@@ -247,7 +248,7 @@ end_move:
lmsw ax ! This is it!
jmp flush_instr
flush_instr:
jmpi 0,8 ! jmp offset 0 of segment 8 (cs)
jmpi 0,KERNEL_CS ! jmp offset 0 of segment 0x10 (cs)
! This routine checks that the keyboard command queue is empty
! (after emptying the output buffers)
......@@ -765,6 +766,8 @@ beep: mov al,#0x07
gdt:
.word 0,0,0,0 ! dummy
.word 0,0,0,0 ! unused
.word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000 ! base address=0
.word 0x9A00 ! code read/exec
......
......@@ -6,12 +6,14 @@ Normal harddisk support
CONFIG_BLK_DEV_HD y/n y
XT harddisk support
CONFIG_BLK_DEV_XD y/n n
TCP/IP
CONFIG_TCPIP y/n y
TCP/IP Networking
CONFIG_INET y/n y
Kernel profiling support
CONFIG_PROFILE y/n n
Limit memory to low 16MB
CONFIG_MAX_16M y/n n
System V IPC
CONFIG_SYSVIPC y/n y
Use -m486 flag for 486-specific optimizations
CONFIG_M486 y/n y
:
......@@ -46,8 +48,6 @@ CONFIG_SCSI_7000FASST y/n n
.
Filesystems
.
Mount root initially readonly
CONFIG_ROOT_RDONLY y/n n
Standard (minix) fs support
CONFIG_MINIX_FS y/n y
Extended fs support
......@@ -69,12 +69,6 @@ Various character device drivers..
.
Keyboard meta-key sends ESC-prefix
CONFIG_KBD_META y/n y
Autoconfigure serial IRQ lines at bootup
CONFIG_AUTO_IRQ y/n n
AST Fourport serial driver support
CONFIG_AST_FOURPORT y/n n
Accent Async 4 serial support
CONFIG_ACCENT_ASYNC y/n n
Logitech busmouse support
CONFIG_BUSMOUSE y/n n
PS/2 mouse (aka 'auxiliary device') support
......@@ -85,3 +79,8 @@ ATIXL busmouse support
CONFIG_ATIXL_BUSMOUSE y/n n
Soundcard support (distributed separately)
CONFIG_SOUND y/n n
.
Final check to see if you are awake
.
Have you edited the main Makefile for root device etc
CONFIG_CLUEFUL y/n n
......@@ -176,3 +176,8 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
filp->f_reada = 1;
return read;
}
int block_fsync(struct inode *inode, struct file *filp)
{
return fsync_dev (inode->i_rdev);
}
This diff is collapsed.
......@@ -29,11 +29,13 @@
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/segment.h>
#include <asm/segment.h>
extern int sys_exit(int exit_code);
extern int sys_close(int fd);
extern void shm_exit (void);
/*
* MAX_ARG_PAGES defines the number of pages allocated for arguments
......@@ -80,8 +82,8 @@ int core_dump(long signr, struct pt_regs * regs)
if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE)
return 0;
__asm__("mov %%fs,%0":"=r" (fs));
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
if (open_namei("core",O_CREAT | O_WRONLY | O_TRUNC,0600,&inode,NULL)) {
__asm__("mov %w0,%%fs"::"r" (KERNEL_DS));
if (open_namei("core",O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) {
inode = NULL;
goto end_coredump;
}
......@@ -139,7 +141,7 @@ int core_dump(long signr, struct pt_regs * regs)
convert it into standard 387 format first.. */
dump.u_fpvalid = 0;
}
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
__asm__("mov %w0,%%fs"::"r" (KERNEL_DS));
/* struct user */
DUMP_WRITE(&dump,sizeof(dump));
/* name of the executable */
......@@ -147,7 +149,7 @@ int core_dump(long signr, struct pt_regs * regs)
/* Now dump all of the user data. Include malloced stuff as well */
DUMP_SEEK(PAGE_SIZE);
/* now we start writing out the user space info */
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x17));
__asm__("mov %w0,%%fs"::"r" (USER_DS));
/* Dump the data area */
if (dump.u_dsize != 0) {
dump_start = dump.u_tsize << 12;
......@@ -161,13 +163,13 @@ int core_dump(long signr, struct pt_regs * regs)
DUMP_WRITE(dump_start,dump_size);
};
/* Finally dump the task struct. Not be used by gdb, but could be useful */
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
__asm__("mov %w0,%%fs"::"r" (KERNEL_DS));
DUMP_WRITE(current,sizeof(*current));
close_coredump:
if (file.f_op->release)
file.f_op->release(inode,&file);
end_coredump:
__asm__("mov %0,%%fs"::"r" (fs));
__asm__("mov %w0,%%fs"::"r" (fs));
iput(inode);
return has_dumped;
}
......@@ -187,7 +189,7 @@ int sys_uselib(const char * library)
unsigned long offset;
int error;
if (!library || get_limit(0x17) != TASK_SIZE)
if (!library || get_limit(USER_DS) != TASK_SIZE)
return -EINVAL;
if ((libnum >= MAX_SHARED_LIBS) || (libnum < 0))
return -EINVAL;
......@@ -361,12 +363,6 @@ static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
data_limit = TASK_SIZE;
code_base = data_base = 0;
current->start_code = code_base;
set_base(current->ldt[1],code_base);
set_limit(current->ldt[1],code_limit);
set_base(current->ldt[2],data_base);
set_limit(current->ldt[2],data_limit);
/* make sure fs points to the NEW data segment */
__asm__("pushl $0x17\n\tpop %%fs"::);
data_base += data_limit;
for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
data_base -= PAGE_SIZE;
......@@ -435,7 +431,7 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
int ch;
if ((0xffff & eip[1]) != 0x000f)
if ((0xffff & eip[1]) != USER_CS)
panic("VFS: execve called from supervisor mode");
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
page[i]=0;
......@@ -591,6 +587,8 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
if (i < 15)
current->comm[i++] = ch;
current->comm[i] = '\0';
if (current->shm)
shm_exit();
if (current->executable) {
iput(current->executable);
current->executable = NULL;
......@@ -604,7 +602,6 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
!permission(inode,MAY_READ))
current->dumpable = 0;
current->numlibraries = 0;
current->signal = 0;
for (i=0 ; i<32 ; i++) {
current->sigaction[i].sa_mask = 0;
current->sigaction[i].sa_flags = 0;
......
......@@ -15,7 +15,7 @@
$(AS) -o $*.o $<
OBJS= freelists.o truncate.o namei.o inode.o \
file.o dir.o symlink.o
file.o dir.o symlink.o fsync.o
ext.o: $(OBJS)
$(LD) -r -o ext.o $(OBJS)
......
......@@ -37,7 +37,7 @@ static struct file_operations ext_dir_operations = {
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* fsync */
file_fsync /* fsync */
};
/*
......
......@@ -48,7 +48,7 @@ static struct file_operations ext_file_operations = {
NULL, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
NULL /* fsync */
ext_sync_file /* fsync */
};
struct inode_operations ext_file_inode_operations = {
......
......@@ -289,6 +289,7 @@ printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = NULL;
inode->i_blocks = inode->i_blksize = 0;
insert_inode_hash(inode);
#ifdef EXTFS_DEBUG
printk("ext_new_inode : allocating inode %d\n", inode->i_ino);
#endif
......
/*
* linux/fs/ext/fsync.c
*
* Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
* from
* Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
* from
* linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds
*
* extfs fsync primitive
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/locks.h>
#include <linux/fs.h>
#include <linux/ext_fs.h>
#define blocksize BLOCK_SIZE
#define addr_per_block 256
static int sync_block (struct inode * inode, unsigned long * block, int wait)
{
struct buffer_head * bh;
int tmp;
if (!*block)
return 0;
tmp = *block;
bh = get_hash_table(inode->i_dev, *block, blocksize);
if (!bh)
return 0;
if (*block != tmp) {
brelse (bh);
return 1;
}
if (wait && bh->b_req && !bh->b_uptodate) {
brelse(bh);
return -1;
}
if (wait || !bh->b_uptodate || !bh->b_dirt)
{
brelse(bh);
return 0;
}
ll_rw_block(WRITE, 1, &bh);
bh->b_count--;
return 0;
}
static int sync_iblock (struct inode * inode, unsigned long * iblock,
struct buffer_head **bh, int wait)
{
int rc, tmp;
*bh = NULL;
tmp = *iblock;
if (!tmp)
return 0;
rc = sync_block (inode, iblock, wait);
if (rc)
return rc;
*bh = bread(inode->i_dev, tmp, blocksize);
if (tmp != *iblock) {
brelse(*bh);
*bh = NULL;
return 1;
}
if (!*bh)
return -1;
return 0;
}
static int sync_direct(struct inode *inode, int wait)
{
int i;
int rc, err = 0;
for (i = 0; i < 9; i++) {
rc = sync_block (inode, inode->u.ext_i.i_data + i, wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
return err;
}
static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
{
int i;
struct buffer_head * ind_bh;
int rc, err = 0;
rc = sync_iblock (inode, iblock, &ind_bh, wait);
if (rc || !ind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_block (inode,
((unsigned long *) ind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(ind_bh);
return err;
}
static int sync_dindirect(struct inode *inode, unsigned long *diblock,
int wait)
{
int i;
struct buffer_head * dind_bh;
int rc, err = 0;
rc = sync_iblock (inode, diblock, &dind_bh, wait);
if (rc || !inode)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_indirect (inode,
((unsigned long *) dind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(dind_bh);
return err;
}
static int sync_tindirect(struct inode *inode, unsigned long *tiblock,
int wait)
{
int i;
struct buffer_head * tind_bh;
int rc, err = 0;
rc = sync_iblock (inode, tiblock, &tind_bh, wait);
if (rc || !tind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_dindirect (inode,
((unsigned long *) tind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(tind_bh);
return err;
}
int ext_sync_file(struct inode * inode, struct file *file)
{
int wait, err = 0;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return -EINVAL;
for (wait=0; wait<=1; wait++)
{
err |= sync_direct(inode, wait);
err |= sync_indirect(inode, inode->u.ext_i.i_data+9, wait);
err |= sync_dindirect(inode, inode->u.ext_i.i_data+10, wait);
err |= sync_tindirect(inode, inode->u.ext_i.i_data+11, wait);
}
err |= ext_sync_inode (inode);
return (err < 0) ? -EIO : 0;
}
......@@ -50,7 +50,8 @@ static struct super_operations ext_sops = {
ext_put_inode,
ext_put_super,
ext_write_super,
ext_statfs
ext_statfs,
NULL
};
struct super_block *ext_read_super(struct super_block *s,void *data,
......@@ -383,7 +384,7 @@ void ext_read_inode(struct inode * inode)
init_fifo(inode);
}
void ext_write_inode(struct inode * inode)
static struct buffer_head * ext_update_inode(struct inode * inode)
{
struct buffer_head * bh;
struct ext_inode * raw_inode;
......@@ -406,5 +407,36 @@ void ext_write_inode(struct inode * inode)
raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
bh->b_dirt=1;
inode->i_dirt=0;
return bh;
}
void ext_write_inode(struct inode * inode)
{
struct buffer_head *bh;
bh = ext_update_inode (inode);
brelse(bh);
}
int ext_sync_inode (struct inode *inode)
{
int err = 0;
struct buffer_head *bh;
bh = ext_update_inode(inode);
if (bh && bh->b_dirt)
{
ll_rw_block(WRITE, 1, &bh);
wait_on_buffer(bh);
if (bh->b_req && !bh->b_uptodate)
{
printk ("IO error syncing ext inode [%04x:%08x]\n",
inode->i_dev, inode->i_ino);
err = -1;
}
}
else if (!bh)
err = -1;
brelse (bh);
return err;
}
......@@ -14,7 +14,7 @@
.s.o:
$(AS) -o $*.o $<
OBJS= acl.o balloc.o bitmap.o dcache.o dir.o file.o ialloc.o inode.o \
OBJS= acl.o balloc.o bitmap.o dcache.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o symlink.o truncate.o
ext2.o: $(OBJS)
......
......@@ -38,7 +38,7 @@
:"a" (0), "c" (size/4), "D" ((long) (addr)) \
:"cx", "di")
static inline int find_first_zero_bit (unsigned *addr, unsigned size)
static inline int find_first_zero_bit (unsigned long * addr, unsigned size)
{
int res;
if (!size)
......@@ -63,9 +63,10 @@ static inline int find_first_zero_bit (unsigned *addr, unsigned size)
return res;
}
static inline int find_next_zero_bit (unsigned * addr, int size, int offset)
static inline int find_next_zero_bit (unsigned long * addr, int size,
int offset)
{
unsigned *p = ((unsigned *) addr) + (offset >> 5);
unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
int set = 0, bit = offset & 31, res;
if (bit) {
......
......@@ -191,8 +191,6 @@ void ext2_dcache_invalidate (unsigned short dev)
/*
* Lookup a directory entry in the cache
*
* Note: the name is in the caller's address space
*/
unsigned long ext2_dcache_lookup (unsigned short dev, unsigned long dir,
const char *name, int len)
......@@ -243,8 +241,6 @@ unsigned long ext2_dcache_lookup (unsigned short dev, unsigned long dir,
*
* This function is called by ext2_lookup(), ext2_readdir()
* and the functions which create directory entries
*
* Note: the name is in the kernel address space
*/
void ext2_dcache_add (unsigned short dev, unsigned long dir, const char *name,
int len, int ino)
......@@ -305,8 +301,6 @@ void ext2_dcache_add (unsigned short dev, unsigned long dir, const char *name,
* Remove a directory from the cache
*
* This function is called by the functions which remove directory entries
*
* Note: the name is in the kernel address space
*/
void ext2_dcache_remove (unsigned short dev, unsigned long dir,
const char *name, int len)
......
......@@ -41,7 +41,7 @@ static struct file_operations ext2_dir_operations = {
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* fsync */
file_fsync /* fsync */
};
/*
......@@ -77,13 +77,13 @@ int ext2_check_dir_entry (char * function, struct inode * dir,
error_msg = "rec_len % 4 != 0";
else if (de->rec_len < EXT2_DIR_REC_LEN(de->name_len))
error_msg = "rec_len is too small for name_len";
else if (((char *) de - bh->b_data) + de->rec_len >
else if (dir && ((char *) de - bh->b_data) + de->rec_len >
dir->i_sb->s_blocksize)
error_msg = "directory entry accross blocks";
error_msg = "directory entry across blocks";
if (error_msg != NULL) {
printk ("%s: bad directory entry (dev %04x, dir %d): %s\n",
function, dir->i_dev, dir->i_ino, error_msg);
function, dir ? dir->i_dev : 0, dir->i_ino, error_msg);
printk ("offset=%d, inode=%d, rec_len=%d, name_len=%d\n",
offset, de->inode, de->rec_len, de->name_len);
}
......
......@@ -48,7 +48,7 @@ static struct file_operations ext2_file_operations = {
NULL, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
NULL /* fsync */
ext2_sync_file /* fsync */
};
struct inode_operations ext2_file_inode_operations = {
......
/*
* linux/fs/ext2/fsync.c
*
* Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
* from
* Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
* from
* linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds
*
* ext2fs fsync primitive
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/locks.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
static int sync_block (struct inode * inode, unsigned long * block, int wait)
{
struct buffer_head * bh;
int tmp;
if (!*block)
return 0;
tmp = *block;
bh = get_hash_table(inode->i_dev, *block, blocksize);
if (!bh)
return 0;
if (*block != tmp) {
brelse (bh);
return 1;
}
if (wait && bh->b_req && !bh->b_uptodate) {
brelse(bh);
return -1;
}
if (wait || !bh->b_uptodate || !bh->b_dirt)
{
brelse(bh);
return 0;
}
ll_rw_block(WRITE, 1, &bh);
bh->b_count--;
return 0;
}
static int sync_iblock (struct inode * inode, unsigned long * iblock,
struct buffer_head **bh, int wait)
{
int rc, tmp;
*bh = NULL;
tmp = *iblock;
if (!tmp)
return 0;
rc = sync_block (inode, iblock, wait);
if (rc)
return rc;
*bh = bread(inode->i_dev, tmp, blocksize);
if (tmp != *iblock) {
brelse(*bh);
*bh = NULL;
return 1;
}
if (!*bh)
return -1;
return 0;
}
static int sync_direct(struct inode *inode, int wait)
{
int i;
int rc, err = 0;
for (i = 0; i < EXT2_NDIR_BLOCKS; i++) {
rc = sync_block (inode, inode->u.ext2_i.i_data + i, wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
return err;
}
static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
{
int i;
struct buffer_head * ind_bh;
int rc, err = 0;
rc = sync_iblock (inode, iblock, &ind_bh, wait);
if (rc || !ind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_block (inode,
((unsigned long *) ind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(ind_bh);
return err;
}
static int sync_dindirect(struct inode *inode, unsigned long *diblock,
int wait)
{
int i;
struct buffer_head * dind_bh;
int rc, err = 0;
rc = sync_iblock (inode, diblock, &dind_bh, wait);
if (rc || !dind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_indirect (inode,
((unsigned long *) dind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(dind_bh);
return err;
}
static int sync_tindirect(struct inode *inode, unsigned long *tiblock,
int wait)
{
int i;
struct buffer_head * tind_bh;
int rc, err = 0;
rc = sync_iblock (inode, tiblock, &tind_bh, wait);
if (rc || !tind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_dindirect (inode,
((unsigned long *) tind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(tind_bh);
return err;
}
int ext2_sync_file(struct inode * inode, struct file *file)
{
int wait, err = 0;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return -EINVAL;
/* Don't sync fast links! */
if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
goto skip;
for (wait=0; wait<=1; wait++)
{
err |= sync_direct(inode, wait);
err |= sync_indirect(inode,
inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
wait);
err |= sync_dindirect(inode,
inode->u.ext2_i.i_data+EXT2_DIND_BLOCK,
wait);
err |= sync_tindirect(inode,
inode->u.ext2_i.i_data+EXT2_TIND_BLOCK,
wait);
}
skip:
err |= ext2_sync_inode (inode);
return (err < 0) ? -EIO : 0;
}
......@@ -32,7 +32,7 @@
#include <asm/bitops.h>
static inline int find_first_zero_bit(unsigned * addr, unsigned size)
static inline int find_first_zero_bit (unsigned long * addr, unsigned size)
{
int res;
if (!size)
......@@ -358,7 +358,8 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
if (!gdp) {
for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
tmp = get_group_desc(sb, j);
if (tmp->bg_free_inodes_count >= avefreei) {
if (tmp->bg_free_inodes_count &&
tmp->bg_free_inodes_count >= avefreei) {
if (!gdp ||
(tmp->bg_free_inodes_count >
gdp->bg_free_inodes_count)) {
......@@ -405,6 +406,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
if (!gdp) {
unlock_super (sb);
iput(inode);
return NULL;
}
bitmap_nr = load_inode_bitmap (sb, i);
......@@ -456,6 +458,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
inode->u.ext2_i.i_dtime = 0;
inode->u.ext2_i.i_block_group = i;
inode->i_op = NULL;
insert_inode_hash(inode);
inc_inode_version (inode, gdp, mode);
#ifdef EXT2FS_DEBUG
printk ("ext2_new_inode : allocating inode %d\n", inode->i_ino);
......
......@@ -26,7 +26,8 @@
void ext2_put_inode (struct inode * inode)
{
if (inode->i_nlink || inode->i_ino == EXT2_ACL_INO)
if (inode->i_nlink || inode->i_ino == EXT2_ACL_IDX_INO ||
inode->i_ino == EXT2_ACL_DATA_INO)
return;
inode->i_size = 0;
if (inode->i_blocks)
......@@ -67,7 +68,8 @@ static struct super_operations ext2_sops = {
ext2_put_inode,
ext2_put_super,
ext2_write_super,
ext2_statfs
ext2_statfs,
ext2_remount
};
#ifdef EXT2FS_PRE_02B_COMPAT
......@@ -217,6 +219,13 @@ struct super_block * ext2_read_super (struct super_block * s, void * data,
bh_count = (s->u.ext2_sb.s_groups_count +
EXT2_DESC_PER_BLOCK(s) - 1) /
EXT2_DESC_PER_BLOCK(s);
if (bh_count >= EXT2_MAX_GROUP_DESC) {
s->s_dev = 0;
unlock_super (s);
brelse (bh);
printk ("EXT2-fs: Too big file system\n");
return NULL;
}
for (i = 0; i < bh_count; i++) {
s->u.ext2_sb.s_group_desc[i] = bread (dev, i + 2, s->s_blocksize);
if (!s->u.ext2_sb.s_group_desc[i]) {
......@@ -263,9 +272,9 @@ struct super_block * ext2_read_super (struct super_block * s, void * data,
s->s_dirt = 1;
}
#endif
printk ("[EXT II FS %s, bs=%d, fs=%d, gc=%d, bpg=%d, ipg=%d]\n",
EXT2FS_VERSION, s->s_blocksize, s->u.ext2_sb.s_frag_size,
s->u.ext2_sb.s_groups_count,
printk ("[EXT II FS %s, %s, bs=%d, fs=%d, gc=%d, bpg=%d, ipg=%d]\n",
EXT2FS_VERSION, EXT2FS_DATE, s->s_blocksize,
s->u.ext2_sb.s_frag_size, s->u.ext2_sb.s_groups_count,
EXT2_BLOCKS_PER_GROUP(s), EXT2_INODES_PER_GROUP(s));
return s;
}
......@@ -283,56 +292,91 @@ struct super_block * ext2_read_super (struct super_block * s, void * data,
* Note that this function also writes backups of the super block and
* of the group descriptors in each group.
*/
void ext2_write_super (struct super_block * sb)
static void ext2_commit_super (struct super_block *sb,
struct ext2_super_block *es)
{
struct ext2_super_block * es;
struct buffer_head * bh;
unsigned long block;
unsigned long bh_count;
int i, j;
if ((sb->s_flags & MS_RDONLY) == 0) {
es = (struct ext2_super_block *) sb->u.ext2_sb.s_sbh->b_data;
es->s_wtime = CURRENT_TIME;
sb->u.ext2_sb.s_sbh->b_dirt = 1;
bh_count = (sb->u.ext2_sb.s_groups_count +
EXT2_DESC_PER_BLOCK(sb) - 1) /
EXT2_DESC_PER_BLOCK(sb);
for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
block = sb->u.ext2_sb.s_first_data_block +
i * sb->u.ext2_sb.s_blocks_per_group;
if (!(bh = bread (sb->s_dev, block, BLOCK_SIZE)))
printk ("ext2_commit_super: Unable to read backup super block for group %d\n", i);
else {
#ifdef EXT2FS_DEBUG
printk ("ext2_write_super: setting valid to 0\n");
#endif
es->s_valid = 0;
es->s_wtime = CURRENT_TIME;
sb->u.ext2_sb.s_sbh->b_dirt = 1;
bh_count = (sb->u.ext2_sb.s_groups_count +
EXT2_DESC_PER_BLOCK(sb) - 1) /
EXT2_DESC_PER_BLOCK(sb);
for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
block = sb->u.ext2_sb.s_first_data_block +
i * sb->u.ext2_sb.s_blocks_per_group;
if (!(bh = bread (sb->s_dev, block, BLOCK_SIZE)))
printk ("ext2_write_super: Unable to read backup super block for group %d\n", i);
else {
printk ("ext2_commit_super: writing super block backup in group %d at block %d\n", i, block);
#endif
memcpy (bh->b_data, es, BLOCK_SIZE);
bh ->b_dirt = 1;
brelse (bh);
}
for (j = 0; j < bh_count; j++) {
block ++;
#ifdef EXT2FS_DEBUG
printk ("ext2_write_super: writing super block backup in group %d at block %d\n", i, block);
printk ("ext2_commit_super: writing descriptors (block %d) backup in group %d at block %d\n", j, i, block);
#endif
memcpy (bh->b_data, es, BLOCK_SIZE);
if (!(bh = bread (sb->s_dev, block, sb->s_blocksize)))
printk ("ext2_commit_super: Unable to read backup descriptor for group %d\n", i);
else {
memcpy (bh->b_data, sb->u.ext2_sb.s_group_desc[j]->b_data, sb->s_blocksize);
bh ->b_dirt = 1;
brelse (bh);
}
for (j = 0; j < bh_count; j++) {
block ++;
#ifdef EXT2FS_DEBUG
printk ("ext2_write_super: writing descriptors (block %d) backup in group %d at block %d\n", j, i, block);
#endif
if (!(bh = bread (sb->s_dev, block, sb->s_blocksize)))
printk ("ext2_write_super: Unable to read backup descriptor for group %d\n", i);
else {
memcpy (bh->b_data, sb->u.ext2_sb.s_group_desc[j]->b_data, sb->s_blocksize);
bh ->b_dirt = 1;
brelse (bh);
}
}
}
}
sb->s_dirt = 0;
}
void ext2_write_super (struct super_block * sb)
{
struct ext2_super_block * es;
if ((sb->s_flags & MS_RDONLY) == 0) {
es = (struct ext2_super_block *) sb->u.ext2_sb.s_sbh->b_data;
#ifdef EXT2FS_DEBUG
printk ("ext2_write_super: setting valid to 0\n");
#endif
es->s_valid = 0;
ext2_commit_super (sb, es);
}
sb->s_dirt = 0;
}
int ext2_remount(struct super_block *sb, int *flags)
{
struct ext2_super_block * es;
es = (struct ext2_super_block *) sb->u.ext2_sb.s_sbh->b_data;
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
if (*flags & MS_RDONLY) {
if (es->s_valid || !sb->u.ext2_sb.s_was_mounted_valid)
return 0;
/* OK, we are remounting a valid rw partition rdonly, so set
the rdonly flag and then mark the partition as valid
again. */
sb->s_flags |= MS_RDONLY;
es->s_valid = sb->u.ext2_sb.s_was_mounted_valid;
ext2_commit_super(sb, es);
}
else {
/* Mounting a RDONLY partition read-write, so reread and
store the current valid flag. (It may have been changed
by ext2fs since we originally mounted the partition.) */
sb->u.ext2_sb.s_was_mounted_valid = es->s_valid;
}
return 0;
}
void ext2_statfs (struct super_block * sb, struct statfs * buf)
{
long tmp;
......@@ -647,8 +691,8 @@ void ext2_read_inode (struct inode * inode)
unsigned long block;
struct ext2_group_desc * gdp;
if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_INO &&
inode->i_ino < EXT2_FIRST_INO) ||
if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
inode->i_ino != EXT2_ACL_DATA_INO && inode->i_ino < EXT2_FIRST_INO) ||
inode->i_ino > inode->i_sb->u.ext2_sb.s_inodes_count) {
printk ("ext2_read_inode: bad inode number of dev %0x04: %d\n",
inode->i_dev, inode->i_ino);
......@@ -697,7 +741,8 @@ void ext2_read_inode (struct inode * inode)
inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
brelse (bh);
inode->i_op = NULL;
if (inode->i_ino == EXT2_ACL_INO)
if (inode->i_ino == EXT2_ACL_IDX_INO ||
inode->i_ino == EXT2_ACL_DATA_INO)
/* Nothing to do */ ;
else if (S_ISREG(inode->i_mode))
inode->i_op = &ext2_file_inode_operations;
......@@ -713,7 +758,7 @@ void ext2_read_inode (struct inode * inode)
init_fifo(inode);
}
void ext2_write_inode (struct inode * inode)
static struct buffer_head * ext2_update_inode (struct inode * inode)
{
struct buffer_head * bh;
struct ext2_inode * raw_inode;
......@@ -727,7 +772,7 @@ void ext2_write_inode (struct inode * inode)
inode->i_ino > inode->i_sb->u.ext2_sb.s_inodes_count) {
printk ("ext2_write_inode: bad inode number of dev %0x04: %d\n",
inode->i_dev, inode->i_ino);
return;
return 0;
}
block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
......@@ -768,5 +813,35 @@ void ext2_write_inode (struct inode * inode)
raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
bh->b_dirt = 1;
inode->i_dirt = 0;
return bh;
}
void ext2_write_inode (struct inode * inode)
{
struct buffer_head * bh;
bh = ext2_update_inode(inode);
brelse (bh);
}
int ext2_sync_inode (struct inode *inode)
{
int err = 0;
struct buffer_head *bh;
bh = ext2_update_inode(inode);
if (bh && bh->b_dirt)
{
ll_rw_block(WRITE, 1, &bh);
wait_on_buffer(bh);
if (bh->b_req && !bh->b_uptodate)
{
printk ("IO error syncing ext2 inode [%04x:%08x]\n",
inode->i_dev, inode->i_ino);
err = -1;
}
}
else if (!bh)
err = -1;
brelse (bh);
return err;
}
......@@ -63,14 +63,10 @@ static int ext2_match (int len, const char * const name,
* itself (as a parameter - res_dir). It does NOT read the inode of the
* entry - you'll have to do that yourself if you want to.
*
* In the ext2 file system, this function also returns a pointer on the
* previous directory entry because functions which remove directory
* entries need it
*/
static struct buffer_head * ext2_find_entry (struct inode * dir,
const char * const name, int namelen,
struct ext2_dir_entry ** res_dir,
struct ext2_dir_entry ** prev_dir)
struct ext2_dir_entry ** res_dir)
{
long offset;
struct buffer_head * bh;
......@@ -92,8 +88,6 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
bh = ext2_bread (dir, 0, 0, &err);
if (!bh)
return NULL;
if (prev_dir)
*prev_dir = NULL;
offset = 0;
de = (struct ext2_dir_entry *) bh->b_data;
while (offset < dir->i_size) {
......@@ -105,8 +99,6 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
continue;
}
de = (struct ext2_dir_entry *) bh->b_data;
if (prev_dir)
*prev_dir = NULL;
}
if (! ext2_check_dir_entry ("ext2_find_entry", dir, de, bh,
offset)) {
......@@ -118,8 +110,6 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
return bh;
}
offset += de->rec_len;
if (prev_dir)
*prev_dir = de;
de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
}
brelse (bh);
......@@ -143,7 +133,7 @@ int ext2_lookup (struct inode * dir, const char * name, int len,
#ifndef DONT_USE_DCACHE
if (!(ino = ext2_dcache_lookup (dir->i_dev, dir->i_ino, name, len))) {
#endif
if (!(bh = ext2_find_entry (dir, name, len, &de, NULL))) {
if (!(bh = ext2_find_entry (dir, name, len, &de))) {
iput (dir);
return -ENOENT;
}
......@@ -200,6 +190,13 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
#endif
if (!namelen)
return NULL;
/* Is this a busy deleted directory? Can't create new files
if so */
if (dir->i_size == 0)
{
*err = -ENOENT;
return NULL;
}
bh = ext2_bread (dir, 0, 0, err);
if (!bh)
return NULL;
......@@ -215,6 +212,10 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
if (!bh)
return NULL;
if (dir->i_size <= offset) {
if (dir->i_size == 0) {
*err = -ENOENT;
return NULL;
}
#ifdef EXT2FS_DEBUG
printk ("ext2_add_entry: creating next block\n");
#endif
......@@ -262,6 +263,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
bh->b_dirt = 1;
*res_dir = de;
*err = 0;
return bh;
}
offset += de->rec_len;
......@@ -275,13 +277,31 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
* ext2_delete_entry deletes a directory entry by merging it with the
* previous entry
*/
static void ext2_delete_entry (struct ext2_dir_entry * dir,
struct ext2_dir_entry * prev_dir)
static int ext2_delete_entry (struct ext2_dir_entry * dir,
struct buffer_head *bh)
{
if (prev_dir != NULL)
prev_dir->rec_len += dir->rec_len;
else
dir->inode = 0;
struct ext2_dir_entry * de, * pde;
int i;
i = 0;
pde = NULL;
de = (struct ext2_dir_entry *) bh->b_data;
while (i < bh->b_size) {
if (! ext2_check_dir_entry ("ext2_delete_entry", NULL,
de, bh, i))
return -EIO;
if (de == dir) {
if (pde)
pde->rec_len += dir->rec_len;
else
dir->inode = 0;
return 0;
}
i += de->rec_len;
pde = de;
de = (struct ext2_dir_entry *) ((char *) de + de->rec_len);
}
return -ENOENT;
}
int ext2_create (struct inode * dir,const char * name, int len, int mode,
......@@ -333,7 +353,7 @@ int ext2_mknod (struct inode * dir, const char * name, int len, int mode,
if (!dir)
return -ENOENT;
bh = ext2_find_entry (dir, name, len, &de, NULL);
bh = ext2_find_entry (dir, name, len, &de);
if (bh) {
brelse (bh);
iput (dir);
......@@ -395,7 +415,7 @@ int ext2_mkdir (struct inode * dir, const char * name, int len, int mode)
if (!dir)
return -ENOENT;
bh = ext2_find_entry (dir, name, len, &de, NULL);
bh = ext2_find_entry (dir, name, len, &de);
if (bh) {
brelse (bh);
iput (dir);
......@@ -519,18 +539,26 @@ int ext2_rmdir (struct inode * dir, const char * name, int len)
int retval;
struct inode * inode;
struct buffer_head * bh;
struct ext2_dir_entry * de, * pde;
struct ext2_dir_entry * de;
repeat:
if (!dir)
return -ENOENT;
inode = NULL;
bh = ext2_find_entry (dir, name, len, &de, &pde);
bh = ext2_find_entry (dir, name, len, &de);
retval = -ENOENT;
if (!bh)
goto end_rmdir;
retval = -EPERM;
if (!(inode = iget (dir->i_sb, de->inode)))
goto end_rmdir;
if (de->inode != inode->i_ino) {
iput(inode);
brelse(bh);
current->counter = 0;
schedule();
goto repeat;
}
if ((dir->i_mode & S_ISVTX) && current->euid &&
inode->i_uid != current->euid)
goto end_rmdir;
......@@ -546,23 +574,31 @@ int ext2_rmdir (struct inode * dir, const char * name, int len)
retval = -ENOTEMPTY;
goto end_rmdir;
}
if (inode->i_count > 1) {
retval = -EBUSY;
goto end_rmdir;
if (inode->i_count > 1 && inode->i_nlink <= 2) {
/* Are we deleting the last instance of a busy directory?
Better clean up if so. */
/* Make directory empty (it will be truncated when finally
dereferenced). This also inhibits ext2_add_entry. */
inode->i_size = 0;
#ifndef DONT_USE_DCACHE
ext2_dcache_remove(inode->i_dev, inode->i_ino, ".", 1);
ext2_dcache_remove(inode->i_dev, inode->i_ino, "..", 2);
#endif
}
if (inode->i_nlink != 2)
printk ("empty directory has nlink!=2 (%d)\n", inode->i_nlink);
#ifndef DONT_USE_DCACHE
ext2_dcache_remove (dir->i_dev, dir->i_ino, de->name, de->name_len);
#endif
ext2_delete_entry (de, pde);
retval = ext2_delete_entry (de, bh);
if (retval)
goto end_rmdir;
bh->b_dirt = 1;
inode->i_nlink = 0;
inode->i_dirt = 1;
dir->i_nlink --;
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
retval = 0;
end_rmdir:
iput (dir);
iput (inode);
......@@ -575,17 +611,25 @@ int ext2_unlink (struct inode * dir, const char * name, int len)
int retval;
struct inode * inode;
struct buffer_head * bh;
struct ext2_dir_entry * de, * pde;
struct ext2_dir_entry * de;
repeat:
if (!dir)
return -ENOENT;
retval = -ENOENT;
inode = NULL;
bh = ext2_find_entry (dir, name, len, &de, &pde);
bh = ext2_find_entry (dir, name, len, &de);
if (!bh)
goto end_unlink;
if (!(inode = iget (dir->i_sb, de->inode)))
goto end_unlink;
if (de->inode != inode->i_ino) {
iput(inode);
brelse(bh);
current->counter = 0;
schedule();
goto repeat;
}
retval = -EPERM;
if ((dir->i_mode & S_ISVTX) && !suser() &&
current->euid != inode->i_uid &&
......@@ -601,7 +645,9 @@ int ext2_unlink (struct inode * dir, const char * name, int len)
#ifndef DONT_USE_DCACHE
ext2_dcache_remove (dir->i_dev, dir->i_ino, de->name, de->name_len);
#endif
ext2_delete_entry (de, pde);
retval = ext2_delete_entry (de, bh);
if (retval)
goto end_unlink;
bh->b_dirt = 1;
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
......@@ -665,7 +711,7 @@ int ext2_symlink (struct inode * dir, const char * name, int len,
}
inode->i_size = i;
inode->i_dirt = 1;
bh = ext2_find_entry (dir, name, len, &de, NULL);
bh = ext2_find_entry (dir, name, len, &de);
if (bh) {
inode->i_nlink --;
inode->i_dirt = 1;
......@@ -711,7 +757,7 @@ int ext2_link (struct inode * oldinode, struct inode * dir,
iput (dir);
return -EMLINK;
}
bh = ext2_find_entry (dir, name, len, &de, NULL);
bh = ext2_find_entry (dir, name, len, &de);
if (bh) {
brelse (bh);
iput (dir);
......@@ -788,11 +834,13 @@ static int do_ext2_rename (struct inode * old_dir, const char * old_name,
{
struct inode * old_inode, * new_inode;
struct buffer_head * old_bh, * new_bh, * dir_bh;
struct ext2_dir_entry * old_de, * new_de, * pde;
struct ext2_dir_entry * old_de, * new_de;
int retval;
goto start_up;
try_again:
if (new_bh && new_de)
ext2_delete_entry(new_de, new_bh);
brelse (old_bh);
brelse (new_bh);
brelse (dir_bh);
......@@ -803,7 +851,8 @@ static int do_ext2_rename (struct inode * old_dir, const char * old_name,
start_up:
old_inode = new_inode = NULL;
old_bh = new_bh = dir_bh = NULL;
old_bh = ext2_find_entry (old_dir, old_name, old_len, &old_de, &pde);
new_de = NULL;
old_bh = ext2_find_entry (old_dir, old_name, old_len, &old_de);
retval = -ENOENT;
if (!old_bh)
goto end_rename;
......@@ -815,7 +864,7 @@ static int do_ext2_rename (struct inode * old_dir, const char * old_name,
current->euid != old_inode->i_uid &&
current->euid != old_dir->i_uid && !suser())
goto end_rename;
new_bh = ext2_find_entry (new_dir, new_name, new_len, &new_de, NULL);
new_bh = ext2_find_entry (new_dir, new_name, new_len, &new_de);
if (new_bh) {
new_inode = iget (new_dir->i_sb, new_de->inode);
if (!new_inode) {
......@@ -882,11 +931,11 @@ static int do_ext2_rename (struct inode * old_dir, const char * old_name,
ext2_dcache_add (new_dir->i_dev, new_dir->i_ino, new_de->name,
new_de->name_len, new_de->inode);
#endif
if (old_bh->b_blocknr == new_bh->b_blocknr &&
((char *) new_de) + new_de->rec_len == (char *) old_de)
new_de->rec_len += old_de->rec_len;
else
ext2_delete_entry (old_de, pde);
retval = ext2_delete_entry (old_de, old_bh);
if (retval == -ENOENT)
goto try_again;
if (retval)
goto end_rename;
if (new_inode) {
new_inode->i_nlink --;
new_inode->i_dirt = 1;
......
......@@ -6,25 +6,89 @@
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/mm.h>
struct file file_table[NR_FILE];
struct file * first_file;
int nr_files = 0;
static void insert_file_free(struct file *file)
{
file->f_next = first_file;
file->f_prev = first_file->f_prev;
file->f_next->f_prev = file;
file->f_prev->f_next = file;
first_file = file;
}
static void remove_file_free(struct file *file)
{
if (first_file == file)
first_file = first_file->f_next;
if (file->f_next)
file->f_next->f_prev = file->f_prev;
if (file->f_prev)
file->f_prev->f_next = file->f_next;
file->f_next = file->f_prev = NULL;
}
static void put_last_free(struct file *file)
{
remove_file_free(file);
file->f_prev = first_file->f_prev;
file->f_prev->f_next = file;
file->f_next = first_file;
file->f_next->f_prev = file;
}
void grow_files(void)
{
unsigned long page;
struct file * file;
int i;
page = get_free_page(GFP_KERNEL);
if (!page)
return;
file = (struct file *) page;
for (i=0; i < (PAGE_SIZE / sizeof(struct file)); i++, file++)
{
if (!first_file)
{
file->f_next = file;
file->f_prev = file;
first_file = file;
}
else
insert_file_free(file);
}
nr_files += i;
}
unsigned long file_table_init(unsigned long start, unsigned long end)
{
memset(file_table,0,sizeof(file_table));
first_file = NULL;
return start;
}
struct file * get_empty_filp(void)
{
int i;
struct file * f = file_table+0;
struct file * f;
for (i = 0; i++ < NR_FILE; f++)
if (!first_file)
grow_files();
repeat:
for (f = first_file, i=0; i < nr_files; i++, f = f->f_next)
if (!f->f_count) {
remove_file_free(f);
memset(f,0,sizeof(*f));
put_last_free(f);
f->f_count = 1;
return f;
}
if (nr_files < NR_FILE) {
grow_files();
goto repeat;
}
return NULL;
}
......@@ -12,18 +12,105 @@
#include <asm/system.h>
static struct inode * inode_table;
static struct inode * last_inode;
static struct inode * hash_table[NR_IHASH];
static struct inode * first_inode;
static struct wait_queue * inode_wait = NULL;
static int nr_inodes = 0, nr_free_inodes = 0;
static inline int const hashfn(dev_t dev, int i)
{
return (dev ^ i) % NR_IHASH;
}
static inline struct inode ** const hash(dev_t dev, int i)
{
return hash_table + hashfn(dev, i);
}
static void insert_inode_free(struct inode *inode)
{
inode->i_next = first_inode;
inode->i_prev = first_inode->i_prev;
inode->i_next->i_prev = inode;
inode->i_prev->i_next = inode;
first_inode = inode;
}
static void remove_inode_free(struct inode *inode)
{
if (first_inode == inode)
first_inode = first_inode->i_next;
if (inode->i_next)
inode->i_next->i_prev = inode->i_prev;
if (inode->i_prev)
inode->i_prev->i_next = inode->i_next;
inode->i_next = inode->i_prev = NULL;
}
void insert_inode_hash(struct inode *inode)
{
struct inode **h;
h = hash(inode->i_dev, inode->i_ino);
inode->i_hash_next = *h;
inode->i_hash_prev = NULL;
if (inode->i_hash_next)
inode->i_hash_next->i_hash_prev = inode;
*h = inode;
}
static void remove_inode_hash(struct inode *inode)
{
struct inode **h;
h = hash(inode->i_dev, inode->i_ino);
if (*h == inode)
*h = inode->i_hash_next;
if (inode->i_hash_next)
inode->i_hash_next->i_hash_prev = inode->i_hash_prev;
if (inode->i_hash_prev)
inode->i_hash_prev->i_hash_next = inode->i_hash_next;
inode->i_hash_prev = inode->i_hash_next = NULL;
}
static void put_last_free(struct inode *inode)
{
remove_inode_free(inode);
inode->i_prev = first_inode->i_prev;
inode->i_prev->i_next = inode;
inode->i_next = first_inode;
inode->i_next->i_prev = inode;
}
void grow_inodes(void)
{
unsigned long page;
struct inode * inode;
int i;
page = get_free_page(GFP_KERNEL);
if (!page)
return;
inode = (struct inode *) page;
for (i=0; i < (PAGE_SIZE / sizeof(struct inode)); i++, inode++)
{
if (!first_inode)
{
inode->i_next = inode;
inode->i_prev = inode;
first_inode = inode;
}
else
insert_inode_free(inode);
}
nr_inodes += i;
nr_free_inodes += i;
}
unsigned long inode_init(unsigned long start, unsigned long end)
{
start += 0x0000000f;
start &= 0xfffffff0;
inode_table = (struct inode *) start;
last_inode = inode_table;
start = (unsigned long) (inode_table + NR_INODE);
memset(inode_table,0,NR_INODE*sizeof(struct inode));
memset(hash_table, 0, sizeof(hash_table));
first_inode = NULL;
return start;
}
......@@ -65,15 +152,21 @@ void clear_inode(struct inode * inode)
wait_on_inode(inode);
wait = ((volatile struct inode *) inode)->i_wait;
remove_inode_hash(inode);
remove_inode_free(inode);
if (inode->i_count)
nr_free_inodes++;
memset(inode,0,sizeof(*inode));
((volatile struct inode *) inode)->i_wait = wait;
insert_inode_free(inode);
}
int fs_may_mount(dev_t dev)
{
struct inode * inode;
int i;
for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++) {
for (inode = first_inode, i=0; i<nr_inodes; i++, inode=inode->i_next) {
if (inode->i_dev != dev)
continue;
if (inode->i_count || inode->i_dirt || inode->i_lock)
......@@ -86,8 +179,9 @@ int fs_may_mount(dev_t dev)
int fs_may_umount(dev_t dev, struct inode * mount_root)
{
struct inode * inode;
int i;
for (inode = inode_table+0 ; inode < inode_table+NR_INODE ; inode++) {
for (inode = first_inode, i=0; i<nr_inodes; i++, inode=inode->i_next) {
if (inode->i_dev==dev && inode->i_count)
if (inode == mount_root && inode->i_count == 1)
continue;
......@@ -97,6 +191,22 @@ int fs_may_umount(dev_t dev, struct inode * mount_root)
return 1;
}
int fs_may_remount_ro(dev_t dev)
{
struct file * file;
int i;
/* Check that no files are currently opened for writing. */
for (file = first_file, i=0; i<nr_files; i++, file=file->f_next) {
if (!file->f_count || !file->f_inode ||
file->f_inode->i_dev != dev)
continue;
if (S_ISREG(file->f_inode->i_mode) && (file->f_mode & 2))
return 0;
}
return 1;
}
static void write_inode(struct inode * inode)
{
if (!inode->i_dirt)
......@@ -159,8 +269,8 @@ void invalidate_inodes(dev_t dev)
int i;
struct inode * inode;
inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) {
inode = first_inode;
for(i = 0; i < nr_inodes*2; i++, inode = inode->i_next) {
wait_on_inode(inode);
if (inode->i_dev == dev) {
if (inode->i_count) {
......@@ -175,9 +285,11 @@ void invalidate_inodes(dev_t dev)
void sync_inodes(dev_t dev)
{
int i;
struct inode * inode;
for(inode = 0+inode_table ; inode < NR_INODE+inode_table ; inode++) {
inode = first_inode;
for(i = 0; i < nr_inodes*2; i++, inode = inode->i_next) {
if (dev && inode->i_dev != dev)
continue;
wait_on_inode(inode);
......@@ -224,25 +336,36 @@ void iput(struct inode * inode)
goto repeat;
}
inode->i_count--;
nr_free_inodes++;
return;
}
struct inode * get_empty_inode(void)
{
struct inode * inode;
struct inode * inode, * best;
int i;
if (nr_inodes < NR_INODE && nr_free_inodes < (nr_inodes >> 2))
grow_inodes();
repeat:
inode = NULL;
for (i = NR_INODE; i ; i--) {
if (++last_inode >= inode_table + NR_INODE)
last_inode = inode_table;
if (!last_inode->i_count) {
inode = last_inode;
if (!inode->i_dirt && !inode->i_lock)
inode = first_inode;
best = NULL;
for (i = 0; i<nr_inodes; inode = inode->i_next, i++) {
if (!inode->i_count) {
if (!best)
best = inode;
if (!inode->i_dirt && !inode->i_lock) {
best = inode;
break;
}
}
}
if (!best || best->i_dirt || best->i_lock)
if (nr_inodes < NR_INODE) {
grow_inodes();
goto repeat;
}
inode = best;
if (!inode) {
printk("VFS: No free inodes - contact Linus\n");
sleep_on(&inode_wait);
......@@ -261,6 +384,12 @@ struct inode * get_empty_inode(void)
clear_inode(inode);
inode->i_count = 1;
inode->i_nlink = 1;
nr_free_inodes--;
if (nr_free_inodes < 0)
{
printk ("VFS: get_empty_inode: bad free inode count.\n");
nr_free_inodes = 0;
}
return inode;
}
......@@ -293,18 +422,19 @@ struct inode * iget(struct super_block * sb,int nr)
if (!sb)
panic("VFS: iget with sb==NULL");
repeat:
empty = get_empty_inode();
inode = inode_table;
while (inode < NR_INODE+inode_table) {
inode = *(hash(sb->s_dev,nr));
while (inode) {
if (inode->i_dev != sb->s_dev || inode->i_ino != nr) {
inode++;
inode = inode->i_hash_next;
continue;
}
wait_on_inode(inode);
if (inode->i_dev != sb->s_dev || inode->i_ino != nr) {
inode = inode_table;
continue;
}
if (inode->i_dev != sb->s_dev || inode->i_ino != nr)
goto repeat;
if (!inode->i_count)
nr_free_inodes--;
inode->i_count++;
if (inode->i_mount) {
int i;
......@@ -314,14 +444,8 @@ struct inode * iget(struct super_block * sb,int nr)
break;
if (i >= NR_SUPER) {
printk("VFS: Mounted inode hasn't got sb\n");
if (empty) {
if (last_inode > inode_table)
--last_inode;
else
last_inode
= inode_table + NR_INODE;
if (empty)
iput(empty);
}
return inode;
}
iput(inode);
......@@ -329,18 +453,14 @@ struct inode * iget(struct super_block * sb,int nr)
printk("VFS: Mounted device %d/%d has no rootinode\n",
MAJOR(inode->i_dev), MINOR(inode->i_dev));
else {
if (!inode->i_count)
nr_free_inodes--;
inode->i_count++;
wait_on_inode(inode);
}
}
if (empty) {
if (last_inode > inode_table)
--last_inode;
else
last_inode
= inode_table + NR_INODE;
if (empty)
iput(empty);
}
return inode;
}
if (!empty)
......@@ -350,6 +470,8 @@ struct inode * iget(struct super_block * sb,int nr)
inode->i_dev = sb->s_dev;
inode->i_ino = nr;
inode->i_flags = sb->s_flags;
put_last_free(inode);
insert_inode_hash(inode);
read_inode(inode);
return inode;
}
......
......@@ -45,7 +45,8 @@ static struct super_operations isofs_sops = {
NULL, /* put_inode */
isofs_put_super,
NULL, /* write_super */
isofs_statfs
isofs_statfs,
NULL
};
......@@ -317,7 +318,8 @@ void isofs_read_inode(struct inode * inode)
/* There are defective discs out there - we do this to protect
ourselves. A cdrom will never contain more than 700Mb */
if(inode->i_size < 0 || inode->i_size > 700000000) {
if((inode->i_size < 0 || inode->i_size > 700000000) &&
inode->i_sb->u.isofs_sb.s_cruft == 'n') {
printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n");
inode->i_sb->u.isofs_sb.s_cruft = 'y';
};
......
This diff is collapsed.
......@@ -15,7 +15,7 @@
$(AS) -o $*.o $<
OBJS= bitmap.o truncate.o namei.o inode.o \
file.o dir.o symlink.o
file.o dir.o symlink.o fsync.o
minix.o: $(OBJS)
$(LD) -r -o minix.o $(OBJS)
......
......@@ -217,6 +217,7 @@ struct inode * minix_new_inode(const struct inode * dir)
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = NULL;
inode->i_blocks = inode->i_blksize = 0;
insert_inode_hash(inode);
return inode;
}
......
......@@ -30,7 +30,7 @@ static struct file_operations minix_dir_operations = {
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* default fsync */
file_fsync /* default fsync */
};
/*
......
......@@ -42,7 +42,7 @@ static struct file_operations minix_file_operations = {
NULL, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
NULL /* fsync */
minix_sync_file /* fsync */
};
struct inode_operations minix_file_inode_operations = {
......
/*
* linux/fs/minix/fsync.c
*
* Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
* from
* Copyright (C) 1991, 1992 Linus Torvalds
*
* minix fsync primitive
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/locks.h>
#include <linux/fs.h>
#include <linux/minix_fs.h>
#define blocksize BLOCK_SIZE
#define addr_per_block 512
static int sync_block (struct inode * inode, unsigned short * block, int wait)
{
struct buffer_head * bh;
unsigned short tmp;
if (!*block)
return 0;
tmp = *block;
bh = get_hash_table(inode->i_dev, *block, blocksize);
if (!bh)
return 0;
if (*block != tmp) {
brelse (bh);
return 1;
}
if (wait && bh->b_req && !bh->b_uptodate) {
brelse(bh);
return -1;
}
if (wait || !bh->b_uptodate || !bh->b_dirt)
{
brelse(bh);
return 0;
}
ll_rw_block(WRITE, 1, &bh);
bh->b_count--;
return 0;
}
static int sync_iblock (struct inode * inode, unsigned short * iblock,
struct buffer_head **bh, int wait)
{
int rc;
unsigned short tmp;
*bh = NULL;
tmp = *iblock;
if (!tmp)
return 0;
rc = sync_block (inode, iblock, wait);
if (rc)
return rc;
*bh = bread(inode->i_dev, tmp, blocksize);
if (tmp != *iblock) {
brelse(*bh);
*bh = NULL;
return 1;
}
if (!*bh)
return -1;
return 0;
}
static int sync_direct(struct inode *inode, int wait)
{
int i;
int rc, err = 0;
for (i = 0; i < 7; i++) {
rc = sync_block (inode, inode->u.minix_i.i_data + i, wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
return err;
}
static int sync_indirect(struct inode *inode, unsigned short *iblock, int wait)
{
int i;
struct buffer_head * ind_bh;
int rc, err = 0;
rc = sync_iblock (inode, iblock, &ind_bh, wait);
if (rc || !ind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_block (inode,
((unsigned short *) ind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(ind_bh);
return err;
}
static int sync_dindirect(struct inode *inode, unsigned short *diblock,
int wait)
{
int i;
struct buffer_head * dind_bh;
int rc, err = 0;
rc = sync_iblock (inode, diblock, &dind_bh, wait);
if (rc || !dind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_indirect (inode,
((unsigned short *) dind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(dind_bh);
return err;
}
int minix_sync_file(struct inode * inode, struct file * file)
{
int wait, err = 0;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return -EINVAL;
for (wait=0; wait<=1; wait++)
{
err |= sync_direct(inode, wait);
err |= sync_indirect(inode, inode->u.minix_i.i_data+7, wait);
err |= sync_dindirect(inode, inode->u.minix_i.i_data+8, wait);
}
err |= minix_sync_inode (inode);
return (err < 0) ? -EIO : 0;
}
......@@ -45,7 +45,8 @@ static struct super_operations minix_sops = {
minix_put_inode,
minix_put_super,
NULL,
minix_statfs
minix_statfs,
NULL
};
struct super_block *minix_read_super(struct super_block *s,void *data,
......@@ -362,7 +363,7 @@ void minix_read_inode(struct inode * inode)
init_fifo(inode);
}
void minix_write_inode(struct inode * inode)
static struct buffer_head * minix_update_inode(struct inode * inode)
{
struct buffer_head * bh;
struct minix_inode * raw_inode;
......@@ -373,14 +374,14 @@ void minix_write_inode(struct inode * inode)
printk("Bad inode number on dev 0x%04x: %d is out of range\n",
inode->i_dev, ino);
inode->i_dirt = 0;
return;
return 0;
}
block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks + inode->i_sb->u.minix_sb.s_zmap_blocks +
(ino-1)/MINIX_INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) {
printk("unable to read i-node block\n");
inode->i_dirt = 0;
return;
return 0;
}
raw_inode = ((struct minix_inode *)bh->b_data) +
(ino-1)%MINIX_INODES_PER_BLOCK;
......@@ -396,5 +397,35 @@ void minix_write_inode(struct inode * inode)
raw_inode->i_zone[block] = inode->u.minix_i.i_data[block];
inode->i_dirt=0;
bh->b_dirt=1;
return bh;
}
void minix_write_inode(struct inode * inode)
{
struct buffer_head *bh;
bh = minix_update_inode(inode);
brelse(bh);
}
int minix_sync_inode(struct inode * inode)
{
int err = 0;
struct buffer_head *bh;
bh = minix_update_inode(inode);
if (bh && bh->b_dirt)
{
ll_rw_block(WRITE, 1, &bh);
wait_on_buffer(bh);
if (bh->b_req && !bh->b_uptodate)
{
printk ("IO error syncing minix inode [%04x:%08x]\n",
inode->i_dev, inode->i_ino);
err = -1;
}
}
else if (!bh)
err = -1;
brelse (bh);
return err;
}
......@@ -33,7 +33,7 @@ static struct file_operations msdos_dir_operations = {
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* fsync */
file_fsync /* fsync */
};
struct inode_operations msdos_dir_inode_operations = {
......
......@@ -35,7 +35,7 @@ static struct file_operations msdos_file_operations = {
NULL, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
NULL /* fsync */
file_fsync /* fsync */
};
struct inode_operations msdos_file_inode_operations = {
......
......@@ -61,7 +61,8 @@ static struct super_operations msdos_sops = {
msdos_put_inode,
msdos_put_super,
NULL, /* added in 0.96c */
msdos_statfs
msdos_statfs,
NULL
};
......
......@@ -264,7 +264,7 @@ void date_unix2dos(int unix_date,unsigned short *time,
non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
returned in bh. */
int msdos_get_entry(struct inode *dir,int *pos,struct buffer_head **bh,
int msdos_get_entry(struct inode *dir, off_t *pos,struct buffer_head **bh,
struct msdos_dir_entry **de)
{
int sector,offset;
......
......@@ -34,7 +34,7 @@ static int msdos_format_name(char conv,const char *name,int len,char *res,
int dot_dirs)
{
char *walk,**reserved;
char c;
unsigned char c;
int space;
if (IS_FREE(name)) return -EINVAL;
......@@ -295,7 +295,7 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
static int msdos_empty(struct inode *dir)
{
int pos;
off_t pos;
struct buffer_head *bh;
struct msdos_dir_entry *de;
......
......@@ -32,7 +32,8 @@ static struct super_operations nfs_sops = {
nfs_put_inode, /* put inode */
nfs_put_super, /* put superblock */
NULL, /* write superblock */
nfs_statfs /* stat filesystem */
nfs_statfs, /* stat filesystem */
NULL
};
static void nfs_put_inode(struct inode * inode)
......
......@@ -16,6 +16,7 @@
#define NFS_PROC_DEBUG
#endif
#include <linux/config.h>
#include <linux/param.h>
#include <linux/sched.h>
#include <linux/mm.h>
......@@ -23,8 +24,7 @@
#include <linux/utsname.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <netinet/in.h>
#include <linux/in.h>
#ifdef NFS_PROC_DEBUG
static int proc_debug = 0;
......
......@@ -6,16 +6,16 @@
* low-level nfs remote procedure call interface
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/nfs_fs.h>
#include <linux/errno.h>
#include <linux/socket.h>
#include <linux/fcntl.h>
#include <asm/segment.h>
#include <linux/in.h>
#include <linux/net.h>
#include <netinet/in.h>
#include "../../net/kern_sock.h"
extern struct socket *socki_lookup(struct inode *inode);
......
......@@ -69,7 +69,7 @@ static int pipe_write(struct inode * inode, struct file * filp, char * buf, int
if (current->signal & ~current->blocked)
return written?written:-ERESTARTSYS;
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
return written?written:-EAGAIN;
else
interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode));
}
......
......@@ -14,7 +14,7 @@
.s.o:
$(AS) -o $*.o $<
OBJS= inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o
OBJS= inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o
proc.o: $(OBJS)
$(LD) -r -o proc.o $(OBJS)
......
......@@ -19,15 +19,6 @@
#define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
#define KSTK_EIP(stack) (((unsigned long *)stack)[1019])
#define KSTK_ESP(stack) (((unsigned long *)stack)[1022])
#define _SSIZE(stack) (TASK_SIZE - KSTK_ESP(stack))
#define SSIZE(stack) (KSTK_ESP(stack) ? _SSIZE(stack) : 0)
#define VSIZE(task,stack) ((task)->brk + 1023 + SSIZE(stack))
static int get_loadavg(char * buffer)
{
int a, b, c;
......@@ -163,8 +154,10 @@ static unsigned long get_wchan(struct task_struct *p)
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
ebp = p->tss.ebp;
stack_page = p->kernel_stack_page;
if (!stack_page)
return 0;
ebp = p->tss.ebp;
do {
if (ebp < stack_page || ebp >= 4092+stack_page)
return 0;
......@@ -177,10 +170,14 @@ static unsigned long get_wchan(struct task_struct *p)
return 0;
}
#define KSTK_EIP(stack) (((unsigned long *)stack)[1019])
#define KSTK_ESP(stack) (((unsigned long *)stack)[1022])
static int get_stat(int pid, char * buffer)
{
struct task_struct ** p = get_task(pid);
unsigned long sigignore=0, sigcatch=0, bit=1, wchan;
unsigned long vsize, eip, esp;
int i,tty_pgrp;
char state;
......@@ -190,6 +187,15 @@ static int get_stat(int pid, char * buffer)
state = '.';
else
state = "RSDZTD"[(*p)->state];
eip = esp = 0;
vsize = (*p)->kernel_stack_page;
if (vsize) {
eip = KSTK_EIP(vsize);
esp = KSTK_ESP(vsize);
vsize = (*p)->brk + 4095;
if (esp)
vsize += TASK_SIZE - esp;
}
wchan = get_wchan(*p);
for(i=0; i<32; ++i) {
switch((int) (*p)->sigaction[i].sa_handler) {
......@@ -230,14 +236,14 @@ static int get_stat(int pid, char * buffer)
(*p)->timeout,
(*p)->it_real_value,
(*p)->start_time,
VSIZE((*p),(*p)->kernel_stack_page),
vsize,
(*p)->rss, /* you might want to shift this left 3 */
(*p)->rlim[RLIMIT_RSS].rlim_cur,
(*p)->start_code,
(*p)->end_code,
(*p)->start_stack,
KSTK_ESP((*p)->kernel_stack_page),
KSTK_EIP((*p)->kernel_stack_page),
esp,
eip,
(*p)->signal,
(*p)->blocked,
sigignore,
......
......@@ -37,7 +37,8 @@ static struct super_operations proc_sops = {
proc_put_inode,
proc_put_super,
NULL,
proc_statfs
proc_statfs,
NULL
};
struct super_block *proc_read_super(struct super_block *s,void *data,
......@@ -100,12 +101,26 @@ void proc_read_inode(struct inode * inode)
inode->i_op = &proc_root_inode_operations;
return;
}
if (!pid) {
if ((ino >= 128) && (ino <= 160)) { /* files within /proc/net */
inode->i_mode = S_IFREG | 0444;
inode->i_op = &proc_array_inode_operations;
if (ino == 5) {
inode->i_mode = S_IFREG | 0400;
inode->i_op = &proc_kmsg_inode_operations;
inode->i_op = &proc_net_inode_operations;
return;
}
if (!pid) {
switch (ino) {
case 5:
inode->i_mode = S_IFREG | 0444;
inode->i_op = &proc_kmsg_inode_operations;
break;
case 8: /* for the net directory */
inode->i_mode = S_IFDIR | 0555;
inode->i_nlink = 2;
inode->i_op = &proc_net_inode_operations;
break;
default:
inode->i_mode = S_IFREG | 0444;
inode->i_op = &proc_array_inode_operations;
break;
}
return;
}
......
/*
* linux/fs/proc/net.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* gjh 3/'93 heim@peanuts.informatik.uni-tuebingen.de (Gerald J. Heim)
* most of this file is stolen from base.c
* it works, but you shouldn't use it as a guideline
* for new proc-fs entries. once i'll make it better.
* fvk 3/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen)
* cleaned up the whole thing, moved "net" specific code to
* the NET kernel layer (where it belonged in the first place).
* Michael K. Johnson (johnsonm@stolaf.edu) 3/93
* Added support from my previous inet.c. Cleaned things up
* quite a bit, modularized the code.
* fvk 4/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen)
* Renamed "route_get_info()" to "rt_get_info()" for consistency.
*
* proc net directory handling functions
*/
#include <linux/autoconf.h>
#include <asm/segment.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
/* forward references */
static int proc_readnet(struct inode * inode, struct file * file,
char * buf, int count);
static int proc_readnetdir(struct inode *, struct file *,
struct dirent *, int);
static int proc_lookupnet(struct inode *,const char *,int,struct inode **);
/* the get_*_info() functions are in the net code, and are configured
in via the standard mechanism... */
#ifdef CONFIG_INET
extern int unix_get_info(char *);
extern int tcp_get_info(char *);
extern int udp_get_info(char *);
extern int raw_get_info(char *);
extern int arp_get_info(char *);
extern int dev_get_info(char *);
extern int rt_get_info(char *);
#endif /* CONFIG_INET */
static struct file_operations proc_net_operations = {
NULL, /* lseek - default */
proc_readnet, /* read - bad */
NULL, /* write - bad */
proc_readnetdir, /* readdir */
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* can't fsync */
};
/*
* proc directories can do almost nothing..
*/
struct inode_operations proc_net_inode_operations = {
&proc_net_operations, /* default net directory file-ops */
NULL, /* create */
proc_lookupnet, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* bmap */
NULL, /* truncate */
NULL /* permission */
};
static struct proc_dir_entry net_dir[] = {
{ 1,2,".." },
{ 8,1,"." }
#ifdef CONFIG_INET
,{ 128,4,"unix" },
{ 129,3,"arp" },
{ 130,5,"route" },
{ 131,3,"dev" },
{ 132,3,"raw" },
{ 133,3,"tcp" },
{ 134,3,"udp" }
#endif /* CONFIG_INET */
};
#define NR_NET_DIRENTRY ((sizeof (net_dir))/(sizeof (net_dir[0])))
static int proc_lookupnet(struct inode * dir,const char * name, int len,
struct inode ** result)
{
unsigned int ino;
int i;
*result = NULL;
if (!dir)
return -ENOENT;
if (!S_ISDIR(dir->i_mode)) {
iput(dir);
return -ENOENT;
}
i = NR_NET_DIRENTRY;
while (i-- > 0 && !proc_match(len,name,net_dir+i))
/* nothing */;
if (i < 0) {
iput(dir);
return -ENOENT;
}
ino = net_dir[i].low_ino;
if (!(*result = iget(dir->i_sb,ino))) {
iput(dir);
return -ENOENT;
}
iput(dir);
return 0;
}
static int proc_readnetdir(struct inode * inode, struct file * filp,
struct dirent * dirent, int count)
{
struct proc_dir_entry * de;
unsigned int ino;
int i,j;
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
ino = inode->i_ino;
if (((unsigned) filp->f_pos) < NR_NET_DIRENTRY) {
de = net_dir + filp->f_pos;
filp->f_pos++;
i = de->namelen;
ino = de->low_ino;
put_fs_long(ino, &dirent->d_ino);
put_fs_word(i,&dirent->d_reclen);
put_fs_byte(0,i+dirent->d_name);
j = i;
while (i--)
put_fs_byte(de->name[i], i+dirent->d_name);
return j;
}
return 0;
}
static int proc_readnet(struct inode * inode, struct file * file,
char * buf, int count)
{
char * page;
int length;
int end;
unsigned int ino;
if (count < 0)
return -EINVAL;
page = (char *) get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
ino = inode->i_ino;
switch (ino) {
#ifdef CONFIG_INET
case 128:
length = unix_get_info(page);
break;
case 129:
length = arp_get_info(page);
break;
case 130:
length = rt_get_info(page);
break;
case 131:
length = dev_get_info(page);
break;
case 132:
length = raw_get_info(page);
break;
case 133:
length = tcp_get_info(page);
break;
case 134:
length = udp_get_info(page);
break;
#endif /* CONFIG_INET */
default:
free_page((unsigned long) page);
return -EBADF;
}
if (file->f_pos >= length) {
free_page((unsigned long) page);
return 0;
}
if (count + file->f_pos > length)
count = length - file->f_pos;
end = count + file->f_pos;
memcpy_tofs(buf, page + file->f_pos, count);
free_page((unsigned long) page);
file->f_pos = end;
return count;
}
......@@ -58,7 +58,8 @@ static struct proc_dir_entry root_dir[] = {
{ 4,7,"meminfo" },
{ 5,4,"kmsg" },
{ 6,7,"version" },
{ 7,4,"self" } /* will change inode # */
{ 7,4,"self" }, /* will change inode # */
{ 8,3,"net" }
};
#define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0])))
......
......@@ -34,6 +34,8 @@ extern int root_mountflags;
struct super_block super_block[NR_SUPER];
static int do_remount_sb(struct super_block *sb, int flags);
/* this is initialized in init/main.c */
dev_t ROOT_DEV = 0;
......@@ -198,9 +200,20 @@ static void put_unnamed_dev(dev_t dev)
static int do_umount(dev_t dev)
{
struct super_block * sb;
if (dev==ROOT_DEV)
return -EBUSY;
int retval;
if (dev==ROOT_DEV) {
/* Special case for "unmounting" root. We just try to remount
it readonly, and sync() the device. */
if (!(sb=get_super(dev)))
return -ENOENT;
if (!(sb->s_flags & MS_RDONLY)) {
retval = do_remount_sb(sb, MS_RDONLY);
if (retval)
return retval;
}
return 0;
}
if (!(sb=get_super(dev)) || !(sb->s_covered))
return -ENOENT;
if (!sb->s_covered->i_mount)
......@@ -267,7 +280,7 @@ int sys_umount(char * name)
iput(inode);
return -ENXIO;
}
if (!(retval = do_umount(dev))) {
if (!(retval = do_umount(dev)) && dev != ROOT_DEV) {
fops = blkdev_fops[MAJOR(dev)];
if (fops && fops->release)
fops->release(inode,NULL);
......@@ -278,7 +291,7 @@ int sys_umount(char * name)
iput(inode);
if (retval)
return retval;
sync_dev(dev);
fsync_dev(dev);
return 0;
}
......@@ -329,6 +342,24 @@ static int do_mount(dev_t dev, const char * dir, char * type, int flags, void *
* FS-specific mount options can't be altered by remounting.
*/
static int do_remount_sb(struct super_block *sb, int flags)
{
int retval;
/* If we are remounting RDONLY, make sure there are no rw files open */
if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
if (!fs_may_remount_ro(sb->s_dev))
return -EBUSY;
if (sb->s_op && sb->s_op->remount_fs) {
retval = sb->s_op->remount_fs(sb, &flags);
if (retval)
return retval;
}
sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) |
(flags & MS_RMT_MASK);
return 0;
}
static int do_remount(const char *dir,int flags)
{
struct inode *dir_i;
......@@ -341,10 +372,9 @@ static int do_remount(const char *dir,int flags)
iput(dir_i);
return -EINVAL;
}
dir_i->i_sb->s_flags = (dir_i->i_sb->s_flags & ~MS_RMT_MASK) |
(flags & MS_RMT_MASK);
retval = do_remount_sb(dir_i->i_sb, flags);
iput(dir_i);
return 0;
return retval;
}
......
......@@ -15,7 +15,7 @@
$(AS) -o $*.o $<
OBJS= bitmap.o truncate.o namei.o inode.o \
file.o dir.o symlink.o
file.o dir.o symlink.o fsync.o
xiafs.o: $(OBJS)
$(LD) -r -o xiafs.o $(OBJS)
......
......@@ -332,6 +332,7 @@ struct inode * xiafs_new_inode(struct inode * dir)
inode->i_op = NULL;
inode->i_blocks = 0;
inode->i_blksize = XIAFS_ZSIZE(inode->i_sb);
insert_inode_hash(inode);
return inode;
}
......
......@@ -32,7 +32,7 @@ static struct file_operations xiafs_dir_operations = {
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* default fsync */
file_fsync /* default fsync */
};
/*
......
......@@ -45,7 +45,7 @@ static struct file_operations xiafs_file_operations = {
NULL, /* mmap */
NULL, /* no special open is needed */
NULL, /* release */
NULL /* fsync */
xiafs_sync_file /* fsync */
};
struct inode_operations xiafs_file_inode_operations = {
......
/*
* linux/fs/xiafs/fsync.c
*
* Changes Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
* from
* Copyright (C) 1991, 1992 Linus Torvalds
*
* xiafs fsync primitive
*/
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/locks.h>
#include <linux/fs.h>
#include <linux/xia_fs.h>
#include "xiafs_mac.h"
#define blocksize (XIAFS_ZSIZE(inode->i_sb))
#define addr_per_block (XIAFS_ADDRS_PER_Z(inode->i_sb))
static int sync_block (struct inode * inode, int * block, int wait)
{
struct buffer_head * bh;
int tmp;
if (!*block)
return 0;
tmp = *block;
bh = get_hash_table(inode->i_dev, *block, blocksize);
if (!bh)
return 0;
if (*block != tmp) {
brelse (bh);
return 1;
}
if (wait && bh->b_req && !bh->b_uptodate) {
brelse(bh);
return -1;
}
if (wait || !bh->b_uptodate || !bh->b_dirt)
{
brelse(bh);
return 0;
}
ll_rw_block(WRITE, 1, &bh);
bh->b_count--;
return 0;
}
static int sync_iblock (struct inode * inode, int * iblock,
struct buffer_head **bh, int wait)
{
int rc, tmp;
*bh = NULL;
tmp = *iblock;
if (!tmp)
return 0;
rc = sync_block (inode, iblock, wait);
if (rc)
return rc;
*bh = bread(inode->i_dev, tmp, blocksize);
if (tmp != *iblock) {
brelse(*bh);
*bh = NULL;
return 1;
}
if (!*bh)
return -1;
return 0;
}
static int sync_direct(struct inode *inode, int wait)
{
int i;
int rc, err = 0;
for (i = 0; i < 8; i++) {
rc = sync_block (inode, inode->u.ext_i.i_data + i, wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
return err;
}
static int sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
{
int i;
struct buffer_head * ind_bh;
int rc, err = 0;
rc = sync_iblock (inode, iblock, &ind_bh, wait);
if (rc || !ind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_block (inode,
((daddr_t *) ind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(ind_bh);
return err;
}
static int sync_dindirect(struct inode *inode, unsigned long *diblock,
int wait)
{
int i;
struct buffer_head * dind_bh;
int rc, err = 0;
rc = sync_iblock (inode, diblock, &dind_bh, wait);
if (rc || !dind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_indirect (inode,
((daddr_t *) dind_bh->b_data) + i,
wait);
if (rc > 0)
break;
if (rc)
err = rc;
}
brelse(dind_bh);
return err;
}
int xiafs_sync_file(struct inode * inode, struct file * file)
{
int wait, err = 0;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return -EINVAL;
for (wait=0; wait<=1; wait++)
{
err |= sync_direct(inode, wait);
err |= sync_indirect(inode, &inode->u.xiafs_i.i_ind_zone, wait);
err |= sync_dindirect(inode, &inode->u.xiafs_i.i_dind_zone, wait);
}
err |= xiafs_sync_inode (inode);
return (err < 0) ? -EIO : 0;
}
......@@ -52,7 +52,8 @@ static struct super_operations xiafs_sops = {
xiafs_put_inode,
xiafs_put_super,
NULL,
xiafs_statfs
xiafs_statfs,
NULL
};
struct super_block *xiafs_read_super(struct super_block *s, void *data,
......@@ -402,7 +403,7 @@ void xiafs_read_inode(struct inode * inode)
init_fifo(inode);
}
void xiafs_write_inode(struct inode * inode)
static struct buffer_head * xiafs_update_inode(struct inode * inode)
{
struct buffer_head * bh;
struct xiafs_inode * raw_inode;
......@@ -412,14 +413,14 @@ void xiafs_write_inode(struct inode * inode)
if (IS_RDONLY (inode)) {
printk("XIA-FS: write_inode on a read-only filesystem (%s %d)\n", WHERE_ERR);
inode->i_dirt = 0;
return;
return 0;
}
ino = inode->i_ino;
if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR);
inode->i_dirt=0;
return;
return 0;
}
zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones +
inode->i_sb->u.xiafs_sb.s_zmap_zones +
......@@ -427,7 +428,7 @@ void xiafs_write_inode(struct inode * inode)
if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) {
printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR);
inode->i_dirt=0;
return;
return 0;
}
raw_inode = ((struct xiafs_inode *)bh->b_data) +
((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) -1));
......@@ -453,7 +454,36 @@ void xiafs_write_inode(struct inode * inode)
}
inode->i_dirt=0;
bh->b_dirt=1;
brelse(bh);
return bh;
}
void xiafs_write_inode(struct inode * inode)
{
struct buffer_head * bh;
bh = xiafs_update_inode(inode);
brelse (bh);
}
int xiafs_sync_inode (struct inode *inode)
{
int err = 0;
struct buffer_head *bh;
bh = xiafs_update_inode(inode);
if (bh && bh->b_dirt)
{
ll_rw_block(WRITE, 1, &bh);
wait_on_buffer(bh);
if (bh->b_req && !bh->b_uptodate)
{
printk ("IO error syncing xiafs inode [%04x:%08x]\n",
inode->i_dev, inode->i_ino);
err = -1;
}
}
else if (!bh)
err = -1;
brelse (bh);
return err;
}
#
# Makefile for the iBCS emulator files
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
.S.s:
$(CPP) -traditional $< -o $*.s
.c.s:
$(CC) $(CFLAGS) -S $<
.s.o:
$(AS) -c -o $*.o $<
.c.o:
$(CC) $(CFLAGS) -c $<
SUBDIRS =
OBJS = emulate.o
ibcs.o: $(OBJS)
$(LD) -r -o ibcs.o $(OBJS)
sync
clean:
rm -f core *.o *.a *.s
for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean); done
dep:
$(CPP) -M *.c > .depend
for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep) || exit; done
dummy:
#
# include a dependency file if one exists
#
ifeq (.depend,$(wildcard .depend))
include .depend
endif
/*
* linux/abi/emulate.c
*
* Copyright (C) 1993 Linus Torvalds
*/
/*
* Emulate.c contains the entry point for the 'lcall 7,xxx' handler.
*/
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/segment.h>
#include <linux/ptrace.h>
#include <asm/segment.h>
#include <asm/system.h>
void iABI_emulate(struct pt_regs * regs)
{
printk("lcall 7,xxx: eax = %08x\n",regs->eax);
}
......@@ -4,8 +4,12 @@
/*
* linux/include/asm/irq.h
*
* (C) 1992 Linus Torvalds
* (C) 1992, 1993 Linus Torvalds
*/
#include <linux/segment.h>
#define __STR(x) #x
#define STR(x) __STR(x)
#define SAVE_ALL \
"cld\n\t" \
......@@ -20,10 +24,10 @@
"pushl %edx\n\t" \
"pushl %ecx\n\t" \
"pushl %ebx\n\t" \
"movl $0x10,%edx\n\t" \
"movl $" STR(KERNEL_DS) ",%edx\n\t" \
"mov %dx,%ds\n\t" \
"mov %dx,%es\n\t" \
"movl $0x17,%edx\n\t" \
"movl $" STR(USER_DS) ",%edx\n\t" \
"mov %dx,%fs\n\t"
/*
......@@ -47,7 +51,7 @@
"pushl %eax\n\t" \
"pushl %edx\n\t" \
"pushl %ecx\n\t" \
"movl $0x10,%edx\n\t" \
"movl $" STR(KERNEL_DS) ",%edx\n\t" \
"mov %dx,%ds\n\t" \
"mov %dx,%es\n\t"
......
......@@ -24,17 +24,17 @@ static inline unsigned long get_fs_long(const unsigned long *addr)
static inline void put_fs_byte(char val,char *addr)
{
__asm__ ("movb %0,%%fs:%1"::"q" (val),"m" (*addr));
__asm__ ("movb %0,%%fs:%1"::"iq" (val),"m" (*addr));
}
static inline void put_fs_word(short val,short * addr)
{
__asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr));
__asm__ ("movw %0,%%fs:%1"::"ir" (val),"m" (*addr));
}
static inline void put_fs_long(unsigned long val,unsigned long * addr)
{
__asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
__asm__ ("movl %0,%%fs:%1"::"ir" (val),"m" (*addr));
}
static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
......
#ifndef __ASM_SYSTEM_H
#define __ASM_SYSTEM_H
#include <linux/segment.h>
#define move_to_user_mode() \
__asm__ __volatile__ ("movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \
"pushl %0\n\t" \
"pushl %%eax\n\t" \
"pushfl\n\t" \
"pushl $0x0f\n\t" \
"pushl %1\n\t" \
"pushl $1f\n\t" \
"iret\n" \
"1:\tmovl $0x17,%%eax\n\t" \
"1:\tmovl %0,%%eax\n\t" \
"mov %%ax,%%ds\n\t" \
"mov %%ax,%%es\n\t" \
"mov %%ax,%%fs\n\t" \
"mov %%ax,%%gs" \
:::"ax")
::"i" (USER_DS), "i" (USER_CS):"ax")
#define sti() __asm__ __volatile__ ("sti"::)
#define cli() __asm__ __volatile__ ("cli"::)
#define sti() __asm__ __volatile__ ("sti":::"memory")
#define cli() __asm__ __volatile__ ("cli":::"memory")
#define nop() __asm__ __volatile__ ("nop"::)
extern inline int tas(char * m)
......@@ -29,22 +31,22 @@ extern inline int tas(char * m)
}
#define save_flags(x) \
__asm__ __volatile__("pushfl ; popl %0":"=r" (x))
__asm__ __volatile__("pushfl ; popl %0":"=r" (x)::"memory")
#define restore_flags(x) \
__asm__ __volatile__("pushl %0 ; popfl"::"r" (x))
__asm__ __volatile__("pushl %0 ; popfl"::"r" (x):"memory")
#define iret() __asm__ __volatile__ ("iret"::)
#define iret() __asm__ __volatile__ ("iret":::"memory")
#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
"movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \
"movl %%edx,%2" \
:: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
"m" (*((char *) (gate_addr))), \
"m" (*(4+(char *) (gate_addr))), \
"d" ((char *) (addr)),"a" (0x00080000) \
"movw %2,%%dx\n\t" \
"movl %%eax,%0\n\t" \
"movl %%edx,%1" \
:"=m" (*((long *) (gate_addr))), \
"=m" (*(1+(long *) (gate_addr))) \
:"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
"d" ((char *) (addr)),"a" (KERNEL_CS << 16) \
:"ax","dx")
#define set_intr_gate(n,addr) \
......@@ -56,6 +58,9 @@ __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
#define set_system_gate(n,addr) \
_set_gate(&idt[n],15,3,addr)
#define set_call_gate(a,addr) \
_set_gate(a,12,3,addr)
#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
*(gate_addr) = ((base) & 0xff000000) | \
(((base) & 0x00ff0000)>>16) | \
......
......@@ -19,6 +19,10 @@
#define UTS_MACHINE "i386" /* hardware type */
#endif
#ifndef UTS_DOMAINNAME
#define UTS_DOMAINNAME "(none)" /* set by setdomainname() */
#endif
/*
* The definitions for UTS_RELEASE and UTS_VERSION are now defined
* in linux/version.h, and should only be used by linux/version.c
......
/*
* ddi.h Define the structure for linking in I/O drivers into the
* operating system kernel. This method is currently only
* used by NET layer drivers, but it will be expanded into
* a link methos for ALL kernel-resident device drivers.
*
* Version: @(#)ddi.h 1.0.2 04/22/93
*
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*/
#ifndef _LINUX_DDI_H
#define _LINUX_DDI_H
/* DDI control block flags. */
#define DDI_FREADY 0x10000000 /* device is initialized */
#define DDI_FPRESENT 0x20000000 /* device hardware is present */
#define DDI_FBLKDEV 0x00000001 /* device has a BLK spec. file */
#define DDI_FCHRDEV 0x00000002 /* device has a CHR spec. file */
/* Various constants. */
#define DDI_MAXNAME 16 /* length of a DDI ID string */
/* This structure is used to set up a DDI driver. */
struct ddconf {
int ioaddr; /* main I/O (port) address */
int ioaux; /* auxiliary I/O (HD, AST) */
int irq; /* IRQ channel */
int dma; /* DMA channel to use */
unsigned long memsize; /* size of onboard memory */
unsigned long memaddr; /* base address of memory */
};
/* The DDI device control block. */
struct ddi_device {
char *title; /* title of the driver */
char name[DDI_MAXNAME]; /* unit name of the I/O driver */
short int unit; /* unit number of this driver */
short int nunits; /* number of units in driver */
int (*init)(struct ddi_device *); /* initialization func */
int (*handler)(int, ...); /* command handler */
short int major; /* driver major dev number */
short int minor; /* driver minor dev number */
unsigned long flags; /* various flags */
struct ddconf config; /* driver HW setup */
};
/* This structure is used to set up networking protocols. */
struct ddi_proto {
char *name; /* protocol name */
void (*init)(struct ddi_proto *); /* initialization func */
};
/* This structure is used to link a STREAMS interface. */
struct iflink {
char id[DDI_MAXNAME]; /* DDI ID string */
char stream[DDI_MAXNAME]; /* STREAMS interface name */
int family; /* address (protocol) family */
unsigned int flags; /* any flags needed (unused) */
};
/* DDI control requests. */
#define DDIOCSDBG 0x9000 /* set DDI debug level */
#define DDIOCGNAME 0x9001 /* get DDI ID name */
#define DDIOCGCONF 0x9002 /* get DDI HW config */
#define DDIOCSCONF 0x9003 /* set DDI HW config */
/* DDI global functions. */
extern void ddi_init(void);
extern struct ddi_device *ddi_map(const char *id);
#endif /* _LINUX_DDI_H */
......@@ -28,14 +28,16 @@
/*
* The second extended file system version
*/
#define EXT2FS_VERSION "0.3, 93/04/22"
#define EXT2FS_DATE "93/06/06"
#define EXT2FS_VERSION "0.3a"
/*
* Special inodes numbers
*/
#define EXT2_BAD_INO 1 /* Bad blocks inode */
#define EXT2_ROOT_INO 2 /* Root inode */
#define EXT2_ACL_INO 3 /* ACL inode */
#define EXT2_ACL_IDX_INO 3 /* ACL inode */
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
#define EXT2_FIRST_INO 11 /* First non reserved inode */
/*
......@@ -55,14 +57,14 @@
#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
#ifdef KERNEL
#ifdef __KERNEL__
# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
#else
# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
#endif
#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (unsigned long))
#ifdef KERNEL
#ifdef __KERNEL__
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->u.ext2_sb.s_log_block_size + 10)
#else
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
......@@ -75,7 +77,7 @@
#define EXT2_MIN_FRAG_SIZE 1024
#define EXT2_MAX_FRAG_SIZE 1024
#define EXT2_MIN_FRAG_LOG_SIZE 10
#ifdef KERNEL
#ifdef __KERNEL__
# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
#else
......@@ -86,22 +88,21 @@
/*
* ACL structures
*/
struct ext2_acl_header /* Header of Access Control Lists */
{
unsigned long aclh_size;
unsigned long aclh_file_count;
unsigned long aclh_acle_count;
unsigned long aclh_first_acle;
unsigned long aclh_reserved;
};
struct ext2_acl_entry /* Access Control List Entry */
{
unsigned long acle_size;
unsigned short acle_perms; /* Access permissions */
unsigned short acle_type; /* Type of entry */
unsigned short acle_tag; /* User or group identity */
unsigned short acle_pad1;
unsigned long acle_reserved;
unsigned long acle_next; /* Pointer on next entry for the */
/* same inode or on next free entry */
};
......@@ -133,7 +134,7 @@ struct ext2_group_desc
/*
* Macro-instructions used to manage group descriptors
*/
#ifdef KERNEL
#ifdef __KERNEL__
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
......@@ -259,6 +260,9 @@ extern int ext2_check_dir_entry (char *, struct inode *,
extern int ext2_read (struct inode *, struct file *, char *, int);
extern int ext2_write (struct inode *, struct file *, char *, int);
/* fsync.c */
extern int ext2_sync_file(struct inode *, struct file *);
/* ialloc.c */
extern struct inode * ext2_new_inode (const struct inode *, int);
extern void ext2_free_inode (struct inode *);
......@@ -272,11 +276,13 @@ extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
extern void ext2_put_super (struct super_block *);
extern void ext2_write_super (struct super_block *);
extern int ext2_remount (struct super_block *, int *);
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
extern void ext2_read_inode (struct inode *);
extern void ext2_write_inode (struct inode *);
extern void ext2_put_inode (struct inode *);
extern void ext2_statfs (struct super_block *, struct statfs *);
extern int ext2_sync_inode(struct inode *);
/* ioctl.c */
extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
......
#ifndef _EXT2_FS_SB
#define _EXT2_FS_SB
#define EXT2_MAX_GROUP_DESC 4
#define EXT2_MAX_GROUP_DESC 8
#define EXT2_MAX_GROUP_LOADED 8
/*
......
......@@ -94,6 +94,8 @@ extern void ext_read_inode(struct inode *);
extern void ext_write_inode(struct inode *);
extern void ext_put_inode(struct inode *);
extern void ext_statfs(struct super_block *, struct statfs *);
extern int ext_sync_inode(struct inode *);
extern int ext_sync_file(struct inode *, struct file *);
extern int ext_lseek(struct inode *, struct file *, off_t, int);
extern int ext_read(struct inode *, struct file *, char *, int);
......
......@@ -20,7 +20,7 @@
#define F_SETFD 2 /* set f_flags */
#define F_GETFL 3 /* more flags (cloexec) */
#define F_SETFL 4
#define F_GETLK 5 /* not implemented */
#define F_GETLK 5
#define F_SETLK 6
#define F_SETLKW 7
......
......@@ -6,12 +6,6 @@
* Handbook", Sanches and Canton.
*/
extern int ticks_to_floppy_on(unsigned int nr);
extern void floppy_on(unsigned int nr);
extern void floppy_off(unsigned int nr);
extern void floppy_select(unsigned int nr);
extern void floppy_deselect(unsigned int nr);
/* Fd controller regs. S&C, about page 340 */
#define FD_STATUS 0x3f4
#define FD_DATA 0x3f5
......
......@@ -21,12 +21,13 @@
* recompiled to take full advantage of the new limits..
*/
#undef NR_OPEN
#define NR_OPEN 256 /* don't change - fd_set etc depend on this */
#define NR_OPEN 256
#define NR_INODE 256 /* this should be bigger than NR_FILE */
#define NR_FILE 128 /* this can well be larger on a larger system */
#define NR_SUPER 16
#define NR_INODE 2048 /* this should be bigger than NR_FILE */
#define NR_FILE 1024 /* this can well be larger on a larger system */
#define NR_SUPER 32
#define NR_HASH 997
#define NR_IHASH 131
#define NR_FILE_LOCKS 32
#define BLOCK_SIZE 1024
#define BLOCK_SIZE_BITS 10
......@@ -146,6 +147,7 @@ struct buffer_head {
unsigned char b_uptodate;
unsigned char b_dirt; /* 0-clean,1-dirty */
unsigned char b_lock; /* 0 - ok, 1 -locked */
unsigned char b_req; /* 0 if the buffer has been invalidated */
struct wait_queue * b_wait;
struct buffer_head * b_prev; /* doubly linked list of hash-queue */
struct buffer_head * b_next;
......@@ -213,6 +215,7 @@ struct file {
unsigned short f_flags;
unsigned short f_count;
unsigned short f_reada;
struct file *f_next, *f_prev;
struct inode * f_inode;
struct file_operations * f_op;
};
......@@ -298,6 +301,7 @@ struct super_operations {
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
void (*statfs) (struct super_block *, struct statfs *);
int (*remount_fs) (struct super_block *, int *);
};
struct file_system_type {
......@@ -325,8 +329,10 @@ extern struct file_system_type *get_fs_type(char *name);
extern int fs_may_mount(dev_t dev);
extern int fs_may_umount(dev_t dev, struct inode * mount_root);
extern int fs_may_remount_ro(dev_t dev);
extern struct file file_table[NR_FILE];
extern struct file *first_file;
extern int nr_files;
extern struct super_block super_block[NR_SUPER];
extern void grow_buffers(int size);
......@@ -340,11 +346,9 @@ extern void check_disk_change(dev_t dev);
extern void invalidate_inodes(dev_t dev);
extern void invalidate_buffers(dev_t dev);
extern int floppy_change(struct buffer_head * first_block);
extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev);
extern void sync_inodes(dev_t dev);
extern void sync_dev(dev_t dev);
extern int fsync_dev(dev_t dev);
extern void sync_supers(dev_t dev);
extern int bmap(struct inode * inode,int block);
extern int notify_change(int flags, struct inode * inode);
......@@ -357,6 +361,7 @@ extern int do_mknod(const char * filename, int mode, dev_t dev);
extern void iput(struct inode * inode);
extern struct inode * iget(struct super_block * sb,int nr);
extern struct inode * get_empty_inode(void);
extern void insert_inode_hash(struct inode *);
extern void clear_inode(struct inode *);
extern struct inode * get_pipe_inode(void);
extern struct file * get_empty_filp(void);
......@@ -381,4 +386,7 @@ extern int read_ahead[];
extern int char_write(struct inode *, struct file *, char *, int);
extern int block_write(struct inode *, struct file *, char *, int);
extern int block_fsync(struct inode *, struct file *);
extern int file_fsync(struct inode *, struct file *);
#endif
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the ICMP protocol.
*
* Version: @(#)icmp.h 1.0.3 04/28/93
*
* Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* 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 Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _LINUX_ICMP_H
#define _LINUX_ICMP_H
#define ICMP_ECHOREPLY 0 /* Echo Reply */
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
#define ICMP_REDIRECT 5 /* Redirect (change route) */
#define ICMP_ECHO 8 /* Echo Request */
#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
#define ICMP_PARAMETERPROB 12 /* Parameter Problem */
#define ICMP_TIMESTAMP 13 /* Timestamp Request */
#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
#define ICMP_INFO_REQUEST 15 /* Information Request */
#define ICMP_INFO_REPLY 16 /* Information Reply */
#define ICMP_ADDRESS 17 /* Address Mask Request */
#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */
/* Codes for UNREACH. */
#define ICMP_NET_UNREACH 0 /* Network Unreachable */
#define ICMP_HOST_UNREACH 1 /* Host Unreachable */
#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
#define ICMP_PORT_UNREACH 3 /* Port Unreachable */
#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
#define ICMP_SR_FAILED 5 /* Source Route failed */
#define ICMP_NET_UNKNOWN 6
#define ICMP_HOST_UNKNOWN 7
#define ICMP_HOST_ISOLATED 8
#define ICMP_NET_ANO 9
#define ICMP_HOST_ANO 10
#define ICMP_NET_UNR_TOS 11
#define ICMP_HOST_UNR_TOS 12
/* Codes for REDIRECT. */
#define ICMP_REDIR_NET 0 /* Redirect Net */
#define ICMP_REDIR_HOST 1 /* Redirect Host */
#define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */
#define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */
/* Codes for TIME_EXCEEDED. */
#define ICMP_EXC_TTL 0 /* TTL count exceeded */
#define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */
struct icmphdr {
unsigned char type;
unsigned char code;
unsigned short checksum;
union {
struct {
unsigned short id;
unsigned short sequence;
} echo;
unsigned long gateway;
} un;
};
struct icmp_err {
int errno;
unsigned fatal:1;
};
#endif /* _LINUX_ICMP_H */
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Global definitions for the INET interface module.
*
* Version: @(#)if.h 1.0.2 04/18/93
*
* Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
* Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* 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 Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _LINUX_IF_H
#define _LINUX_IF_H
#include <linux/types.h> /* for "caddr_t" et al */
#include <linux/socket.h> /* for "struct sockaddr" et al */
/* Structure defining a queue for a network interface. */
struct ifnet {
char *if_name; /* name, e.g. ``en'' or ``lo'' */
short if_unit; /* sub-unit for device driver */
short if_mtu; /* maximum transmission unit */
short if_flags; /* up/down, broadcast, etc. */
short if_timer; /* time 'til if_watchdog called */
int if_metric; /* routing metric (not used) */
struct ifaddr *if_addrlist; /* linked list of addrs per if */
struct ifqueue {
#ifdef not_yet_in_linux
struct mbuf *ifq_head;
struct mbuf *ifq_tail;
int ifq_len;
int ifq_maxlen;
int ifq_drops;
#endif
} if_snd; /* output queue */
/* Procedure handles. */
int (*if_init)(); /* init routine */
int (*if_output)(); /* output routine */
int (*if_ioctl)(); /* ioctl routine */
int (*if_reset)(); /* bus reset routine */
int (*if_watchdog)(); /* timer routine */
/* Generic interface statistics. */
int if_ipackets; /* packets recv'd on interface */
int if_ierrors; /* input errors on interface */
int if_opackets; /* packets sent on interface */
int if_oerrors; /* output errors on interface */
int if_collisions; /* collisions on CSMA i'faces */
/* Linked list: pointer to next interface. */
struct ifnet *if_next;
};
/* Standard interface flags. */
#define IFF_UP 0x1 /* interface is up */
#define IFF_BROADCAST 0x2 /* broadcast address valid */
#define IFF_DEBUG 0x4 /* turn on debugging */
#define IFF_LOOPBACK 0x8 /* is a loopback net */
#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
#define IFF_RUNNING 0x40 /* resources allocated */
#define IFF_NOARP 0x80 /* no ARP protocol */
/* These are not yet used: */
#define IFF_PROMISC 0x100 /* recve all packets */
#define IFF_ALLMULTI 0x200 /* recve all multicast packets */
/*
* The ifaddr structure contains information about one address
* of an interface. They are maintained by the different address
* families, are allocated and attached when an address is set,
* and are linked together so all addresses for an interface can
* be located.
*/
struct ifaddr {
struct sockaddr ifa_addr; /* address of interface */
union {
struct sockaddr ifu_broadaddr;
struct sockaddr ifu_dstaddr;
} ifa_ifu;
struct iface *ifa_ifp; /* back-pointer to interface */
struct ifaddr *ifa_next; /* next address for interface */
};
#define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */
#define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */
/*
* Interface request structure used for socket
* ioctl's. All interface ioctl's must have parameter
* definitions which begin with ifr_name. The
* remainder may be interface specific.
*/
struct ifreq {
#define IFNAMSIZ 16
char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
short ifru_flags;
int ifru_metric;
int ifru_mtu;
caddr_t ifru_data;
} ifr_ifru;
};
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_metric ifr_ifru.ifru_metric /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define ifr_data ifr_ifru.ifru_data /* for use by interface */
/*
* Structure used in SIOCGIFCONF request.
* Used to retrieve interface configuration
* for machine (useful for programs which
* must know all networks accessible).
*/
struct ifconf {
int ifc_len; /* size of buffer */
union {
caddr_t ifcu_buf;
struct ifreq *ifcu_req;
} ifc_ifcu;
};
#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
#define ifc_req ifc_ifcu.ifcu_req /* array of structures */
/* BSD UNIX expects to find these here, so here we go: */
#include <linux/if_arp.h>
#include <linux/route.h>
#endif /* _NET_IF_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -166,7 +166,7 @@ typedef char scrnmap_t;
struct kbentry {
u_char kb_table;
u_char kb_index;
u_char kb_value;
u_short kb_value;
};
#define K_NORMTAB 0x00
#define K_SHIFTTAB 0x01
......
This diff is collapsed.
......@@ -104,6 +104,8 @@ extern void minix_read_inode(struct inode *);
extern void minix_write_inode(struct inode *);
extern void minix_put_inode(struct inode *);
extern void minix_statfs(struct super_block *, struct statfs *);
extern int minix_sync_inode(struct inode *);
extern int minix_sync_file(struct inode *, struct file *);
extern struct inode_operations minix_file_inode_operations;
extern struct inode_operations minix_dir_inode_operations;
......
This diff is collapsed.
......@@ -133,7 +133,7 @@ extern int msdos_add_cluster(struct inode *inode);
extern int date_dos2unix(unsigned short time,unsigned short date);
extern void date_unix2dos(int unix_date,unsigned short *time,
unsigned short *date);
extern int msdos_get_entry(struct inode *dir,int *pos,struct buffer_head **bh,
extern int msdos_get_entry(struct inode *dir,off_t *pos,struct buffer_head **bh,
struct msdos_dir_entry **de);
extern int msdos_scan(struct inode *dir,char *name,struct buffer_head **res_bh,
struct msdos_dir_entry **res_de,int *ino);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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