Commit e6c7a63f authored by Linus Torvalds's avatar Linus Torvalds

[PATCH] Linux-0.95 (March 8, 1992)

This was the first kernel that got released under the GPL (0.12 had a
time-lapse to make sure the people involved accepted the license change:
nobody ever complained).

Because 0.12 had been so successful, this was supposed to be closer to
1.0.  Yeah, right.  1.0 was eventually released almost exactly two years
later..

The big change here is the first signs of a real VFS layer: while the
only available filesystem is still the Minix-compatible one, the code is
factored out, and the Minix-specific stuff is put in its own directory.
You can clearly see how the thing is moving towards having multiple
different filesystems.

The VFS changes also cause cleanups in various drivers, since we end
up having more clear inode operation structure pointer handling.

Superblock handling is still minix-specific..

NOTE! We also have /bin/init finally.  It still falls through to the old
"run shells forever" case if no init can be found, but it's starting to
look a whole more like real UNIX user-land now..

New developers: Ross Biro shows up, and does ptrace.  He will later end
up doing the first-generation networking code.

Other changes:

 - UK and Danish keyboard maps (and the keyboard driver supported
   "Application mode" keys from vt100+)
 - Make sure interrupts clear the 'D'irection flag
 - Floppy driver gets track buffer, which speeds it up immensely.  This
   was done based on patches by Lawrence Foard (entropy@wintermute.wpi.edu)
 - Lots of buffer cache cleanups.
 - support nonblocking pipe file descriptors
 - recursive symlink support
 - sys_swapon() means that we don't have to select the swap device
   at build (or boot) time ("Written 01/25/92 by Simmule Turner, heavily
   changed by Linus")
 - start some generic timer work (ugh, but these first timers were
   _horrible_ hardcoded things)
 - ptrace for debugging
 - console size query support with TIOC[G|S]WINSZ
 - /dev/kmem ("by Damiano")
 - rebooting (with ctrl-alt-del or sys_reboot()).

From the release notes:

              New features of 0.95, in order of appearance
                      (ie in the order you see them)

      Init/login

Yeah, thanks to poe (Peter Orbaeck (sp?)), linux now boots up like a
real unix with a login-prompt.  Login as root (no passwd), and change
your /etc/passwd to your hearts delight (and add other logins in
/etc/inittab etc).

      Bash is even bigger

It's really a bummer to boot up from floppies: bash takes a long time to
load.  Bash is also now so big that I couldn't fit compress and tar onto
the root-floppy: You'll probably want the old rootimage-0.12 just in
order to get tar+compress onto your harddisk.  If anybody has pointers
to a simple shell that is freely distributable, it might be a good idea
to use that for the root-diskette.

Especially with a small buffer-cache, things aren't fun. Don't worry:
linux runs much better on a harddisk.

      Virtual consoles on any (?) hardware.

You can select one of several consoles by pressing the left alt-key and
a function key at the same time. Linux should report the number of
virtual consoles available upon bootup. /dev/tty0 is now "the current"
screen, /dev/tty1 is the main console, and /dev/tty2-8 can exist
depending on your text-mode or card.

The virtual consoles also have some new screen-handling commands: they
confirm even better to vt200 control codes than 0.11. Special graphic
characters etc: you can well use them as terminals to VMS (although
that's a shameful waste of resources), and the PF1-4 keys work somewhat
in the application-key mode.

      Symbolic links.

0.95 now allows symlinks to point to other symlinks etc (the maximum
depth is a rather arbitrary 5 links). 0.12 didn't like more than one
level of indirection.

      Virtual memory.

VM under 0.95 should be better than under 0.12: no more lockups (as far
as I have seen), and you can now swap to the filesystem as well as to a
special partition. There are two programs to handle this: mkswap to set
up a swap-file/partition and swapon to start up swapping.

mkswap needs either a partition or a file that already exists to make a
swap-area. To make a swap-file, do this:

      # dd bs=1024 count=NN if=/dev/hda of=swapfile
      # mkswap swapfile NN

The first command just makes a file that is NN blocks long (initializing
it from /dev/hda, but that could be anything). The second command then
writes the necessary setup-info into the file. To start swapping, write

      # swapon swapfile

NOTE! 'dd' isn't on the rootdisk: you have to install some things onto
the harddisk before you can get up and running.

NOTE2! When linux runs totally out of virtual memory, things slow down
dramatically. It tries to keep on running as long as it can, but at
least it shouldn't lock up any more. ^C should work, although you might
have to wait a while for it..

      Faster floppies

Ok, you don't notice this much when booting up from a floppy: bash has
grown, so it takes longer to load, and the optimizations work mostly
with sequential accesses.  When you start un-taring floppies to get the
programs onto your harddisk, you'll notice that it's much faster now.
That should be about the only use for floppies under a unix: nobody in
their right mind uses floppies as filesystems.

      Better FS-independence

Hopefully you'll never even notice this, but the filesystem has been
partly rewritten to make it less minix-fs-specific. I haven't
implemented all the VFS-patches I got, so it's still not ready, but it's
getting there, slowly.

      And that's it, I think.

Happy hacking.

                      Linus (torvalds@kruuna.helsinki.fi)
parent 2ab763b2
...@@ -2,31 +2,30 @@ ...@@ -2,31 +2,30 @@
# if you want the ram-disk device, define this to be the # if you want the ram-disk device, define this to be the
# size in blocks. # size in blocks.
# #
RAMDISK = #-DRAMDISK=512 #RAMDISK = -DRAMDISK=512
AS86 =as86 -0 -a AS86 =as86 -0 -a
LD86 =ld86 -0 LD86 =ld86 -0
AS =gas AS =as
LD =gld LD =ld
LDFLAGS =-s -x -M LDFLAGS =-s -x -M
CC =gcc $(RAMDISK) CC =gcc $(RAMDISK)
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \ CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer
-fcombine-regs -mstring-insns
CPP =cpp -nostdinc -Iinclude CPP =cpp -nostdinc -Iinclude
# #
# ROOT_DEV specifies the default root-device when making the image. # ROOT_DEV specifies the default root-device when making the image.
# This can be either FLOPPY, /dev/xxxx or empty, in which case the # This can be either FLOPPY, /dev/xxxx or empty, in which case the
# default of /dev/hd6 is used by 'build'. # default of FLOPPY is used by 'build'.
# #
ROOT_DEV=/dev/hd6 ROOT_DEV=/dev/hdb1
SWAP_DEV=/dev/hd2
ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o
DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a FILESYSTEMS =fs/minix/minix.o
MATH =kernel/math/math.a DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
LIBS =lib/lib.a MATH =kernel/math/math.a
LIBS =lib/lib.a
.c.s: .c.s:
$(CC) $(CFLAGS) \ $(CC) $(CFLAGS) \
...@@ -40,8 +39,7 @@ LIBS =lib/lib.a ...@@ -40,8 +39,7 @@ LIBS =lib/lib.a
all: Image all: Image
Image: boot/bootsect boot/setup tools/system tools/build Image: boot/bootsect boot/setup tools/system tools/build
tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) \ tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) > Image
$(SWAP_DEV) > Image
sync sync
disk: Image disk: Image
...@@ -54,9 +52,10 @@ tools/build: tools/build.c ...@@ -54,9 +52,10 @@ tools/build: tools/build.c
boot/head.o: boot/head.s boot/head.o: boot/head.s
tools/system: boot/head.o init/main.o \ tools/system: boot/head.o init/main.o \
$(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS) $(ARCHIVES) $(FILESYSTEMS) $(DRIVERS) $(MATH) $(LIBS)
$(LD) $(LDFLAGS) boot/head.o init/main.o \ $(LD) $(LDFLAGS) boot/head.o init/main.o \
$(ARCHIVES) \ $(ARCHIVES) \
$(FILESYSTEMS) \
$(DRIVERS) \ $(DRIVERS) \
$(MATH) \ $(MATH) \
$(LIBS) \ $(LIBS) \
...@@ -80,6 +79,9 @@ mm/mm.o: ...@@ -80,6 +79,9 @@ mm/mm.o:
fs/fs.o: fs/fs.o:
(cd fs; make) (cd fs; make)
fs/minix/minix.o:
(cd fs/minix; make)
lib/lib.a: lib/lib.a:
(cd lib; make) (cd lib; make)
...@@ -99,7 +101,7 @@ boot/bootsect: boot/bootsect.s ...@@ -99,7 +101,7 @@ boot/bootsect: boot/bootsect.s
clean: clean:
rm -f Image System.map tmp_make core boot/bootsect boot/setup \ rm -f Image System.map tmp_make core boot/bootsect boot/setup \
boot/bootsect.s boot/setup.s boot/bootsect.s boot/setup.s init/main.s
rm -f init/*.o tools/system tools/build boot/*.o rm -f init/*.o tools/system tools/build boot/*.o
(cd mm;make clean) (cd mm;make clean)
(cd fs;make clean) (cd fs;make clean)
......
...@@ -53,6 +53,7 @@ start: ...@@ -53,6 +53,7 @@ start:
mov cx,#256 mov cx,#256
sub si,si sub si,si
sub di,di sub di,di
cld
rep rep
movw movw
jmpi go,INITSEG jmpi go,INITSEG
...@@ -83,7 +84,6 @@ go: mov ax,cs ...@@ -83,7 +84,6 @@ go: mov ax,cs
* fs = 0, gs = parameter table segment * fs = 0, gs = parameter table segment
*/ */
push #0 push #0
pop fs pop fs
mov bx,#0x78 ! fs:bx is parameter table address mov bx,#0x78 ! fs:bx is parameter table address
......
...@@ -12,9 +12,10 @@ ...@@ -12,9 +12,10 @@
* the page directory. * the page directory.
*/ */
.text .text
.globl _idt,_gdt,_pg_dir,_tmp_floppy_area .globl _idt,_gdt,_pg_dir,_tmp_floppy_area,_floppy_track_buffer
_pg_dir: _pg_dir:
startup_32: startup_32:
cld
movl $0x10,%eax movl $0x10,%eax
mov %ax,%ds mov %ax,%ds
mov %ax,%es mov %ax,%es
...@@ -34,17 +35,39 @@ startup_32: ...@@ -34,17 +35,39 @@ startup_32:
movl %eax,0x000000 # loop forever if it isn't movl %eax,0x000000 # loop forever if it isn't
cmpl %eax,0x100000 cmpl %eax,0x100000
je 1b je 1b
/* check if it is 486 or 386. */
movl %esp,%edi # save stack pointer
andl $0xfffffffc,%esp # align stack to avoid AC fault
pushfl # push EFLAGS
popl %eax # get EFLAGS
movl %eax,%ecx # save original EFLAGS
xorl $0x40000,%eax # flip AC bit in EFLAGS
pushl %eax # copy to EFLAGS
popfl # set EFLAGS
pushfl # get new EFLAGS
popl %eax # put it in eax
xorl %ecx,%eax # check if AC bit is changed. zero is 486.
jz 1f # 486
pushl %ecx # restore original EFLAGS
popfl
movl %edi,%esp # restore esp
movl %cr0,%eax # 386
andl $0x80000011,%eax # Save PG,PE,ET
orl $2,%eax # set MP
jmp 2f
/* /*
* NOTE! 486 should set bit 16, to check for write-protect in supervisor * NOTE! 486 should set bit 16, to check for write-protect in supervisor
* mode. Then it would be unnecessary with the "verify_area()"-calls. * mode. Then it would be unnecessary with the "verify_area()"-calls.
* 486 users probably want to set the NE (#5) bit also, so as to use * 486 users probably want to set the NE (#5) bit also, so as to use
* int 16 for math errors. * int 16 for math errors.
*/ */
movl %cr0,%eax # check math chip 1: pushl %ecx # restore original EFLAGS
popfl
movl %edi,%esp # restore esp
movl %cr0,%eax # 486
andl $0x80000011,%eax # Save PG,PE,ET andl $0x80000011,%eax # Save PG,PE,ET
/* "orl $0x10020,%eax" here for 486 might be good */ orl $0x10022,%eax # set NE and MP
orl $2,%eax # set MP 2: movl %eax,%cr0
movl %eax,%cr0
call check_x87 call check_x87
jmp after_page_tables jmp after_page_tables
...@@ -55,8 +78,8 @@ check_x87: ...@@ -55,8 +78,8 @@ check_x87:
fninit fninit
fstsw %ax fstsw %ax
cmpb $0,%al cmpb $0,%al
je 1f /* no coprocessor: have to set bits */ je 1f
movl %cr0,%eax movl %cr0,%eax /* no coprocessor: have to set bits */
xorl $6,%eax /* reset MP, set EM */ xorl $6,%eax /* reset MP, set EM */
movl %eax,%cr0 movl %eax,%cr0
ret ret
...@@ -131,14 +154,22 @@ pg3: ...@@ -131,14 +154,22 @@ pg3:
*/ */
_tmp_floppy_area: _tmp_floppy_area:
.fill 1024,1,0 .fill 1024,1,0
/*
* floppy_track_buffer is used to buffer one track of floppy data: it
* has to be separate from the tmp_floppy area, as otherwise a single-
* sector read/write can mess it up. It can contain one full track of
* data (18*2*512 bytes).
*/
_floppy_track_buffer:
.fill 512*2*18,1,0
after_page_tables: after_page_tables:
call setup_paging
pushl $0 # These are the parameters to main :-) pushl $0 # These are the parameters to main :-)
pushl $0 pushl $0
pushl $0 pushl $0
pushl $L6 # return address for main, if it decides to. cld # gcc2 wants the direction flag cleared at all times
pushl $_main call _start_kernel
jmp setup_paging
L6: L6:
jmp L6 # main should never return here, but jmp L6 # main should never return here, but
# just in case, we know what happens. # just in case, we know what happens.
...@@ -148,6 +179,7 @@ int_msg: ...@@ -148,6 +179,7 @@ int_msg:
.asciz "Unknown interrupt\n\r" .asciz "Unknown interrupt\n\r"
.align 2 .align 2
ignore_int: ignore_int:
cld
pushl %eax pushl %eax
pushl %ecx pushl %ecx
pushl %edx pushl %edx
...@@ -210,6 +242,7 @@ setup_paging: ...@@ -210,6 +242,7 @@ setup_paging:
1: stosl /* fill pages backwards - more efficient :-) */ 1: stosl /* fill pages backwards - more efficient :-) */
subl $0x1000,%eax subl $0x1000,%eax
jge 1b jge 1b
cld
xorl %eax,%eax /* pg_dir is at 0x0000 */ xorl %eax,%eax /* pg_dir is at 0x0000 */
movl %eax,%cr3 /* cr3 - page directory start */ movl %eax,%cr3 /* cr3 - page directory start */
movl %cr0,%eax movl %cr0,%eax
......
...@@ -77,6 +77,7 @@ novga: mov [14],ax ...@@ -77,6 +77,7 @@ novga: mov [14],ax
mov es,ax mov es,ax
mov di,#0x0080 mov di,#0x0080
mov cx,#0x10 mov cx,#0x10
cld
rep rep
movsb movsb
...@@ -89,6 +90,7 @@ novga: mov [14],ax ...@@ -89,6 +90,7 @@ novga: mov [14],ax
mov es,ax mov es,ax
mov di,#0x0090 mov di,#0x0090
mov cx,#0x10 mov cx,#0x10
cld
rep rep
movsb movsb
...@@ -106,6 +108,7 @@ no_disk1: ...@@ -106,6 +108,7 @@ no_disk1:
mov di,#0x0090 mov di,#0x0090
mov cx,#0x10 mov cx,#0x10
mov ax,#0x00 mov ax,#0x00
cld
rep rep
stosb stosb
is_disk1: is_disk1:
...@@ -220,6 +223,10 @@ chsvga: cld ...@@ -220,6 +223,10 @@ chsvga: cld
mov es,ax mov es,ax
lea si,msg1 lea si,msg1
call prtstr call prtstr
flush: in al,#0x60 ! Flush the keyboard buffer
cmp al,#0x82
jb nokey
jmp flush
nokey: in al,#0x60 nokey: in al,#0x60
cmp al,#0x82 cmp al,#0x82
jb nokey jb nokey
...@@ -230,7 +237,8 @@ nokey: in al,#0x60 ...@@ -230,7 +237,8 @@ nokey: in al,#0x60
mov ax,#0x5019 mov ax,#0x5019
pop ds pop ds
ret ret
svga: lea si,idati ! Check ATI 'clues' svga: cld
lea si,idati ! Check ATI 'clues'
mov di,#0x31 mov di,#0x31
mov cx,#0x09 mov cx,#0x09
repe repe
...@@ -354,7 +362,8 @@ l1: inc si ...@@ -354,7 +362,8 @@ l1: inc si
lea di,mogenoa lea di,mogenoa
lea cx,selmod lea cx,selmod
jmp cx jmp cx
nogen: lea si,idparadise ! Check Paradise 'clues' nogen: cld
lea si,idparadise ! Check Paradise 'clues'
mov di,#0x7d mov di,#0x7d
mov cx,#0x04 mov cx,#0x04
repe repe
......
AR =gar AR =ar
AS =gas AS =as
CC =gcc CC =gcc
LD =gld LD =ld
CFLAGS =-Wall -O -fstrength-reduce -fcombine-regs -fomit-frame-pointer \ CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
-fno-defer-pop -mstring-insns -nostdinc -I../include -fno-defer-pop -nostdinc -I../include
CPP =gcc -E -nostdinc -I../include CPP =gcc -E -nostdinc -I../include
.c.s: .c.s:
...@@ -16,8 +16,8 @@ CPP =gcc -E -nostdinc -I../include ...@@ -16,8 +16,8 @@ CPP =gcc -E -nostdinc -I../include
$(AS) -o $*.o $< $(AS) -o $*.o $<
OBJS= open.o read_write.o inode.o file_table.o buffer.o super.o \ OBJS= open.o read_write.o inode.o file_table.o buffer.o super.o \
block_dev.o char_dev.o file_dev.o stat.o exec.o pipe.o namei.o \ block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
bitmap.o fcntl.o ioctl.o truncate.o select.o fcntl.o ioctl.o select.o
fs.o: $(OBJS) fs.o: $(OBJS)
$(LD) -r -o fs.o $(OBJS) $(LD) -r -o fs.o $(OBJS)
...@@ -25,18 +25,15 @@ fs.o: $(OBJS) ...@@ -25,18 +25,15 @@ fs.o: $(OBJS)
clean: clean:
rm -f core *.o *.a tmp_make rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done for i in *.c;do rm -f `basename $$i .c`.s;done
cd minix; make clean
dep: dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do $(CPP) -M $$i;done) >> tmp_make (for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile cp tmp_make Makefile
cd minix; make dep
### Dependencies: ### Dependencies:
bitmap.o : bitmap.c ../include/string.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
../include/sys/param.h ../include/sys/time.h ../include/time.h \
../include/sys/resource.h
block_dev.o : block_dev.c ../include/errno.h ../include/linux/sched.h \ block_dev.o : block_dev.c ../include/errno.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \ ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
...@@ -65,17 +62,13 @@ fcntl.o : fcntl.c ../include/string.h ../include/errno.h \ ...@@ -65,17 +62,13 @@ fcntl.o : fcntl.c ../include/string.h ../include/errno.h \
../include/signal.h ../include/sys/param.h ../include/sys/time.h \ ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/asm/segment.h \ ../include/time.h ../include/sys/resource.h ../include/asm/segment.h \
../include/fcntl.h ../include/sys/stat.h ../include/fcntl.h ../include/sys/stat.h
file_dev.o : file_dev.c ../include/errno.h ../include/fcntl.h \
../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/linux/mm.h ../include/linux/kernel.h \
../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/asm/segment.h
file_table.o : file_table.c ../include/linux/fs.h ../include/sys/types.h file_table.o : file_table.c ../include/linux/fs.h ../include/sys/types.h
inode.o : inode.c ../include/string.h ../include/sys/stat.h \ inode.o : inode.c ../include/string.h ../include/sys/stat.h \
../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \ ../include/sys/types.h ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/linux/mm.h ../include/linux/kernel.h \ ../include/linux/fs.h ../include/linux/mm.h ../include/linux/kernel.h \
../include/signal.h ../include/sys/param.h ../include/sys/time.h \ ../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/asm/system.h ../include/time.h ../include/sys/resource.h ../include/linux/minix_fs.h \
../include/asm/system.h
ioctl.o : ioctl.c ../include/string.h ../include/errno.h \ ioctl.o : ioctl.c ../include/string.h ../include/errno.h \
../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \ ../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \ ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
...@@ -85,20 +78,21 @@ namei.o : namei.c ../include/linux/sched.h ../include/linux/head.h \ ...@@ -85,20 +78,21 @@ namei.o : namei.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \ ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \ ../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
../include/sys/time.h ../include/time.h ../include/sys/resource.h \ ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
../include/asm/segment.h ../include/string.h ../include/fcntl.h \ ../include/linux/minix_fs.h ../include/asm/segment.h ../include/string.h \
../include/errno.h ../include/const.h ../include/sys/stat.h ../include/fcntl.h ../include/errno.h ../include/const.h \
../include/sys/stat.h
open.o : open.c ../include/string.h ../include/errno.h ../include/fcntl.h \ open.o : open.c ../include/string.h ../include/errno.h ../include/fcntl.h \
../include/sys/types.h ../include/utime.h ../include/sys/stat.h \ ../include/sys/types.h ../include/utime.h ../include/sys/stat.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \ ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
../include/sys/param.h ../include/sys/time.h ../include/time.h \ ../include/sys/param.h ../include/sys/time.h ../include/time.h \
../include/sys/resource.h ../include/linux/tty.h ../include/termios.h \ ../include/sys/resource.h ../include/asm/segment.h
../include/asm/segment.h
pipe.o : pipe.c ../include/signal.h ../include/sys/types.h \ pipe.o : pipe.c ../include/signal.h ../include/sys/types.h \
../include/errno.h ../include/termios.h ../include/linux/sched.h \ ../include/errno.h ../include/termios.h ../include/fcntl.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \ ../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/linux/kernel.h ../include/sys/param.h ../include/sys/time.h \ ../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.h \
../include/time.h ../include/sys/resource.h ../include/asm/segment.h ../include/sys/time.h ../include/time.h ../include/sys/resource.h \
../include/asm/segment.h
read_write.o : read_write.c ../include/sys/stat.h ../include/sys/types.h \ read_write.o : read_write.c ../include/sys/stat.h ../include/sys/types.h \
../include/errno.h ../include/linux/kernel.h ../include/linux/sched.h \ ../include/errno.h ../include/linux/kernel.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \ ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
...@@ -120,10 +114,5 @@ super.o : super.c ../include/linux/config.h ../include/linux/sched.h \ ...@@ -120,10 +114,5 @@ super.o : super.c ../include/linux/config.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \ ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \ ../include/linux/mm.h ../include/linux/kernel.h ../include/signal.h \
../include/sys/param.h ../include/sys/time.h ../include/time.h \ ../include/sys/param.h ../include/sys/time.h ../include/time.h \
../include/sys/resource.h ../include/asm/system.h ../include/errno.h \ ../include/sys/resource.h ../include/linux/minix_fs.h \
../include/sys/stat.h ../include/asm/system.h ../include/errno.h ../include/sys/stat.h
truncate.o : truncate.c ../include/linux/sched.h ../include/linux/head.h \
../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/signal.h ../include/sys/param.h \
../include/sys/time.h ../include/time.h ../include/sys/resource.h \
../include/sys/stat.h
...@@ -13,23 +13,25 @@ ...@@ -13,23 +13,25 @@
extern int *blk_size[]; extern int *blk_size[];
int block_write(int dev, long * pos, char * buf, int count) int block_write(struct inode * inode, struct file * filp, char * buf, int count)
{ {
int block = *pos >> BLOCK_SIZE_BITS; int block = filp->f_pos >> BLOCK_SIZE_BITS;
int offset = *pos & (BLOCK_SIZE-1); int offset = filp->f_pos & (BLOCK_SIZE-1);
int chars; int chars;
int written = 0; int written = 0;
int size; int size;
unsigned int dev;
struct buffer_head * bh; struct buffer_head * bh;
register char * p; register char * p;
dev = inode->i_rdev;
if (blk_size[MAJOR(dev)]) if (blk_size[MAJOR(dev)])
size = blk_size[MAJOR(dev)][MINOR(dev)]; size = blk_size[MAJOR(dev)][MINOR(dev)];
else else
size = 0x7fffffff; size = 0x7fffffff;
while (count>0) { while (count>0) {
if (block >= size) if (block >= size)
return written?written:-EIO; return written;
chars = BLOCK_SIZE - offset; chars = BLOCK_SIZE - offset;
if (chars > count) if (chars > count)
chars=count; chars=count;
...@@ -42,7 +44,7 @@ int block_write(int dev, long * pos, char * buf, int count) ...@@ -42,7 +44,7 @@ int block_write(int dev, long * pos, char * buf, int count)
return written?written:-EIO; return written?written:-EIO;
p = offset + bh->b_data; p = offset + bh->b_data;
offset = 0; offset = 0;
*pos += chars; filp->f_pos += chars;
written += chars; written += chars;
count -= chars; count -= chars;
while (chars-->0) while (chars-->0)
...@@ -53,23 +55,25 @@ int block_write(int dev, long * pos, char * buf, int count) ...@@ -53,23 +55,25 @@ int block_write(int dev, long * pos, char * buf, int count)
return written; return written;
} }
int block_read(int dev, unsigned long * pos, char * buf, int count) int block_read(struct inode * inode, struct file * filp, char * buf, int count)
{ {
int block = *pos >> BLOCK_SIZE_BITS; unsigned int block = filp->f_pos >> BLOCK_SIZE_BITS;
int offset = *pos & (BLOCK_SIZE-1); unsigned int offset = filp->f_pos & (BLOCK_SIZE-1);
int chars; unsigned int chars;
int size; unsigned int size;
unsigned int dev;
int read = 0; int read = 0;
struct buffer_head * bh; struct buffer_head * bh;
register char * p; register char * p;
dev = inode->i_rdev;
if (blk_size[MAJOR(dev)]) if (blk_size[MAJOR(dev)])
size = blk_size[MAJOR(dev)][MINOR(dev)]; size = blk_size[MAJOR(dev)][MINOR(dev)];
else else
size = 0x7fffffff; size = 0x7fffffff;
while (count>0) { while (count>0) {
if (block >= size) if (block >= size)
return read?read:-EIO; return read;
chars = BLOCK_SIZE-offset; chars = BLOCK_SIZE-offset;
if (chars > count) if (chars > count)
chars = count; chars = count;
...@@ -78,7 +82,7 @@ int block_read(int dev, unsigned long * pos, char * buf, int count) ...@@ -78,7 +82,7 @@ int block_read(int dev, unsigned long * pos, char * buf, int count)
block++; block++;
p = offset + bh->b_data; p = offset + bh->b_data;
offset = 0; offset = 0;
*pos += chars; filp->f_pos += chars;
read += chars; read += chars;
count -= chars; count -= chars;
while (chars-->0) while (chars-->0)
......
...@@ -41,43 +41,39 @@ static inline void wait_on_buffer(struct buffer_head * bh) ...@@ -41,43 +41,39 @@ static inline void wait_on_buffer(struct buffer_head * bh)
sti(); sti();
} }
int sys_sync(void) static void sync_buffers(int dev)
{ {
int i; int i;
struct buffer_head * bh; struct buffer_head * bh;
sync_inodes(); /* write out inodes into buffers */ bh = free_list;
bh = start_buffer; for (i=0 ; i<NR_BUFFERS ; i++,bh = bh->b_next_free) {
for (i=0 ; i<NR_BUFFERS ; i++,bh++) { #if 0
if (dev && (bh->b_dev != dev))
continue;
#endif
wait_on_buffer(bh); wait_on_buffer(bh);
#if 0
if (dev && (bh->b_dev != dev))
continue;
#endif
if (bh->b_dirt) if (bh->b_dirt)
ll_rw_block(WRITE,bh); ll_rw_block(WRITE,bh);
} }
}
int sys_sync(void)
{
sync_inodes(); /* write out inodes into buffers */
sync_buffers(0);
return 0; return 0;
} }
int sync_dev(int dev) int sync_dev(int dev)
{ {
int i; sync_buffers(dev);
struct buffer_head * bh;
bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
if (bh->b_dev != dev)
continue;
wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_dirt)
ll_rw_block(WRITE,bh);
}
sync_inodes(); sync_inodes();
bh = start_buffer; sync_buffers(dev);
for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
if (bh->b_dev != dev)
continue;
wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_dirt)
ll_rw_block(WRITE,bh);
}
return 0; return 0;
} }
...@@ -128,22 +124,61 @@ void check_disk_change(int dev) ...@@ -128,22 +124,61 @@ void check_disk_change(int dev)
#define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH) #define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
#define hash(dev,block) hash_table[_hashfn(dev,block)] #define hash(dev,block) hash_table[_hashfn(dev,block)]
static inline void remove_from_queues(struct buffer_head * bh) static inline void remove_from_hash_queue(struct buffer_head * bh)
{ {
/* remove from hash-queue */
if (bh->b_next) if (bh->b_next)
bh->b_next->b_prev = bh->b_prev; bh->b_next->b_prev = bh->b_prev;
if (bh->b_prev) if (bh->b_prev)
bh->b_prev->b_next = bh->b_next; bh->b_prev->b_next = bh->b_next;
if (hash(bh->b_dev,bh->b_blocknr) == bh) if (hash(bh->b_dev,bh->b_blocknr) == bh)
hash(bh->b_dev,bh->b_blocknr) = bh->b_next; hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
/* remove from free list */ bh->b_next = bh->b_prev = NULL;
}
static inline void remove_from_free_list(struct buffer_head * bh)
{
if (!(bh->b_prev_free) || !(bh->b_next_free)) if (!(bh->b_prev_free) || !(bh->b_next_free))
panic("Free block list corrupted"); panic("Free block list corrupted");
bh->b_prev_free->b_next_free = bh->b_next_free; bh->b_prev_free->b_next_free = bh->b_next_free;
bh->b_next_free->b_prev_free = bh->b_prev_free; bh->b_next_free->b_prev_free = bh->b_prev_free;
if (free_list == bh) if (free_list == bh)
free_list = bh->b_next_free; free_list = bh->b_next_free;
bh->b_next_free = bh->b_prev_free = NULL;
}
static inline void remove_from_queues(struct buffer_head * bh)
{
remove_from_hash_queue(bh);
remove_from_free_list(bh);
}
static inline void put_first_free(struct buffer_head * bh)
{
if (!bh || (bh == free_list))
return;
remove_from_free_list(bh);
/* add to front of free list */
bh->b_next_free = free_list;
bh->b_prev_free = free_list->b_prev_free;
free_list->b_prev_free->b_next_free = bh;
free_list->b_prev_free = bh;
free_list = bh;
}
static inline void put_last_free(struct buffer_head * bh)
{
if (!bh)
return;
if (bh == free_list) {
free_list = bh->b_next_free;
return;
}
remove_from_free_list(bh);
/* add to back of free list */
bh->b_next_free = free_list;
bh->b_prev_free = free_list->b_prev_free;
free_list->b_prev_free->b_next_free = bh;
free_list->b_prev_free = bh;
} }
static inline void insert_into_queues(struct buffer_head * bh) static inline void insert_into_queues(struct buffer_head * bh)
...@@ -189,8 +224,10 @@ struct buffer_head * get_hash_table(int dev, int block) ...@@ -189,8 +224,10 @@ struct buffer_head * get_hash_table(int dev, int block)
return NULL; return NULL;
bh->b_count++; bh->b_count++;
wait_on_buffer(bh); wait_on_buffer(bh);
if (bh->b_dev == dev && bh->b_blocknr == block) if (bh->b_dev == dev && bh->b_blocknr == block) {
put_last_free(bh);
return bh; return bh;
}
bh->b_count--; bh->b_count--;
} }
} }
...@@ -201,17 +238,23 @@ struct buffer_head * get_hash_table(int dev, int block) ...@@ -201,17 +238,23 @@ struct buffer_head * get_hash_table(int dev, int block)
* so it should be much more efficient than it looks. * so it should be much more efficient than it looks.
* *
* The algoritm is changed: hopefully better, and an elusive bug removed. * The algoritm is changed: hopefully better, and an elusive bug removed.
*
* 14.02.92: changed it to sync dirty buffers a bit: better performance
* when the filesystem starts to get full of dirty blocks (I hope).
*/ */
#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock) #define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
struct buffer_head * getblk(int dev,int block) struct buffer_head * getblk(int dev,int block)
{ {
struct buffer_head * tmp, * bh; struct buffer_head * bh, * tmp;
int buffers;
repeat: repeat:
if (bh = get_hash_table(dev,block)) if (bh = get_hash_table(dev,block))
return bh; return bh;
buffers = NR_BUFFERS;
tmp = free_list; tmp = free_list;
do { do {
tmp = tmp->b_next_free;
if (tmp->b_count) if (tmp->b_count)
continue; continue;
if (!bh || BADNESS(tmp)<BADNESS(bh)) { if (!bh || BADNESS(tmp)<BADNESS(bh)) {
...@@ -219,8 +262,10 @@ struct buffer_head * getblk(int dev,int block) ...@@ -219,8 +262,10 @@ struct buffer_head * getblk(int dev,int block)
if (!BADNESS(tmp)) if (!BADNESS(tmp))
break; break;
} }
if (tmp->b_dirt)
ll_rw_block(WRITEA,tmp);
/* and repeat until we find something good */ /* and repeat until we find something good */
} while ((tmp = tmp->b_next_free) != free_list); } while (buffers--);
if (!bh) { if (!bh) {
sleep_on(&buffer_wait); sleep_on(&buffer_wait);
goto repeat; goto repeat;
...@@ -377,5 +422,5 @@ void buffer_init(long buffer_end) ...@@ -377,5 +422,5 @@ void buffer_init(long buffer_end)
free_list->b_prev_free = h; free_list->b_prev_free = h;
h->b_next_free = free_list; h->b_next_free = free_list;
for (i=0;i<NR_HASH;i++) for (i=0;i<NR_HASH;i++)
hash_table[i]=NULL; hash_table[i] = NULL;
} }
...@@ -13,22 +13,22 @@ ...@@ -13,22 +13,22 @@
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/io.h> #include <asm/io.h>
extern int tty_read(unsigned minor,char * buf,int count); extern int tty_read(unsigned minor,char * buf,int count,unsigned short flags);
extern int tty_write(unsigned minor,char * buf,int count); extern int tty_write(unsigned minor,char * buf,int count);
typedef (*crw_ptr)(int rw,unsigned minor,char * buf,int count,off_t * pos); typedef (*crw_ptr)(int,unsigned,char *,int,off_t *,unsigned short);
static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos) static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos, unsigned short flags)
{ {
return ((rw==READ)?tty_read(minor,buf,count): return ((rw==READ)?tty_read(minor,buf,count,flags):
tty_write(minor,buf,count)); tty_write(minor,buf,count));
} }
static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos) static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos, unsigned short flags)
{ {
if (current->tty<0) if (current->tty<0)
return -EPERM; return -EPERM;
return rw_ttyx(rw,current->tty,buf,count,pos); return rw_ttyx(rw,current->tty,buf,count,pos,flags);
} }
static int rw_ram(int rw,char * buf, int count, off_t *pos) static int rw_ram(int rw,char * buf, int count, off_t *pos)
...@@ -43,7 +43,21 @@ static int rw_mem(int rw,char * buf, int count, off_t * pos) ...@@ -43,7 +43,21 @@ static int rw_mem(int rw,char * buf, int count, off_t * pos)
static int rw_kmem(int rw,char * buf, int count, off_t * pos) static int rw_kmem(int rw,char * buf, int count, off_t * pos)
{ {
return -EIO; /* kmem by Damiano */
int i = *pos; /* Current position where to read */
/* i can go from 0 to LOW_MEM (See include/linux/mm.h */
/* I am not shure about it but it doesn't mem fault :-) */
while ( (count-- > 0) && (i <LOW_MEM) ) {
if (rw==READ)
put_fs_byte( *(char *)i ,buf++);
else
return (-EIO);
i++;
}
i -= *pos; /* Count how many read or write */
*pos += i; /* Update position */
return (i); /* Return number read */
} }
static int rw_port(int rw,char * buf, int count, off_t * pos) static int rw_port(int rw,char * buf, int count, off_t * pos)
...@@ -62,7 +76,8 @@ static int rw_port(int rw,char * buf, int count, off_t * pos) ...@@ -62,7 +76,8 @@ static int rw_port(int rw,char * buf, int count, off_t * pos)
return i; return i;
} }
static int rw_memory(int rw, unsigned minor, char * buf, int count, off_t * pos) static int rw_memory(int rw, unsigned minor, char * buf, int count,
off_t * pos, unsigned short flags)
{ {
switch(minor) { switch(minor) {
case 0: case 0:
...@@ -92,13 +107,30 @@ static crw_ptr crw_table[]={ ...@@ -92,13 +107,30 @@ static crw_ptr crw_table[]={
NULL, /* /dev/lp */ NULL, /* /dev/lp */
NULL}; /* unnamed pipes */ NULL}; /* unnamed pipes */
int rw_char(int rw,int dev, char * buf, int count, off_t * pos) int char_read(struct inode * inode, struct file * filp, char * buf, int count)
{
unsigned int major,minor;
crw_ptr call_addr;
major = MAJOR(inode->i_rdev);
minor = MINOR(inode->i_rdev);
if (major >= NRDEVS)
return -ENODEV;
if (!(call_addr = crw_table[major]))
return -ENODEV;
return call_addr(READ,minor,buf,count,&filp->f_pos,filp->f_flags);
}
int char_write(struct inode * inode, struct file * filp, char * buf, int count)
{ {
unsigned int major,minor;
crw_ptr call_addr; crw_ptr call_addr;
if (MAJOR(dev)>=NRDEVS) major = MAJOR(inode->i_rdev);
minor = MINOR(inode->i_rdev);
if (major >= NRDEVS)
return -ENODEV; return -ENODEV;
if (!(call_addr=crw_table[MAJOR(dev)])) if (!(call_addr=crw_table[major]))
return -ENODEV; return -ENODEV;
return call_addr(rw,MINOR(dev),buf,count,pos); return call_addr(WRITE,minor,buf,count,&filp->f_pos,filp->f_flags);
} }
...@@ -41,7 +41,7 @@ extern int sys_close(int fd); ...@@ -41,7 +41,7 @@ extern int sys_close(int fd);
int sys_uselib(const char * library) int sys_uselib(const char * library)
{ {
struct m_inode * inode; struct inode * inode;
unsigned long base; unsigned long base;
if (get_limit(0x17) != TASK_SIZE) if (get_limit(0x17) != TASK_SIZE)
...@@ -148,7 +148,7 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, ...@@ -148,7 +148,7 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
do { do {
len++; len++;
} while (get_fs_byte(tmp++)); } while (get_fs_byte(tmp++));
if (p-len < 0) { /* this shouldn't happen - 128kB */ if (p < len) { /* this shouldn't happen - 128kB */
set_fs(old_fs); set_fs(old_fs);
return 0; return 0;
} }
...@@ -207,7 +207,7 @@ static unsigned long change_ldt(unsigned long text_size,unsigned long * page) ...@@ -207,7 +207,7 @@ static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
int do_execve(unsigned long * eip,long tmp,char * filename, int do_execve(unsigned long * eip,long tmp,char * filename,
char ** argv, char ** envp) char ** argv, char ** envp)
{ {
struct m_inode * inode; struct inode * inode;
struct buffer_head * bh; struct buffer_head * bh;
struct exec ex; struct exec ex;
unsigned long page[MAX_ARG_PAGES]; unsigned long page[MAX_ARG_PAGES];
...@@ -232,18 +232,24 @@ int do_execve(unsigned long * eip,long tmp,char * filename, ...@@ -232,18 +232,24 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
goto exec_error2; goto exec_error2;
} }
i = inode->i_mode; i = inode->i_mode;
e_uid = (i & S_ISUID) ? inode->i_uid : current->euid; /* make sure we don't let suid, sgid files be ptraced. */
e_gid = (i & S_ISGID) ? inode->i_gid : current->egid; if (current->flags & PF_PTRACED) {
e_uid = current->euid;
e_gid = current->egid;
} else {
e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
}
if (current->euid == inode->i_uid) if (current->euid == inode->i_uid)
i >>= 6; i >>= 6;
else if (in_group_p(inode->i_gid)) else if (in_group_p(inode->i_gid))
i >>= 3; i >>= 3;
if (!(i & 1) && if (!(i & 1) &&
!((inode->i_mode & 0111) && suser())) { !((inode->i_mode & 0111) && suser())) {
retval = -ENOEXEC; retval = -EACCES;
goto exec_error2; goto exec_error2;
} }
if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) { if (!(bh = bread(inode->i_dev,inode->i_data[0]))) {
retval = -EACCES; retval = -EACCES;
goto exec_error2; goto exec_error2;
} }
...@@ -367,11 +373,13 @@ int do_execve(unsigned long * eip,long tmp,char * filename, ...@@ -367,11 +373,13 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
current->brk = ex.a_bss + current->brk = ex.a_bss +
(current->end_data = ex.a_data + (current->end_data = ex.a_data +
(current->end_code = ex.a_text)); (current->end_code = ex.a_text));
current->start_stack = p & 0xfffff000; current->start_stack = p;
current->suid = current->euid = e_uid; current->suid = current->euid = e_uid;
current->sgid = current->egid = e_gid; current->sgid = current->egid = e_gid;
eip[0] = ex.a_entry; /* eip, magic happens :-) */ eip[0] = ex.a_entry; /* eip, magic happens :-) */
eip[3] = p; /* stack pointer */ eip[3] = p; /* stack pointer */
if (current->flags & PF_PTRACED)
send_sig(SIGTRAP, current, 0);
return 0; return 0;
exec_error2: exec_error2:
iput(inode); iput(inode);
......
...@@ -35,6 +35,8 @@ static int dupfd(unsigned int fd, unsigned int arg) ...@@ -35,6 +35,8 @@ static int dupfd(unsigned int fd, unsigned int arg)
int sys_dup2(unsigned int oldfd, unsigned int newfd) int sys_dup2(unsigned int oldfd, unsigned int newfd)
{ {
if (newfd == oldfd)
return newfd;
sys_close(newfd); sys_close(newfd);
return dupfd(oldfd,newfd); return dupfd(oldfd,newfd);
} }
...@@ -68,8 +70,8 @@ int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -68,8 +70,8 @@ int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
filp->f_flags |= arg & (O_APPEND | O_NONBLOCK); filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
return 0; return 0;
case F_GETLK: case F_SETLK: case F_SETLKW: case F_GETLK: case F_SETLK: case F_SETLKW:
return -1; return -ENOSYS;
default: default:
return -1; return -EINVAL;
} }
} }
...@@ -8,18 +8,17 @@ ...@@ -8,18 +8,17 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/system.h> #include <asm/system.h>
extern int *blk_size[]; struct inode inode_table[NR_INODE]={{0,},};
struct m_inode inode_table[NR_INODE]={{0,},}; extern void minix_read_inode(struct inode * inode);
extern void minix_write_inode(struct inode * inode);
static void read_inode(struct m_inode * inode); static inline void wait_on_inode(struct inode * inode)
static void write_inode(struct m_inode * inode);
static inline void wait_on_inode(struct m_inode * inode)
{ {
cli(); cli();
while (inode->i_lock) while (inode->i_lock)
...@@ -27,7 +26,7 @@ static inline void wait_on_inode(struct m_inode * inode) ...@@ -27,7 +26,7 @@ static inline void wait_on_inode(struct m_inode * inode)
sti(); sti();
} }
static inline void lock_inode(struct m_inode * inode) static inline void lock_inode(struct inode * inode)
{ {
cli(); cli();
while (inode->i_lock) while (inode->i_lock)
...@@ -36,16 +35,39 @@ static inline void lock_inode(struct m_inode * inode) ...@@ -36,16 +35,39 @@ static inline void lock_inode(struct m_inode * inode)
sti(); sti();
} }
static inline void unlock_inode(struct m_inode * inode) static inline void unlock_inode(struct inode * inode)
{ {
inode->i_lock=0; inode->i_lock=0;
wake_up(&inode->i_wait); wake_up(&inode->i_wait);
} }
static void write_inode(struct inode * inode)
{
lock_inode(inode);
if (!inode->i_dirt || !inode->i_dev) {
unlock_inode(inode);
return;
}
minix_write_inode(inode);
unlock_inode(inode);
}
static void read_inode(struct inode * inode)
{
lock_inode(inode);
minix_read_inode(inode);
unlock_inode(inode);
}
int bmap(struct inode * inode, int block)
{
return minix_bmap(inode,block);
}
void invalidate_inodes(int dev) void invalidate_inodes(int dev)
{ {
int i; int i;
struct m_inode * inode; struct inode * inode;
inode = 0+inode_table; inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) { for(i=0 ; i<NR_INODE ; i++,inode++) {
...@@ -61,7 +83,7 @@ void invalidate_inodes(int dev) ...@@ -61,7 +83,7 @@ void invalidate_inodes(int dev)
void sync_inodes(void) void sync_inodes(void)
{ {
int i; int i;
struct m_inode * inode; struct inode * inode;
inode = 0+inode_table; inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) { for(i=0 ; i<NR_INODE ; i++,inode++) {
...@@ -71,85 +93,7 @@ void sync_inodes(void) ...@@ -71,85 +93,7 @@ void sync_inodes(void)
} }
} }
static int _bmap(struct m_inode * inode,int block,int create) void iput(struct inode * inode)
{
struct buffer_head * bh;
int i;
if (block<0)
panic("_bmap: block<0");
if (block >= 7+512+512*512)
panic("_bmap: block>big");
if (block<7) {
if (create && !inode->i_zone[block])
if (inode->i_zone[block]=new_block(inode->i_dev)) {
inode->i_ctime=CURRENT_TIME;
inode->i_dirt=1;
}
return inode->i_zone[block];
}
block -= 7;
if (block<512) {
if (create && !inode->i_zone[7])
if (inode->i_zone[7]=new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_zone[7])
return 0;
if (!(bh = bread(inode->i_dev,inode->i_zone[7])))
return 0;
i = ((unsigned short *) (bh->b_data))[block];
if (create && !i)
if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
block -= 512;
if (create && !inode->i_zone[8])
if (inode->i_zone[8]=new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_zone[8])
return 0;
if (!(bh=bread(inode->i_dev,inode->i_zone[8])))
return 0;
i = ((unsigned short *)bh->b_data)[block>>9];
if (create && !i)
if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block>>9]=i;
bh->b_dirt=1;
}
brelse(bh);
if (!i)
return 0;
if (!(bh=bread(inode->i_dev,i)))
return 0;
i = ((unsigned short *)bh->b_data)[block&511];
if (create && !i)
if (i=new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block&511]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
int bmap(struct m_inode * inode,int block)
{
return _bmap(inode,block,0);
}
int create_block(struct m_inode * inode, int block)
{
return _bmap(inode,block,1);
}
void iput(struct m_inode * inode)
{ {
if (!inode) if (!inode)
return; return;
...@@ -172,7 +116,7 @@ void iput(struct m_inode * inode) ...@@ -172,7 +116,7 @@ void iput(struct m_inode * inode)
return; return;
} }
if (S_ISBLK(inode->i_mode)) { if (S_ISBLK(inode->i_mode)) {
sync_dev(inode->i_zone[0]); sync_dev(inode->i_rdev);
wait_on_inode(inode); wait_on_inode(inode);
} }
repeat: repeat:
...@@ -180,9 +124,9 @@ void iput(struct m_inode * inode) ...@@ -180,9 +124,9 @@ void iput(struct m_inode * inode)
inode->i_count--; inode->i_count--;
return; return;
} }
if (!inode->i_nlinks) { if (!inode->i_nlink) {
truncate(inode); minix_truncate(inode);
free_inode(inode); minix_free_inode(inode);
return; return;
} }
if (inode->i_dirt) { if (inode->i_dirt) {
...@@ -194,10 +138,10 @@ void iput(struct m_inode * inode) ...@@ -194,10 +138,10 @@ void iput(struct m_inode * inode)
return; return;
} }
struct m_inode * get_empty_inode(void) struct inode * get_empty_inode(void)
{ {
struct m_inode * inode; struct inode * inode;
static struct m_inode * last_inode = inode_table; static struct inode * last_inode = inode_table;
int i; int i;
do { do {
...@@ -213,8 +157,8 @@ struct m_inode * get_empty_inode(void) ...@@ -213,8 +157,8 @@ struct m_inode * get_empty_inode(void)
} }
if (!inode) { if (!inode) {
for (i=0 ; i<NR_INODE ; i++) for (i=0 ; i<NR_INODE ; i++)
printk("%04x: %6d\t",inode_table[i].i_dev, printk("(%04x: %d (%o)) ",inode_table[i].i_dev,
inode_table[i].i_num); inode_table[i].i_ino,inode_table[i].i_mode);
panic("No free inodes in mem"); panic("No free inodes in mem");
} }
wait_on_inode(inode); wait_on_inode(inode);
...@@ -228,9 +172,9 @@ struct m_inode * get_empty_inode(void) ...@@ -228,9 +172,9 @@ struct m_inode * get_empty_inode(void)
return inode; return inode;
} }
struct m_inode * get_pipe_inode(void) struct inode * get_pipe_inode(void)
{ {
struct m_inode * inode; struct inode * inode;
if (!(inode = get_empty_inode())) if (!(inode = get_empty_inode()))
return NULL; return NULL;
...@@ -244,21 +188,21 @@ struct m_inode * get_pipe_inode(void) ...@@ -244,21 +188,21 @@ struct m_inode * get_pipe_inode(void)
return inode; return inode;
} }
struct m_inode * iget(int dev,int nr) struct inode * iget(int dev,int nr)
{ {
struct m_inode * inode, * empty; struct inode * inode, * empty;
if (!dev) if (!dev)
panic("iget with dev==0"); panic("iget with dev==0");
empty = get_empty_inode(); empty = get_empty_inode();
inode = inode_table; inode = inode_table;
while (inode < NR_INODE+inode_table) { while (inode < NR_INODE+inode_table) {
if (inode->i_dev != dev || inode->i_num != nr) { if (inode->i_dev != dev || inode->i_ino != nr) {
inode++; inode++;
continue; continue;
} }
wait_on_inode(inode); wait_on_inode(inode);
if (inode->i_dev != dev || inode->i_num != nr) { if (inode->i_dev != dev || inode->i_ino != nr) {
inode = inode_table; inode = inode_table;
continue; continue;
} }
...@@ -267,7 +211,7 @@ struct m_inode * iget(int dev,int nr) ...@@ -267,7 +211,7 @@ struct m_inode * iget(int dev,int nr)
int i; int i;
for (i = 0 ; i<NR_SUPER ; i++) for (i = 0 ; i<NR_SUPER ; i++)
if (super_block[i].s_imount==inode) if (super_block[i].s_covered==inode)
break; break;
if (i >= NR_SUPER) { if (i >= NR_SUPER) {
printk("Mounted inode hasn't got sb\n"); printk("Mounted inode hasn't got sb\n");
...@@ -276,10 +220,12 @@ struct m_inode * iget(int dev,int nr) ...@@ -276,10 +220,12 @@ struct m_inode * iget(int dev,int nr)
return inode; return inode;
} }
iput(inode); iput(inode);
dev = super_block[i].s_dev; if (!(inode = super_block[i].s_mounted))
nr = ROOT_INO; printk("iget: mounted dev has no rootinode\n");
inode = inode_table; else {
continue; inode->i_count++;
wait_on_inode(inode);
}
} }
if (empty) if (empty)
iput(empty); iput(empty);
...@@ -287,62 +233,14 @@ struct m_inode * iget(int dev,int nr) ...@@ -287,62 +233,14 @@ struct m_inode * iget(int dev,int nr)
} }
if (!empty) if (!empty)
return (NULL); return (NULL);
inode=empty; inode = empty;
if (!(inode->i_sb = get_super(dev))) {
printk("iget: gouldn't get super-block\n\t");
iput(inode);
return NULL;
}
inode->i_dev = dev; inode->i_dev = dev;
inode->i_num = nr; inode->i_ino = nr;
read_inode(inode); read_inode(inode);
return inode; return inode;
} }
static void read_inode(struct m_inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
int block;
lock_inode(inode);
if (!(sb=get_super(inode->i_dev)))
panic("trying to read inode without dev");
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
*(struct d_inode *)inode =
((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK];
brelse(bh);
if (S_ISBLK(inode->i_mode)) {
int i = inode->i_zone[0];
if (blk_size[MAJOR(i)])
inode->i_size = 1024*blk_size[MAJOR(i)][MINOR(i)];
else
inode->i_size = 0x7fffffff;
}
unlock_inode(inode);
}
static void write_inode(struct m_inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
int block;
lock_inode(inode);
if (!inode->i_dirt || !inode->i_dev) {
unlock_inode(inode);
return;
}
if (!(sb=get_super(inode->i_dev)))
panic("trying to write inode without device");
block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
((struct d_inode *)bh->b_data)
[(inode->i_num-1)%INODES_PER_BLOCK] =
*(struct d_inode *)inode;
bh->b_dirt=1;
inode->i_dirt=0;
brelse(bh);
unlock_inode(inode);
}
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <linux/sched.h> #include <linux/sched.h>
extern int tty_ioctl(int dev, int cmd, int arg); extern int tty_ioctl(int dev, int cmd, int arg);
extern int pipe_ioctl(struct m_inode *pino, int cmd, int arg); extern int pipe_ioctl(struct inode *pino, int cmd, int arg);
typedef int (*ioctl_ptr)(int dev,int cmd,int arg); typedef int (*ioctl_ptr)(int dev,int cmd,int arg);
...@@ -40,7 +40,7 @@ int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -40,7 +40,7 @@ int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
mode=filp->f_inode->i_mode; mode=filp->f_inode->i_mode;
if (!S_ISCHR(mode) && !S_ISBLK(mode)) if (!S_ISCHR(mode) && !S_ISBLK(mode))
return -EINVAL; return -EINVAL;
dev = filp->f_inode->i_zone[0]; dev = filp->f_inode->i_rdev;
if (MAJOR(dev) >= NRDEVS) if (MAJOR(dev) >= NRDEVS)
return -ENODEV; return -ENODEV;
if (!ioctl_table[MAJOR(dev)]) if (!ioctl_table[MAJOR(dev)])
......
AR =ar
AS =as
CC =gcc
LD =ld
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
-nostdinc -I../../include
CPP =gcc -E -nostdinc -I../../include
.c.s:
$(CC) $(CFLAGS) \
-S -o $*.s $<
.c.o:
$(CC) $(CFLAGS) \
-c -o $*.o $<
.s.o:
$(AS) -o $*.o $<
OBJS= minix_op.o bitmap.o truncate.o namei.o inode.o file_dev.o
minix.o: $(OBJS)
$(LD) -r -o minix.o $(OBJS)
clean:
rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
### Dependencies:
bitmap.o : bitmap.c ../../include/string.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/linux/mm.h \
../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h
file_dev.o : file_dev.c ../../include/errno.h ../../include/fcntl.h \
../../include/sys/types.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
../../include/time.h ../../include/sys/resource.h \
../../include/linux/minix_fs.h ../../include/asm/segment.h
inode.o : inode.c ../../include/string.h ../../include/sys/stat.h \
../../include/sys/types.h ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/linux/mm.h ../../include/linux/kernel.h \
../../include/signal.h ../../include/sys/param.h ../../include/sys/time.h \
../../include/time.h ../../include/sys/resource.h \
../../include/linux/minix_fs.h ../../include/asm/system.h
minix_op.o : minix_op.c ../../include/linux/fs.h ../../include/sys/types.h \
../../include/linux/minix_fs.h
namei.o : namei.c ../../include/linux/sched.h ../../include/linux/head.h \
../../include/linux/fs.h ../../include/sys/types.h ../../include/linux/mm.h \
../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h \
../../include/asm/segment.h ../../include/string.h ../../include/fcntl.h \
../../include/errno.h ../../include/const.h ../../include/sys/stat.h
truncate.o : truncate.c ../../include/linux/sched.h \
../../include/linux/head.h ../../include/linux/fs.h \
../../include/sys/types.h ../../include/linux/mm.h \
../../include/linux/kernel.h ../../include/signal.h \
../../include/sys/param.h ../../include/sys/time.h ../../include/time.h \
../../include/sys/resource.h ../../include/linux/minix_fs.h \
../../include/linux/tty.h ../../include/termios.h ../../include/errno.h \
../../include/fcntl.h ../../include/sys/stat.h
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <string.h> #include <string.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#define clear_block(addr) \ #define clear_block(addr) \
...@@ -17,15 +18,15 @@ __asm__("cld\n\t" \ ...@@ -17,15 +18,15 @@ __asm__("cld\n\t" \
::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di") ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
#define set_bit(nr,addr) ({\ #define set_bit(nr,addr) ({\
register int res __asm__("ax"); \ char res; \
__asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \ __asm__ __volatile__("btsl %1,%2\n\tsetb %0": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \ "=q" (res):"r" (nr),"m" (*(addr))); \
res;}) res;})
#define clear_bit(nr,addr) ({\ #define clear_bit(nr,addr) ({\
register int res __asm__("ax"); \ char res; \
__asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \ __asm__ __volatile__("btrl %1,%2\n\tsetnb %0": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \ "=q" (res):"r" (nr),"m" (*(addr))); \
res;}) res;})
#define find_first_zero(addr) ({ \ #define find_first_zero(addr) ({ \
...@@ -34,20 +35,20 @@ __asm__("cld\n" \ ...@@ -34,20 +35,20 @@ __asm__("cld\n" \
"1:\tlodsl\n\t" \ "1:\tlodsl\n\t" \
"notl %%eax\n\t" \ "notl %%eax\n\t" \
"bsfl %%eax,%%edx\n\t" \ "bsfl %%eax,%%edx\n\t" \
"je 2f\n\t" \ "jne 2f\n\t" \
"addl %%edx,%%ecx\n\t" \ "addl $32,%%ecx\n\t" \
"jmp 3f\n" \
"2:\taddl $32,%%ecx\n\t" \
"cmpl $8192,%%ecx\n\t" \ "cmpl $8192,%%ecx\n\t" \
"jl 1b\n" \ "jl 1b\n\t" \
"3:" \ "xorl %%edx,%%edx\n" \
:"=c" (__res):"c" (0),"S" (addr):"ax","dx","si"); \ "2:\taddl %%edx,%%ecx" \
:"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
__res;}) __res;})
int free_block(int dev, int block) int minix_free_block(int dev, int block)
{ {
struct super_block * sb; struct super_block * sb;
struct buffer_head * bh; struct buffer_head * bh;
unsigned int bit,zone;
if (!(sb = get_super(dev))) if (!(sb = get_super(dev)))
panic("trying to free block on nonexistent device"); panic("trying to free block on nonexistent device");
...@@ -64,16 +65,17 @@ int free_block(int dev, int block) ...@@ -64,16 +65,17 @@ int free_block(int dev, int block)
if (bh->b_count) if (bh->b_count)
brelse(bh); brelse(bh);
} }
block -= sb->s_firstdatazone - 1 ; zone = block - sb->s_firstdatazone + 1;
if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) { bit = zone & 8191;
printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1); zone >>= 13;
printk("free_block: bit already cleared\n"); bh = sb->s_zmap[zone];
} if (clear_bit(bit,bh->b_data))
sb->s_zmap[block/8192]->b_dirt = 1; printk("free_block (%04x:%d): bit already cleared\n",dev,block);
bh->b_dirt = 1;
return 1; return 1;
} }
int new_block(int dev) int minix_new_block(int dev)
{ {
struct buffer_head * bh; struct buffer_head * bh;
struct super_block * sb; struct super_block * sb;
...@@ -105,9 +107,8 @@ int new_block(int dev) ...@@ -105,9 +107,8 @@ int new_block(int dev)
return j; return j;
} }
void free_inode(struct m_inode * inode) void minix_free_inode(struct inode * inode)
{ {
struct super_block * sb;
struct buffer_head * bh; struct buffer_head * bh;
if (!inode) if (!inode)
...@@ -117,53 +118,67 @@ void free_inode(struct m_inode * inode) ...@@ -117,53 +118,67 @@ void free_inode(struct m_inode * inode)
return; return;
} }
if (inode->i_count>1) { if (inode->i_count>1) {
printk("trying to free inode with count=%d\n",inode->i_count); printk("free_inode: inode has count=%d\n",inode->i_count);
panic("free_inode"); return;
}
if (inode->i_nlink) {
printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
return;
} }
if (inode->i_nlinks) if (!inode->i_sb) {
panic("trying to free inode with links"); printk("free_inode: inode on nonexistent device\n");
if (!(sb = get_super(inode->i_dev))) return;
panic("trying to free inode on nonexistent device"); }
if (inode->i_num < 1 || inode->i_num > sb->s_ninodes) if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->s_ninodes) {
panic("trying to free inode 0 or nonexistant inode"); printk("free_inode: inode 0 or nonexistent inode\n");
if (!(bh=sb->s_imap[inode->i_num>>13])) return;
panic("nonexistent imap in superblock"); }
if (clear_bit(inode->i_num&8191,bh->b_data)) if (!(bh=inode->i_sb->s_imap[inode->i_ino>>13])) {
printk("free_inode: nonexistent imap in superblock\n");
return;
}
if (clear_bit(inode->i_ino&8191,bh->b_data))
printk("free_inode: bit already cleared.\n\r"); printk("free_inode: bit already cleared.\n\r");
bh->b_dirt = 1; bh->b_dirt = 1;
memset(inode,0,sizeof(*inode)); memset(inode,0,sizeof(*inode));
} }
struct m_inode * new_inode(int dev) struct inode * minix_new_inode(int dev)
{ {
struct m_inode * inode; struct inode * inode;
struct super_block * sb;
struct buffer_head * bh; struct buffer_head * bh;
int i,j; int i,j;
if (!(inode=get_empty_inode())) if (!(inode=get_empty_inode()))
return NULL; return NULL;
if (!(sb = get_super(dev))) if (!(inode->i_sb = get_super(dev))) {
panic("new_inode with unknown device"); printk("new_inode: unknown device\n");
iput(inode);
return NULL;
}
j = 8192; j = 8192;
for (i=0 ; i<8 ; i++) for (i=0 ; i<8 ; i++)
if (bh=sb->s_imap[i]) if (bh=inode->i_sb->s_imap[i])
if ((j=find_first_zero(bh->b_data))<8192) if ((j=find_first_zero(bh->b_data))<8192)
break; break;
if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) { if (!bh || j >= 8192 || j+i*8192 > inode->i_sb->s_ninodes) {
iput(inode);
return NULL;
}
if (set_bit(j,bh->b_data)) { /* shouldn't happen */
printk("new_inode: bit already set");
iput(inode); iput(inode);
return NULL; return NULL;
} }
if (set_bit(j,bh->b_data))
panic("new_inode: bit already set");
bh->b_dirt = 1; bh->b_dirt = 1;
inode->i_count=1; inode->i_count = 1;
inode->i_nlinks=1; inode->i_nlink = 1;
inode->i_dev=dev; inode->i_dev = dev;
inode->i_uid=current->euid; inode->i_uid = current->euid;
inode->i_gid=current->egid; inode->i_gid = current->egid;
inode->i_dirt=1; inode->i_dirt = 1;
inode->i_num = j + i*8192; inode->i_ino = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = &minix_inode_operations;
return inode; return inode;
} }
...@@ -8,29 +8,36 @@ ...@@ -8,29 +8,36 @@
#include <fcntl.h> #include <fcntl.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
#define MIN(a,b) (((a)<(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b))
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) int minix_file_read(struct inode * inode, struct file * filp, char * buf, int count)
{ {
int left,chars,nr; int read,left,chars,nr;
struct buffer_head * bh; struct buffer_head * bh;
if ((left=count)<=0) if (filp->f_pos > inode->i_size)
return 0; left = 0;
while (left) { else
if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) { left = inode->i_size - filp->f_pos;
if (left > count)
left = count;
read = 0;
while (left > 0) {
if (nr = bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS)) {
if (!(bh=bread(inode->i_dev,nr))) if (!(bh=bread(inode->i_dev,nr)))
break; return read?read:-EIO;
} else } else
bh = NULL; bh = NULL;
nr = filp->f_pos % BLOCK_SIZE; nr = filp->f_pos & (BLOCK_SIZE-1);
chars = MIN( BLOCK_SIZE-nr , left ); chars = MIN( BLOCK_SIZE-nr , left );
filp->f_pos += chars; filp->f_pos += chars;
left -= chars; left -= chars;
read += chars;
if (bh) { if (bh) {
char * p = nr + bh->b_data; char * p = nr + bh->b_data;
while (chars-->0) while (chars-->0)
...@@ -42,16 +49,15 @@ int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) ...@@ -42,16 +49,15 @@ int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
} }
} }
inode->i_atime = CURRENT_TIME; inode->i_atime = CURRENT_TIME;
return (count-left)?(count-left):-ERROR; return read;
} }
int file_write(struct m_inode * inode, struct file * filp, char * buf, int count) int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count)
{ {
off_t pos; off_t pos;
int block,c; int written,block,c;
struct buffer_head * bh; struct buffer_head * bh;
char * p; char * p;
int i=0;
/* /*
* ok, append may not work when many processes are writing at the same time * ok, append may not work when many processes are writing at the same time
...@@ -61,22 +67,30 @@ int file_write(struct m_inode * inode, struct file * filp, char * buf, int count ...@@ -61,22 +67,30 @@ int file_write(struct m_inode * inode, struct file * filp, char * buf, int count
pos = inode->i_size; pos = inode->i_size;
else else
pos = filp->f_pos; pos = filp->f_pos;
while (i<count) { written = 0;
if (!(block = create_block(inode,pos/BLOCK_SIZE))) while (written<count) {
if (!(block = minix_create_block(inode,pos/BLOCK_SIZE))) {
if (!written)
written = -ENOSPC;
break; break;
if (!(bh=bread(inode->i_dev,block))) }
if (!(bh=bread(inode->i_dev,block))) {
if (!written)
written = -EIO;
break; break;
}
c = pos % BLOCK_SIZE; c = pos % BLOCK_SIZE;
p = c + bh->b_data; p = c + bh->b_data;
bh->b_dirt = 1; bh->b_dirt = 1;
c = BLOCK_SIZE-c; c = BLOCK_SIZE-c;
if (c > count-i) c = count-i; if (c > count-written)
c = count-written;
pos += c; pos += c;
if (pos > inode->i_size) { if (pos > inode->i_size) {
inode->i_size = pos; inode->i_size = pos;
inode->i_dirt = 1; inode->i_dirt = 1;
} }
i += c; written += c;
while (c-->0) while (c-->0)
*(p++) = get_fs_byte(buf++); *(p++) = get_fs_byte(buf++);
brelse(bh); brelse(bh);
...@@ -85,6 +99,7 @@ int file_write(struct m_inode * inode, struct file * filp, char * buf, int count ...@@ -85,6 +99,7 @@ int file_write(struct m_inode * inode, struct file * filp, char * buf, int count
if (!(filp->f_flags & O_APPEND)) { if (!(filp->f_flags & O_APPEND)) {
filp->f_pos = pos; filp->f_pos = pos;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
} }
return (i?i:-1); return written;
} }
/*
* linux/fs/minix/inode.c
*
* (C) 1991 Linus Torvalds
*/
#include <string.h>
#include <sys/stat.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>
static int _bmap(struct inode * inode,int block,int create)
{
struct buffer_head * bh;
int i;
if (block<0)
panic("_bmap: block<0");
if (block >= 7+512+512*512)
panic("_bmap: block>big");
if (block<7) {
if (create && !inode->i_data[block])
if (inode->i_data[block]=minix_new_block(inode->i_dev)) {
inode->i_ctime=CURRENT_TIME;
inode->i_dirt=1;
}
return inode->i_data[block];
}
block -= 7;
if (block<512) {
if (create && !inode->i_data[7])
if (inode->i_data[7]=minix_new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_data[7])
return 0;
if (!(bh = bread(inode->i_dev,inode->i_data[7])))
return 0;
i = ((unsigned short *) (bh->b_data))[block];
if (create && !i)
if (i=minix_new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
block -= 512;
if (create && !inode->i_data[8])
if (inode->i_data[8]=minix_new_block(inode->i_dev)) {
inode->i_dirt=1;
inode->i_ctime=CURRENT_TIME;
}
if (!inode->i_data[8])
return 0;
if (!(bh=bread(inode->i_dev,inode->i_data[8])))
return 0;
i = ((unsigned short *)bh->b_data)[block>>9];
if (create && !i)
if (i=minix_new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block>>9]=i;
bh->b_dirt=1;
}
brelse(bh);
if (!i)
return 0;
if (!(bh=bread(inode->i_dev,i)))
return 0;
i = ((unsigned short *)bh->b_data)[block&511];
if (create && !i)
if (i=minix_new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block&511]=i;
bh->b_dirt=1;
}
brelse(bh);
return i;
}
int minix_bmap(struct inode * inode,int block)
{
return _bmap(inode,block,0);
}
int minix_create_block(struct inode * inode, int block)
{
return _bmap(inode,block,1);
}
void minix_read_inode(struct inode * inode)
{
struct buffer_head * bh;
struct minix_inode * raw_inode;
int block;
block = 2 + inode->i_sb->s_imap_blocks + inode->i_sb->s_zmap_blocks +
(inode->i_ino-1)/MINIX_INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
raw_inode = ((struct minix_inode *) bh->b_data) +
(inode->i_ino-1)%MINIX_INODES_PER_BLOCK;
inode->i_mode = raw_inode->i_mode;
inode->i_uid = raw_inode->i_uid;
inode->i_gid = raw_inode->i_gid;
inode->i_nlink = raw_inode->i_nlinks;
inode->i_size = raw_inode->i_size;
inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
inode->i_rdev = raw_inode->i_zone[0];
else for (block = 0; block < 9; block++)
inode->i_data[block] = raw_inode->i_zone[block];
brelse(bh);
inode->i_op = &minix_inode_operations;
}
void minix_write_inode(struct inode * inode)
{
struct buffer_head * bh;
struct minix_inode * raw_inode;
int block;
block = 2 + inode->i_sb->s_imap_blocks + inode->i_sb->s_zmap_blocks +
(inode->i_ino-1)/MINIX_INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev,block)))
panic("unable to read i-node block");
raw_inode = ((struct minix_inode *)bh->b_data) +
(inode->i_ino-1)%MINIX_INODES_PER_BLOCK;
raw_inode->i_mode = inode->i_mode;
raw_inode->i_uid = inode->i_uid;
raw_inode->i_gid = inode->i_gid;
raw_inode->i_nlinks = inode->i_nlink;
raw_inode->i_size = inode->i_size;
raw_inode->i_time = inode->i_mtime;
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_zone[0] = inode->i_rdev;
else for (block = 0; block < 9; block++)
raw_inode->i_zone[block] = inode->i_data[block];
bh->b_dirt=1;
inode->i_dirt=0;
brelse(bh);
}
/*
* linux/fs/minix/minix_op.c
*
* structures for the minix super_block/inode/file-operations
*/
#include <linux/fs.h>
#include <linux/minix_fs.h>
/*
* These are the low-level inode operations for minix filesystem inodes.
*/
struct inode_operations minix_inode_operations = {
minix_create,
minix_lookup,
minix_link,
minix_unlink,
minix_symlink,
minix_mkdir,
minix_rmdir,
minix_mknod,
minix_rename,
minix_readlink,
minix_open,
minix_release,
minix_follow_link
};
/*
* We have just NULL's here: the current defaults are ok for
* the minix filesystem.
*/
struct file_operations minix_file_operations = {
NULL, /* lseek */
NULL, /* read */
NULL /* write */
};
This diff is collapsed.
...@@ -5,10 +5,14 @@ ...@@ -5,10 +5,14 @@
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/tty.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
static int free_ind(int dev,int block) static int minix_free_ind(int dev,int block)
{ {
struct buffer_head * bh; struct buffer_head * bh;
unsigned short * p; unsigned short * p;
...@@ -22,7 +26,7 @@ static int free_ind(int dev,int block) ...@@ -22,7 +26,7 @@ static int free_ind(int dev,int block)
p = (unsigned short *) bh->b_data; p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++) for (i=0;i<512;i++,p++)
if (*p) if (*p)
if (free_block(dev,*p)) { if (minix_free_block(dev,*p)) {
*p = 0; *p = 0;
bh->b_dirt = 1; bh->b_dirt = 1;
} else } else
...@@ -32,10 +36,10 @@ static int free_ind(int dev,int block) ...@@ -32,10 +36,10 @@ static int free_ind(int dev,int block)
if (block_busy) if (block_busy)
return 0; return 0;
else else
return free_block(dev,block); return minix_free_block(dev,block);
} }
static int free_dind(int dev,int block) static int minix_free_dind(int dev,int block)
{ {
struct buffer_head * bh; struct buffer_head * bh;
unsigned short * p; unsigned short * p;
...@@ -49,7 +53,7 @@ static int free_dind(int dev,int block) ...@@ -49,7 +53,7 @@ static int free_dind(int dev,int block)
p = (unsigned short *) bh->b_data; p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++) for (i=0;i<512;i++,p++)
if (*p) if (*p)
if (free_ind(dev,*p)) { if (minix_free_ind(dev,*p)) {
*p = 0; *p = 0;
bh->b_dirt = 1; bh->b_dirt = 1;
} else } else
...@@ -59,10 +63,10 @@ static int free_dind(int dev,int block) ...@@ -59,10 +63,10 @@ static int free_dind(int dev,int block)
if (block_busy) if (block_busy)
return 0; return 0;
else else
return free_block(dev,block); return minix_free_block(dev,block);
} }
void truncate(struct m_inode * inode) void minix_truncate(struct inode * inode)
{ {
int i; int i;
int block_busy; int block_busy;
...@@ -73,18 +77,18 @@ void truncate(struct m_inode * inode) ...@@ -73,18 +77,18 @@ void truncate(struct m_inode * inode)
repeat: repeat:
block_busy = 0; block_busy = 0;
for (i=0;i<7;i++) for (i=0;i<7;i++)
if (inode->i_zone[i]) { if (inode->i_data[i]) {
if (free_block(inode->i_dev,inode->i_zone[i])) if (minix_free_block(inode->i_dev,inode->i_data[i]))
inode->i_zone[i]=0; inode->i_data[i]=0;
else else
block_busy = 1; block_busy = 1;
} }
if (free_ind(inode->i_dev,inode->i_zone[7])) if (minix_free_ind(inode->i_dev,inode->i_data[7]))
inode->i_zone[7] = 0; inode->i_data[7] = 0;
else else
block_busy = 1; block_busy = 1;
if (free_dind(inode->i_dev,inode->i_zone[8])) if (minix_free_dind(inode->i_dev,inode->i_data[8]))
inode->i_zone[8] = 0; inode->i_data[8] = 0;
else else
block_busy = 1; block_busy = 1;
inode->i_dirt = 1; inode->i_dirt = 1;
...@@ -97,3 +101,54 @@ void truncate(struct m_inode * inode) ...@@ -97,3 +101,54 @@ void truncate(struct m_inode * inode)
inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_ctime = CURRENT_TIME;
} }
/*
* Called when a inode is released. Note that this is different
* from minix_open: open gets called at every open, but release
* gets called only when /all/ the files are closed.
*/
void minix_release(struct inode * inode, struct file * filp)
{
printk("minix_release not implemented\n");
}
static int check_char_dev(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
int min, dev;
dev = inode->i_rdev;
if (MAJOR(dev) == 4 || MAJOR(dev) == 5) {
if (MAJOR(dev) == 5)
min = current->tty;
else
min = MINOR(dev);
if (min < 0)
return -1;
if ((IS_A_PTY_MASTER(min)) && (inode->i_count>1))
return -1;
tty = TTY_TABLE(min);
if (!(filp->f_flags & O_NOCTTY) &&
current->leader &&
current->tty<0 &&
tty->session==0) {
current->tty = min;
tty->session= current->session;
tty->pgrp = current->pgrp;
}
}
return 0;
}
/*
* Called every time a minix-file is opened
*/
int minix_open(struct inode * inode, struct file * filp)
{
if (S_ISCHR(inode->i_mode)) {
if (check_char_dev(inode,filp))
return -EAGAIN;
} else if (S_ISBLK(inode->i_mode))
check_disk_change(inode->i_rdev);
filp->f_op = &minix_file_operations;
return 0;
}
This diff is collapsed.
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/tty.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
...@@ -24,7 +23,7 @@ int sys_ustat(int dev, struct ustat * ubuf) ...@@ -24,7 +23,7 @@ int sys_ustat(int dev, struct ustat * ubuf)
int sys_utime(char * filename, struct utimbuf * times) int sys_utime(char * filename, struct utimbuf * times)
{ {
struct m_inode * inode; struct inode * inode;
long actime,modtime; long actime,modtime;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
...@@ -47,7 +46,7 @@ int sys_utime(char * filename, struct utimbuf * times) ...@@ -47,7 +46,7 @@ int sys_utime(char * filename, struct utimbuf * times)
*/ */
int sys_access(const char * filename,int mode) int sys_access(const char * filename,int mode)
{ {
struct m_inode * inode; struct inode * inode;
int res, i_mode; int res, i_mode;
mode &= 0007; mode &= 0007;
...@@ -75,7 +74,7 @@ int sys_access(const char * filename,int mode) ...@@ -75,7 +74,7 @@ int sys_access(const char * filename,int mode)
int sys_chdir(const char * filename) int sys_chdir(const char * filename)
{ {
struct m_inode * inode; struct inode * inode;
if (!(inode = namei(filename))) if (!(inode = namei(filename)))
return -ENOENT; return -ENOENT;
...@@ -90,7 +89,7 @@ int sys_chdir(const char * filename) ...@@ -90,7 +89,7 @@ int sys_chdir(const char * filename)
int sys_chroot(const char * filename) int sys_chroot(const char * filename)
{ {
struct m_inode * inode; struct inode * inode;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -ENOENT; return -ENOENT;
...@@ -105,7 +104,7 @@ int sys_chroot(const char * filename) ...@@ -105,7 +104,7 @@ int sys_chroot(const char * filename)
int sys_chmod(const char * filename,int mode) int sys_chmod(const char * filename,int mode)
{ {
struct m_inode * inode; struct inode * inode;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -ENOENT; return -ENOENT;
...@@ -121,7 +120,7 @@ int sys_chmod(const char * filename,int mode) ...@@ -121,7 +120,7 @@ int sys_chmod(const char * filename,int mode)
int sys_chown(const char * filename,int uid,int gid) int sys_chown(const char * filename,int uid,int gid)
{ {
struct m_inode * inode; struct inode * inode;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -ENOENT; return -ENOENT;
...@@ -136,45 +135,12 @@ int sys_chown(const char * filename,int uid,int gid) ...@@ -136,45 +135,12 @@ int sys_chown(const char * filename,int uid,int gid)
return 0; return 0;
} }
static int check_char_dev(struct m_inode * inode, int dev, int flag)
{
struct tty_struct *tty;
int min;
if (MAJOR(dev) == 4 || MAJOR(dev) == 5) {
if (MAJOR(dev) == 5)
min = current->tty;
else
min = MINOR(dev);
if (min < 0)
return -1;
if ((IS_A_PTY_MASTER(min)) && (inode->i_count>1))
return -1;
tty = TTY_TABLE(min);
if (!(flag & O_NOCTTY) &&
current->leader &&
current->tty<0 &&
tty->session==0) {
current->tty = min;
tty->session= current->session;
tty->pgrp = current->pgrp;
}
if (flag & O_NONBLOCK) {
TTY_TABLE(min)->termios.c_cc[VMIN] =0;
TTY_TABLE(min)->termios.c_cc[VTIME] =0;
TTY_TABLE(min)->termios.c_lflag &= ~ICANON;
}
}
return 0;
}
int sys_open(const char * filename,int flag,int mode) int sys_open(const char * filename,int flag,int mode)
{ {
struct m_inode * inode; struct inode * inode;
struct file * f; struct file * f;
int i,fd; int i,fd;
mode &= 0777 & ~current->umask;
for(fd=0 ; fd<NR_OPEN ; fd++) for(fd=0 ; fd<NR_OPEN ; fd++)
if (!current->filp[fd]) if (!current->filp[fd])
break; break;
...@@ -192,28 +158,25 @@ int sys_open(const char * filename,int flag,int mode) ...@@ -192,28 +158,25 @@ int sys_open(const char * filename,int flag,int mode)
f->f_count=0; f->f_count=0;
return i; return i;
} }
/* ttys are somewhat special (ttyxx major==4, tty major==5) */ f->f_op = NULL;
if (S_ISCHR(inode->i_mode)) f->f_mode = "\001\002\003\000"[flag & O_ACCMODE];
if (check_char_dev(inode,inode->i_zone[0],flag)) {
iput(inode);
current->filp[fd]=NULL;
f->f_count=0;
return -EAGAIN;
}
/* Likewise with block-devices: check for floppy_change */
if (S_ISBLK(inode->i_mode))
check_disk_change(inode->i_zone[0]);
f->f_mode = inode->i_mode;
f->f_flags = flag; f->f_flags = flag;
f->f_count = 1; f->f_count = 1;
f->f_inode = inode; f->f_inode = inode;
f->f_pos = 0; f->f_pos = 0;
if (inode->i_op && inode->i_op->open)
if (i = inode->i_op->open(inode,f)) {
iput(inode);
f->f_count=0;
current->filp[fd]=NULL;
return i;
}
return (fd); return (fd);
} }
int sys_creat(const char * pathname, int mode) int sys_creat(const char * pathname, int mode)
{ {
return sys_open(pathname, O_CREAT | O_TRUNC, mode); return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
} }
int sys_close(unsigned int fd) int sys_close(unsigned int fd)
......
...@@ -7,25 +7,26 @@ ...@@ -7,25 +7,26 @@
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
#include <termios.h> #include <termios.h>
#include <fcntl.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> /* for get_free_page */
#include <asm/segment.h> #include <asm/segment.h>
#include <linux/kernel.h> #include <linux/kernel.h>
int read_pipe(struct m_inode * inode, char * buf, int count) int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
{ {
int chars, size, read = 0; int chars, size, read = 0;
while (count>0) { if (!(filp->f_flags & O_NONBLOCK))
while (!(size=PIPE_SIZE(*inode))) { while (!PIPE_SIZE(*inode)) {
wake_up(& PIPE_WRITE_WAIT(*inode)); wake_up(& PIPE_WRITE_WAIT(*inode));
if (inode->i_count != 2) /* are there any writers? */ if (inode->i_count != 2) /* are there any writers? */
return read; return 0;
if (current->signal & ~current->blocked) if (current->signal & ~current->blocked)
return read?read:-ERESTARTSYS; return -ERESTARTSYS;
interruptible_sleep_on(& PIPE_READ_WAIT(*inode)); interruptible_sleep_on(& PIPE_READ_WAIT(*inode));
} }
while (count>0 && (size = PIPE_SIZE(*inode))) {
chars = PAGE_SIZE-PIPE_TAIL(*inode); chars = PAGE_SIZE-PIPE_TAIL(*inode);
if (chars > count) if (chars > count)
chars = count; chars = count;
...@@ -43,7 +44,7 @@ int read_pipe(struct m_inode * inode, char * buf, int count) ...@@ -43,7 +44,7 @@ int read_pipe(struct m_inode * inode, char * buf, int count)
return read; return read;
} }
int write_pipe(struct m_inode * inode, char * buf, int count) int pipe_write(struct inode * inode, struct file * filp, char * buf, int count)
{ {
int chars, size, written = 0; int chars, size, written = 0;
...@@ -52,9 +53,11 @@ int write_pipe(struct m_inode * inode, char * buf, int count) ...@@ -52,9 +53,11 @@ int write_pipe(struct m_inode * inode, char * buf, int count)
wake_up(& PIPE_READ_WAIT(*inode)); wake_up(& PIPE_READ_WAIT(*inode));
if (inode->i_count != 2) { /* no readers */ if (inode->i_count != 2) { /* no readers */
current->signal |= (1<<(SIGPIPE-1)); current->signal |= (1<<(SIGPIPE-1));
return written?written:-1; return written?written:-EINTR;
} }
sleep_on(& PIPE_WRITE_WAIT(*inode)); if (current->signal & ~current->blocked)
return written?written:-EINTR;
interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode));
} }
chars = PAGE_SIZE-PIPE_HEAD(*inode); chars = PAGE_SIZE-PIPE_HEAD(*inode);
if (chars > count) if (chars > count)
...@@ -75,7 +78,7 @@ int write_pipe(struct m_inode * inode, char * buf, int count) ...@@ -75,7 +78,7 @@ int write_pipe(struct m_inode * inode, char * buf, int count)
int sys_pipe(unsigned long * fildes) int sys_pipe(unsigned long * fildes)
{ {
struct m_inode * inode; struct inode * inode;
struct file * f[2]; struct file * f[2];
int fd[2]; int fd[2];
int i,j; int i,j;
...@@ -115,7 +118,7 @@ int sys_pipe(unsigned long * fildes) ...@@ -115,7 +118,7 @@ int sys_pipe(unsigned long * fildes)
return 0; return 0;
} }
int pipe_ioctl(struct m_inode *pino, int cmd, int arg) int pipe_ioctl(struct inode *pino, int cmd, int arg)
{ {
switch (cmd) { switch (cmd) {
case FIONREAD: case FIONREAD:
......
...@@ -12,26 +12,20 @@ ...@@ -12,26 +12,20 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <asm/segment.h> #include <asm/segment.h>
extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos); int sys_lseek(unsigned int fd,off_t offset, unsigned int origin)
extern int read_pipe(struct m_inode * inode, char * buf, int count);
extern int write_pipe(struct m_inode * inode, char * buf, int count);
extern int block_read(int dev, off_t * pos, char * buf, int count);
extern int block_write(int dev, off_t * pos, char * buf, int count);
extern int file_read(struct m_inode * inode, struct file * filp,
char * buf, int count);
extern int file_write(struct m_inode * inode, struct file * filp,
char * buf, int count);
int sys_lseek(unsigned int fd,off_t offset, int origin)
{ {
struct file * file; struct file * file;
int tmp; int tmp;
if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode) if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode))
|| !IS_SEEKABLE(MAJOR(file->f_inode->i_dev)))
return -EBADF; return -EBADF;
if (origin > 2)
return -EINVAL;
if (file->f_inode->i_pipe) if (file->f_inode->i_pipe)
return -ESPIPE; return -ESPIPE;
if (file->f_op && file->f_op->lseek)
return file->f_op->lseek(file->f_inode,file,offset,origin);
/* this is the default handler if no lseek handler is present */
switch (origin) { switch (origin) {
case 0: case 0:
if (offset<0) return -EINVAL; if (offset<0) return -EINVAL;
...@@ -45,59 +39,59 @@ int sys_lseek(unsigned int fd,off_t offset, int origin) ...@@ -45,59 +39,59 @@ int sys_lseek(unsigned int fd,off_t offset, int origin)
if ((tmp=file->f_inode->i_size+offset) < 0) if ((tmp=file->f_inode->i_size+offset) < 0)
return -EINVAL; return -EINVAL;
file->f_pos = tmp; file->f_pos = tmp;
break;
default:
return -EINVAL;
} }
return file->f_pos; return file->f_pos;
} }
int sys_read(unsigned int fd,char * buf,int count) int sys_read(unsigned int fd,char * buf,unsigned int count)
{ {
struct file * file; struct file * file;
struct m_inode * inode; struct inode * inode;
if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd])) if (fd>=NR_OPEN || !(file=current->filp[fd]) || !(inode=file->f_inode))
return -EINVAL; return -EBADF;
if (!(file->f_mode & 1))
return -EBADF;
if (!count) if (!count)
return 0; return 0;
verify_area(buf,count); verify_area(buf,count);
inode = file->f_inode; if (file->f_op && file->f_op->read)
return file->f_op->read(inode,file,buf,count);
/* these are the default read-functions */
if (inode->i_pipe) if (inode->i_pipe)
return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO; return pipe_read(inode,file,buf,count);
if (S_ISCHR(inode->i_mode)) if (S_ISCHR(inode->i_mode))
return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos); return char_read(inode,file,buf,count);
if (S_ISBLK(inode->i_mode)) if (S_ISBLK(inode->i_mode))
return block_read(inode->i_zone[0],&file->f_pos,buf,count); return block_read(inode,file,buf,count);
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) { if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode))
if (count+file->f_pos > inode->i_size) return minix_file_read(inode,file,buf,count);
count = inode->i_size - file->f_pos;
if (count<=0)
return 0;
return file_read(inode,file,buf,count);
}
printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode); printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL; return -EINVAL;
} }
int sys_write(unsigned int fd,char * buf,int count) int sys_write(unsigned int fd,char * buf,unsigned int count)
{ {
struct file * file; struct file * file;
struct m_inode * inode; struct inode * inode;
if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd])) if (fd>=NR_OPEN || !(file=current->filp[fd]) || !(inode=file->f_inode))
return -EINVAL; return -EBADF;
if (!(file->f_mode&2))
return -EBADF;
if (!count) if (!count)
return 0; return 0;
inode=file->f_inode; if (file->f_op && file->f_op->write)
return file->f_op->write(inode,file,buf,count);
/* these are the default read-functions */
if (inode->i_pipe) if (inode->i_pipe)
return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO; return pipe_write(inode,file,buf,count);
if (S_ISCHR(inode->i_mode)) if (S_ISCHR(inode->i_mode))
return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos); return char_write(inode,file,buf,count);
if (S_ISBLK(inode->i_mode)) if (S_ISBLK(inode->i_mode))
return block_write(inode->i_zone[0],&file->f_pos,buf,count); return block_write(inode,file,buf,count);
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode))
return file_write(inode,file,buf,count); return minix_file_write(inode,file,buf,count);
printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode); printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL; return -EINVAL;
} }
...@@ -79,18 +79,18 @@ static void free_wait(select_table * p) ...@@ -79,18 +79,18 @@ static void free_wait(select_table * p)
p->nr = 0; p->nr = 0;
} }
static struct tty_struct * get_tty(struct m_inode * inode) static struct tty_struct * get_tty(struct inode * inode)
{ {
int major, minor; int major, minor;
if (!S_ISCHR(inode->i_mode)) if (!S_ISCHR(inode->i_mode))
return NULL; return NULL;
if ((major = MAJOR(inode->i_zone[0])) != 5 && major != 4) if ((major = MAJOR(inode->i_rdev)) != 5 && major != 4)
return NULL; return NULL;
if (major == 5) if (major == 5)
minor = current->tty; minor = current->tty;
else else
minor = MINOR(inode->i_zone[0]); minor = MINOR(inode->i_rdev);
if (minor < 0) if (minor < 0)
return NULL; return NULL;
return TTY_TABLE(minor); return TTY_TABLE(minor);
...@@ -100,7 +100,7 @@ static struct tty_struct * get_tty(struct m_inode * inode) ...@@ -100,7 +100,7 @@ static struct tty_struct * get_tty(struct m_inode * inode)
* The check_XX functions check out a file. We know it's either * The check_XX functions check out a file. We know it's either
* a pipe, a character device or a fifo (fifo's not implemented) * a pipe, a character device or a fifo (fifo's not implemented)
*/ */
static int check_in(select_table * wait, struct m_inode * inode) static int check_in(select_table * wait, struct inode * inode)
{ {
struct tty_struct * tty; struct tty_struct * tty;
...@@ -110,14 +110,14 @@ static int check_in(select_table * wait, struct m_inode * inode) ...@@ -110,14 +110,14 @@ static int check_in(select_table * wait, struct m_inode * inode)
else else
add_wait(&tty->secondary->proc_list, wait); add_wait(&tty->secondary->proc_list, wait);
else if (inode->i_pipe) else if (inode->i_pipe)
if (!PIPE_EMPTY(*inode)) if (!PIPE_EMPTY(*inode) || inode->i_count < 2)
return 1; return 1;
else else
add_wait(&inode->i_wait, wait); add_wait(&inode->i_wait, wait);
return 0; return 0;
} }
static int check_out(select_table * wait, struct m_inode * inode) static int check_out(select_table * wait, struct inode * inode)
{ {
struct tty_struct * tty; struct tty_struct * tty;
...@@ -134,7 +134,7 @@ static int check_out(select_table * wait, struct m_inode * inode) ...@@ -134,7 +134,7 @@ static int check_out(select_table * wait, struct m_inode * inode)
return 0; return 0;
} }
static int check_ex(select_table * wait, struct m_inode * inode) static int check_ex(select_table * wait, struct inode * inode)
{ {
struct tty_struct * tty; struct tty_struct * tty;
...@@ -198,7 +198,7 @@ int do_select(fd_set in, fd_set out, fd_set ex, ...@@ -198,7 +198,7 @@ int do_select(fd_set in, fd_set out, fd_set ex,
} }
} }
if (!(current->signal & ~current->blocked) && if (!(current->signal & ~current->blocked) &&
(wait_table.nr || current->timeout) && !count) { current->timeout && !count) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
free_wait(&wait_table); free_wait(&wait_table);
...@@ -224,7 +224,11 @@ int sys_select( unsigned long *buffer ) ...@@ -224,7 +224,11 @@ int sys_select( unsigned long *buffer )
struct timeval *tvp; struct timeval *tvp;
unsigned long timeout; unsigned long timeout;
mask = ~((~0) << get_fs_long(buffer++)); mask = get_fs_long(buffer++);
if (mask >= 32)
mask = ~0;
else
mask = ~((~0) << mask);
inp = (fd_set *) get_fs_long(buffer++); inp = (fd_set *) get_fs_long(buffer++);
outp = (fd_set *) get_fs_long(buffer++); outp = (fd_set *) get_fs_long(buffer++);
exp = (fd_set *) get_fs_long(buffer++); exp = (fd_set *) get_fs_long(buffer++);
......
...@@ -12,19 +12,19 @@ ...@@ -12,19 +12,19 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/segment.h> #include <asm/segment.h>
static void cp_stat(struct m_inode * inode, struct stat * statbuf) static void cp_stat(struct inode * inode, struct stat * statbuf)
{ {
struct stat tmp; struct stat tmp;
int i; int i;
verify_area(statbuf,sizeof (struct stat)); verify_area(statbuf,sizeof (struct stat));
tmp.st_dev = inode->i_dev; tmp.st_dev = inode->i_dev;
tmp.st_ino = inode->i_num; tmp.st_ino = inode->i_ino;
tmp.st_mode = inode->i_mode; tmp.st_mode = inode->i_mode;
tmp.st_nlink = inode->i_nlinks; tmp.st_nlink = inode->i_nlink;
tmp.st_uid = inode->i_uid; tmp.st_uid = inode->i_uid;
tmp.st_gid = inode->i_gid; tmp.st_gid = inode->i_gid;
tmp.st_rdev = inode->i_zone[0]; tmp.st_rdev = inode->i_rdev;
tmp.st_size = inode->i_size; tmp.st_size = inode->i_size;
tmp.st_atime = inode->i_atime; tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime; tmp.st_mtime = inode->i_mtime;
...@@ -35,7 +35,7 @@ static void cp_stat(struct m_inode * inode, struct stat * statbuf) ...@@ -35,7 +35,7 @@ static void cp_stat(struct m_inode * inode, struct stat * statbuf)
int sys_stat(char * filename, struct stat * statbuf) int sys_stat(char * filename, struct stat * statbuf)
{ {
struct m_inode * inode; struct inode * inode;
if (!(inode=namei(filename))) if (!(inode=namei(filename)))
return -ENOENT; return -ENOENT;
...@@ -46,7 +46,7 @@ int sys_stat(char * filename, struct stat * statbuf) ...@@ -46,7 +46,7 @@ int sys_stat(char * filename, struct stat * statbuf)
int sys_lstat(char * filename, struct stat * statbuf) int sys_lstat(char * filename, struct stat * statbuf)
{ {
struct m_inode * inode; struct inode * inode;
if (!(inode = lnamei(filename))) if (!(inode = lnamei(filename)))
return -ENOENT; return -ENOENT;
...@@ -58,7 +58,7 @@ int sys_lstat(char * filename, struct stat * statbuf) ...@@ -58,7 +58,7 @@ int sys_lstat(char * filename, struct stat * statbuf)
int sys_fstat(unsigned int fd, struct stat * statbuf) int sys_fstat(unsigned int fd, struct stat * statbuf)
{ {
struct file * f; struct file * f;
struct m_inode * inode; struct inode * inode;
if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode)) if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
return -EBADF; return -EBADF;
...@@ -68,30 +68,16 @@ int sys_fstat(unsigned int fd, struct stat * statbuf) ...@@ -68,30 +68,16 @@ int sys_fstat(unsigned int fd, struct stat * statbuf)
int sys_readlink(const char * path, char * buf, int bufsiz) int sys_readlink(const char * path, char * buf, int bufsiz)
{ {
struct m_inode * inode; struct inode * inode;
struct buffer_head * bh;
int i;
char c;
if (bufsiz <= 0) if (bufsiz <= 0)
return -EBADF; return -EINVAL;
if (bufsiz > 1023)
bufsiz = 1023;
verify_area(buf,bufsiz); verify_area(buf,bufsiz);
if (!(inode = lnamei(path))) if (!(inode = lnamei(path)))
return -ENOENT; return -ENOENT;
if (inode->i_zone[0]) if (!inode->i_op || !inode->i_op->readlink) {
bh = bread(inode->i_dev, inode->i_zone[0]); iput(inode);
else return -EINVAL;
bh = NULL;
iput(inode);
if (!bh)
return 0;
i = 0;
while (i<bufsiz && (c = bh->b_data[i])) {
i++;
put_fs_byte(c,buf++);
} }
brelse(bh); return inode->i_op->readlink(inode,buf,bufsiz);
return i;
} }
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -82,15 +83,15 @@ void put_super(int dev) ...@@ -82,15 +83,15 @@ void put_super(int dev)
} }
if (!(sb = get_super(dev))) if (!(sb = get_super(dev)))
return; return;
if (sb->s_imount) { if (sb->s_covered) {
printk("Mounted disk changed - tssk, tssk\n\r"); printk("Mounted disk changed - tssk, tssk\n\r");
return; return;
} }
lock_super(sb); lock_super(sb);
sb->s_dev = 0; sb->s_dev = 0;
for(i=0;i<I_MAP_SLOTS;i++) for(i=0;i<MINIX_I_MAP_SLOTS;i++)
brelse(sb->s_imap[i]); brelse(sb->s_imap[i]);
for(i=0;i<Z_MAP_SLOTS;i++) for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
brelse(sb->s_zmap[i]); brelse(sb->s_zmap[i]);
free_super(sb); free_super(sb);
return; return;
...@@ -114,8 +115,8 @@ static struct super_block * read_super(int dev) ...@@ -114,8 +115,8 @@ static struct super_block * read_super(int dev)
break; break;
} }
s->s_dev = dev; s->s_dev = dev;
s->s_isup = NULL; s->s_mounted = NULL;
s->s_imount = NULL; s->s_covered = NULL;
s->s_time = 0; s->s_time = 0;
s->s_rd_only = 0; s->s_rd_only = 0;
s->s_dirt = 0; s->s_dirt = 0;
...@@ -125,17 +126,17 @@ static struct super_block * read_super(int dev) ...@@ -125,17 +126,17 @@ static struct super_block * read_super(int dev)
free_super(s); free_super(s);
return NULL; return NULL;
} }
*((struct d_super_block *) s) = *((struct minix_super_block *) s) =
*((struct d_super_block *) bh->b_data); *((struct minix_super_block *) bh->b_data);
brelse(bh); brelse(bh);
if (s->s_magic != SUPER_MAGIC) { if (s->s_magic != MINIX_SUPER_MAGIC) {
s->s_dev = 0; s->s_dev = 0;
free_super(s); free_super(s);
return NULL; return NULL;
} }
for (i=0;i<I_MAP_SLOTS;i++) for (i=0;i < MINIX_I_MAP_SLOTS;i++)
s->s_imap[i] = NULL; s->s_imap[i] = NULL;
for (i=0;i<Z_MAP_SLOTS;i++) for (i=0;i < MINIX_Z_MAP_SLOTS;i++)
s->s_zmap[i] = NULL; s->s_zmap[i] = NULL;
block=2; block=2;
for (i=0 ; i < s->s_imap_blocks ; i++) for (i=0 ; i < s->s_imap_blocks ; i++)
...@@ -149,9 +150,9 @@ static struct super_block * read_super(int dev) ...@@ -149,9 +150,9 @@ static struct super_block * read_super(int dev)
else else
break; break;
if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) { if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
for(i=0;i<I_MAP_SLOTS;i++) for(i=0;i<MINIX_I_MAP_SLOTS;i++)
brelse(s->s_imap[i]); brelse(s->s_imap[i]);
for(i=0;i<Z_MAP_SLOTS;i++) for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
brelse(s->s_zmap[i]); brelse(s->s_zmap[i]);
s->s_dev=0; s->s_dev=0;
free_super(s); free_super(s);
...@@ -165,13 +166,13 @@ static struct super_block * read_super(int dev) ...@@ -165,13 +166,13 @@ static struct super_block * read_super(int dev)
int sys_umount(char * dev_name) int sys_umount(char * dev_name)
{ {
struct m_inode * inode; struct inode * inode;
struct super_block * sb; struct super_block * sb;
int dev; int dev;
if (!(inode=namei(dev_name))) if (!(inode=namei(dev_name)))
return -ENOENT; return -ENOENT;
dev = inode->i_zone[0]; dev = inode->i_rdev;
if (!S_ISBLK(inode->i_mode)) { if (!S_ISBLK(inode->i_mode)) {
iput(inode); iput(inode);
return -ENOTBLK; return -ENOTBLK;
...@@ -179,18 +180,21 @@ int sys_umount(char * dev_name) ...@@ -179,18 +180,21 @@ int sys_umount(char * dev_name)
iput(inode); iput(inode);
if (dev==ROOT_DEV) if (dev==ROOT_DEV)
return -EBUSY; return -EBUSY;
if (!(sb=get_super(dev)) || !(sb->s_imount)) if (!(sb=get_super(dev)) || !(sb->s_covered))
return -ENOENT; return -ENOENT;
if (!sb->s_imount->i_mount) if (!sb->s_covered->i_mount)
printk("Mounted inode has i_mount=0\n"); printk("Mounted inode has i_mount=0\n");
for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++) for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
if (inode->i_dev==dev && inode->i_count) if (inode->i_dev==dev && inode->i_count)
if (inode == sb->s_mounted && inode->i_count == 1)
continue;
else
return -EBUSY; return -EBUSY;
sb->s_imount->i_mount=0; sb->s_covered->i_mount=0;
iput(sb->s_imount); iput(sb->s_covered);
sb->s_imount = NULL; sb->s_covered = NULL;
iput(sb->s_isup); iput(sb->s_mounted);
sb->s_isup = NULL; sb->s_mounted = NULL;
put_super(dev); put_super(dev);
sync_dev(dev); sync_dev(dev);
return 0; return 0;
...@@ -198,13 +202,13 @@ int sys_umount(char * dev_name) ...@@ -198,13 +202,13 @@ int sys_umount(char * dev_name)
int sys_mount(char * dev_name, char * dir_name, int rw_flag) int sys_mount(char * dev_name, char * dir_name, int rw_flag)
{ {
struct m_inode * dev_i, * dir_i; struct inode * dev_i, * dir_i;
struct super_block * sb; struct super_block * sb;
int dev; int dev;
if (!(dev_i=namei(dev_name))) if (!(dev_i=namei(dev_name)))
return -ENOENT; return -ENOENT;
dev = dev_i->i_zone[0]; dev = dev_i->i_rdev;
if (!S_ISBLK(dev_i->i_mode)) { if (!S_ISBLK(dev_i->i_mode)) {
iput(dev_i); iput(dev_i);
return -EPERM; return -EPERM;
...@@ -212,7 +216,7 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag) ...@@ -212,7 +216,7 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag)
iput(dev_i); iput(dev_i);
if (!(dir_i=namei(dir_name))) if (!(dir_i=namei(dir_name)))
return -ENOENT; return -ENOENT;
if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) { if (dir_i->i_count != 1 || dir_i->i_ino == MINIX_ROOT_INO) {
iput(dir_i); iput(dir_i);
return -EBUSY; return -EBUSY;
} }
...@@ -224,7 +228,7 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag) ...@@ -224,7 +228,7 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag)
iput(dir_i); iput(dir_i);
return -EBUSY; return -EBUSY;
} }
if (sb->s_imount) { if (sb->s_covered) {
iput(dir_i); iput(dir_i);
return -EBUSY; return -EBUSY;
} }
...@@ -232,7 +236,11 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag) ...@@ -232,7 +236,11 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag)
iput(dir_i); iput(dir_i);
return -EPERM; return -EPERM;
} }
sb->s_imount=dir_i; if (!(sb->s_mounted = iget(dev,MINIX_ROOT_INO))) {
iput(dir_i);
return -EPERM;
}
sb->s_covered=dir_i;
dir_i->i_mount=1; dir_i->i_mount=1;
dir_i->i_dirt=1; /* NOTE! we don't iput(dir_i) */ dir_i->i_dirt=1; /* NOTE! we don't iput(dir_i) */
return 0; /* we do that in umount */ return 0; /* we do that in umount */
...@@ -242,9 +250,9 @@ void mount_root(void) ...@@ -242,9 +250,9 @@ void mount_root(void)
{ {
int i,free; int i,free;
struct super_block * p; struct super_block * p;
struct m_inode * mi; struct inode * mi;
if (32 != sizeof (struct d_inode)) if (32 != sizeof (struct minix_inode))
panic("bad i-node size"); panic("bad i-node size");
for(i=0;i<NR_FILE;i++) for(i=0;i<NR_FILE;i++)
file_table[i].f_count=0; file_table[i].f_count=0;
...@@ -259,10 +267,10 @@ void mount_root(void) ...@@ -259,10 +267,10 @@ void mount_root(void)
} }
if (!(p=read_super(ROOT_DEV))) if (!(p=read_super(ROOT_DEV)))
panic("Unable to mount root"); panic("Unable to mount root");
if (!(mi=iget(ROOT_DEV,ROOT_INO))) if (!(mi=iget(ROOT_DEV,MINIX_ROOT_INO)))
panic("Unable to read root i-node"); panic("Unable to read root i-node");
mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */ mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
p->s_isup = p->s_imount = mi; p->s_mounted = p->s_covered = mi;
current->pwd = mi; current->pwd = mi;
current->root = mi; current->root = mi;
free=0; free=0;
......
#define outb(value,port) \ static void inline outb(char value, unsigned short port)
__asm__ ("outb %%al,%%dx"::"a" (value),"d" (port)) {
__asm__ volatile ("outb %0,%1"::"a" (value),"d" (port));
}
static void inline outb_p(char value, unsigned short port)
{
__asm__ volatile ("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"
::"a" (value),"d" (port));
}
#define inb(port) ({ \ static unsigned char inline inb(unsigned short port)
unsigned char _v; \ {
__asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \ unsigned char _v;
_v; \ __asm__ volatile ("inb %1,%0":"=a" (_v):"d" (port));
}) return _v;
}
#define outb_p(value,port) \ static unsigned char inb_p(unsigned short port)
__asm__ ("outb %%al,%%dx\n" \ {
"\tjmp 1f\n" \ unsigned char _v;
"1:\tjmp 1f\n" \ __asm__ volatile ("inb %1,%0\n"
"1:"::"a" (value),"d" (port)) "\tjmp 1f\n"
"1:\tjmp 1f\n"
#define inb_p(port) ({ \ "1:":"=a" (_v):"d" ((unsigned short) port));
unsigned char _v; \ return _v;
__asm__ volatile ("inb %%dx,%%al\n" \ }
"\tjmp 1f\n" \
"1:\tjmp 1f\n" \
"1:":"=a" (_v):"d" (port)); \
_v; \
})
...@@ -2,7 +2,7 @@ extern inline unsigned char get_fs_byte(const char * addr) ...@@ -2,7 +2,7 @@ extern inline unsigned char get_fs_byte(const char * addr)
{ {
unsigned register char _v; unsigned register char _v;
__asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr)); __asm__ ("movb %%fs:%1,%0":"=q" (_v):"m" (*addr));
return _v; return _v;
} }
...@@ -24,7 +24,7 @@ extern inline unsigned long get_fs_long(const unsigned long *addr) ...@@ -24,7 +24,7 @@ extern inline unsigned long get_fs_long(const unsigned long *addr)
extern inline void put_fs_byte(char val,char *addr) extern inline void put_fs_byte(char val,char *addr)
{ {
__asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr)); __asm__ ("movb %0,%%fs:%1"::"q" (val),"m" (*addr));
} }
extern inline void put_fs_word(short val,short * addr) extern inline void put_fs_word(short val,short * addr)
...@@ -41,25 +41,25 @@ __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr)); ...@@ -41,25 +41,25 @@ __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
* Someone who knows GNU asm better than I should double check the followig. * Someone who knows GNU asm better than I should double check the followig.
* It seems to work, but I don't know if I'm doing something subtly wrong. * It seems to work, but I don't know if I'm doing something subtly wrong.
* --- TYT, 11/24/91 * --- TYT, 11/24/91
* [ nothing wrong here, Linus ] * [ nothing wrong here, Linus: I just changed the ax to be any reg ]
*/ */
extern inline unsigned long get_fs() extern inline unsigned long get_fs()
{ {
unsigned short _v; unsigned short _v;
__asm__("mov %%fs,%%ax":"=a" (_v):); __asm__("mov %%fs,%0":"=r" (_v):);
return _v; return _v;
} }
extern inline unsigned long get_ds() extern inline unsigned long get_ds()
{ {
unsigned short _v; unsigned short _v;
__asm__("mov %%ds,%%ax":"=a" (_v):); __asm__("mov %%ds,%0":"=r" (_v):);
return _v; return _v;
} }
extern inline void set_fs(unsigned long val) extern inline void set_fs(unsigned long val)
{ {
__asm__("mov %0,%%fs"::"a" ((unsigned short) val)); __asm__("mov %0,%%fs"::"r" ((unsigned short) val));
} }
...@@ -24,11 +24,11 @@ __asm__ ("movw %%dx,%%ax\n\t" \ ...@@ -24,11 +24,11 @@ __asm__ ("movw %%dx,%%ax\n\t" \
"movw %0,%%dx\n\t" \ "movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \ "movl %%eax,%1\n\t" \
"movl %%edx,%2" \ "movl %%edx,%2" \
: \ :: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \ "m" (*((char *) (gate_addr))), \
"o" (*((char *) (gate_addr))), \ "m" (*(4+(char *) (gate_addr))), \
"o" (*(4+(char *) (gate_addr))), \ "d" ((char *) (addr)),"a" (0x00080000) \
"d" ((char *) (addr)),"a" (0x00080000)) :"ax","dx")
#define set_intr_gate(n,addr) \ #define set_intr_gate(n,addr) \
_set_gate(&idt[n],14,0,addr) _set_gate(&idt[n],14,0,addr)
......
...@@ -56,6 +56,7 @@ extern int errno; ...@@ -56,6 +56,7 @@ extern int errno;
#define ENOLCK 37 #define ENOLCK 37
#define ENOSYS 38 #define ENOSYS 38
#define ENOTEMPTY 39 #define ENOTEMPTY 39
#define ELOOP 40
/* Should never be seen by user programs */ /* Should never be seen by user programs */
#define ERESTARTSYS 512 #define ERESTARTSYS 512
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#define O_NOCTTY 00400 /* not fcntl */ #define O_NOCTTY 00400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */ #define O_TRUNC 01000 /* not fcntl */
#define O_APPEND 02000 #define O_APPEND 02000
#define O_NONBLOCK 04000 /* not fcntl */ #define O_NONBLOCK 04000
#define O_NDELAY O_NONBLOCK #define O_NDELAY O_NONBLOCK
/* Defines for fcntl-commands. Note that currently /* Defines for fcntl-commands. Note that currently
......
#ifndef _CONFIG_H #ifndef _CONFIG_H
#define _CONFIG_H #define _CONFIG_H
/*
* Define this if you want the math-emulation code: if this is undefined,
* the kernel will be smaller, but you'll get FPU exceptions if you don't
* have a 387 and are trying to use math.
*/
#define KERNEL_MATH_EMULATION
/* /*
* Defines for what uname() should return * Defines for what uname() should return
*/ */
...@@ -14,7 +23,7 @@ ...@@ -14,7 +23,7 @@
#define DEF_INITSEG 0x9000 #define DEF_INITSEG 0x9000
#define DEF_SYSSEG 0x1000 #define DEF_SYSSEG 0x1000
#define DEF_SETUPSEG 0x9020 #define DEF_SETUPSEG 0x9020
#define DEF_SYSSIZE 0x3000 #define DEF_SYSSIZE 0x4000
/* /*
* The root-device is no longer hard-coded. You can change the default * The root-device is no longer hard-coded. You can change the default
......
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3) #define IS_SEEKABLE(x) ((x)>=1 && (x)<=3)
#define MAY_EXEC 1
#define MAY_WRITE 2
#define MAY_READ 4
#define READ 0 #define READ 0
#define WRITE 1 #define WRITE 1
#define READA 2 /* read-ahead - don't pause */ #define READA 2 /* read-ahead - don't pause */
...@@ -33,15 +37,8 @@ void buffer_init(long buffer_end); ...@@ -33,15 +37,8 @@ void buffer_init(long buffer_end);
#define MAJOR(a) (((unsigned)(a))>>8) #define MAJOR(a) (((unsigned)(a))>>8)
#define MINOR(a) ((a)&0xff) #define MINOR(a) ((a)&0xff)
#define NAME_LEN 14
#define ROOT_INO 1
#define I_MAP_SLOTS 8
#define Z_MAP_SLOTS 8
#define SUPER_MAGIC 0x137F
#define NR_OPEN 20 #define NR_OPEN 20
#define NR_INODE 64 #define NR_INODE 128
#define NR_FILE 64 #define NR_FILE 64
#define NR_SUPER 8 #define NR_SUPER 8
#define NR_HASH 307 #define NR_HASH 307
...@@ -52,13 +49,10 @@ void buffer_init(long buffer_end); ...@@ -52,13 +49,10 @@ void buffer_init(long buffer_end);
#define NULL ((void *) 0) #define NULL ((void *) 0)
#endif #endif
#define INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct d_inode)))
#define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry)))
#define PIPE_READ_WAIT(inode) ((inode).i_wait) #define PIPE_READ_WAIT(inode) ((inode).i_wait)
#define PIPE_WRITE_WAIT(inode) ((inode).i_wait2) #define PIPE_WRITE_WAIT(inode) ((inode).i_wait2)
#define PIPE_HEAD(inode) ((inode).i_zone[0]) #define PIPE_HEAD(inode) ((inode).i_data[0])
#define PIPE_TAIL(inode) ((inode).i_zone[1]) #define PIPE_TAIL(inode) ((inode).i_data[1])
#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1)) #define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))
#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode)) #define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode))
#define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1)) #define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
...@@ -85,31 +79,23 @@ struct buffer_head { ...@@ -85,31 +79,23 @@ struct buffer_head {
struct buffer_head * b_next_free; struct buffer_head * b_next_free;
}; };
struct d_inode { struct inode {
unsigned short i_mode; dev_t i_dev;
unsigned short i_uid; ino_t i_ino;
unsigned long i_size; umode_t i_mode;
unsigned long i_time; nlink_t i_nlink;
unsigned char i_gid; uid_t i_uid;
unsigned char i_nlinks; gid_t i_gid;
unsigned short i_zone[9]; dev_t i_rdev;
}; off_t i_size;
time_t i_atime;
struct m_inode { time_t i_mtime;
unsigned short i_mode; time_t i_ctime;
unsigned short i_uid; unsigned long i_data[16];
unsigned long i_size; struct inode_operations * i_op;
unsigned long i_mtime; struct super_block * i_sb;
unsigned char i_gid;
unsigned char i_nlinks;
unsigned short i_zone[9];
/* these are in memory also */
struct task_struct * i_wait; struct task_struct * i_wait;
struct task_struct * i_wait2; /* for pipes */ struct task_struct * i_wait2; /* for pipes */
unsigned long i_atime;
unsigned long i_ctime;
unsigned short i_dev;
unsigned short i_num;
unsigned short i_count; unsigned short i_count;
unsigned char i_lock; unsigned char i_lock;
unsigned char i_dirt; unsigned char i_dirt;
...@@ -123,7 +109,8 @@ struct file { ...@@ -123,7 +109,8 @@ struct file {
unsigned short f_mode; unsigned short f_mode;
unsigned short f_flags; unsigned short f_flags;
unsigned short f_count; unsigned short f_count;
struct m_inode * f_inode; struct inode * f_inode;
struct file_operations * f_op;
off_t f_pos; off_t f_pos;
}; };
...@@ -140,8 +127,8 @@ struct super_block { ...@@ -140,8 +127,8 @@ struct super_block {
struct buffer_head * s_imap[8]; struct buffer_head * s_imap[8];
struct buffer_head * s_zmap[8]; struct buffer_head * s_zmap[8];
unsigned short s_dev; unsigned short s_dev;
struct m_inode * s_isup; struct inode * s_covered;
struct m_inode * s_imount; struct inode * s_mounted;
unsigned long s_time; unsigned long s_time;
struct task_struct * s_wait; struct task_struct * s_wait;
unsigned char s_lock; unsigned char s_lock;
...@@ -149,23 +136,29 @@ struct super_block { ...@@ -149,23 +136,29 @@ struct super_block {
unsigned char s_dirt; unsigned char s_dirt;
}; };
struct d_super_block { struct file_operations {
unsigned short s_ninodes; int (*lseek) (struct inode *, struct file *, off_t, int);
unsigned short s_nzones; int (*read) (struct inode *, struct file *, char *, int);
unsigned short s_imap_blocks; int (*write) (struct inode *, struct file *, char *, int);
unsigned short s_zmap_blocks;
unsigned short s_firstdatazone;
unsigned short s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
}; };
struct dir_entry { struct inode_operations {
unsigned short inode; int (*create) (struct inode *,const char *,int,int,struct inode **);
char name[NAME_LEN]; int (*lookup) (struct inode *,const char *,int,struct inode **);
int (*link) (struct inode *,struct inode *,const char *,int);
int (*unlink) (struct inode *,const char *,int);
int (*symlink) (struct inode *,const char *,int,const char *);
int (*mkdir) (struct inode *,const char *,int,int);
int (*rmdir) (struct inode *,const char *,int);
int (*mknod) (struct inode *,const char *,int,int,int);
int (*rename) (struct inode *,const char *,int,struct inode *,const char *,int);
int (*readlink) (struct inode *,char *,int);
int (*open) (struct inode *, struct file *);
void (*release) (struct inode *, struct file *);
struct inode * (*follow_link) (struct inode *, struct inode *);
}; };
extern struct m_inode inode_table[NR_INODE]; extern struct inode inode_table[NR_INODE];
extern struct file file_table[NR_FILE]; extern struct file file_table[NR_FILE];
extern struct super_block super_block[NR_SUPER]; extern struct super_block super_block[NR_SUPER];
extern struct buffer_head * start_buffer; extern struct buffer_head * start_buffer;
...@@ -176,35 +169,41 @@ extern int floppy_change(unsigned int nr); ...@@ -176,35 +169,41 @@ extern int floppy_change(unsigned int nr);
extern int ticks_to_floppy_on(unsigned int dev); extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev); extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev); extern void floppy_off(unsigned int dev);
extern void truncate(struct m_inode * inode); extern void truncate(struct inode * inode);
extern void sync_inodes(void); extern void sync_inodes(void);
extern void wait_on(struct m_inode * inode); extern void wait_on(struct inode * inode);
extern int bmap(struct m_inode * inode,int block); extern int bmap(struct inode * inode,int block);
extern int create_block(struct m_inode * inode,int block); extern struct inode * namei(const char * pathname);
extern struct m_inode * namei(const char * pathname); extern struct inode * lnamei(const char * pathname);
extern struct m_inode * lnamei(const char * pathname);
extern int open_namei(const char * pathname, int flag, int mode, extern int open_namei(const char * pathname, int flag, int mode,
struct m_inode ** res_inode); struct inode ** res_inode);
extern void iput(struct m_inode * inode); extern void iput(struct inode * inode);
extern struct m_inode * iget(int dev,int nr); extern struct inode * iget(int dev,int nr);
extern struct m_inode * get_empty_inode(void); extern struct inode * get_empty_inode(void);
extern struct m_inode * get_pipe_inode(void); extern struct inode * get_pipe_inode(void);
extern struct buffer_head * get_hash_table(int dev, int block); extern struct buffer_head * get_hash_table(int dev, int block);
extern struct buffer_head * getblk(int dev, int block); extern struct buffer_head * getblk(int dev, int block);
extern void ll_rw_block(int rw, struct buffer_head * bh); extern void ll_rw_block(int rw, struct buffer_head * bh);
extern void ll_rw_page(int rw, int dev, int nr, char * buffer); extern void ll_rw_page(int rw, int dev, int nr, char * buffer);
extern void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buffer);
extern void brelse(struct buffer_head * buf); extern void brelse(struct buffer_head * buf);
extern struct buffer_head * bread(int dev,int block); extern struct buffer_head * bread(int dev,int block);
extern void bread_page(unsigned long addr,int dev,int b[4]); extern void bread_page(unsigned long addr,int dev,int b[4]);
extern struct buffer_head * breada(int dev,int block,...); extern struct buffer_head * breada(int dev,int block,...);
extern int new_block(int dev);
extern int free_block(int dev, int block);
extern struct m_inode * new_inode(int dev);
extern void free_inode(struct m_inode * inode);
extern int sync_dev(int dev); extern int sync_dev(int dev);
extern struct super_block * get_super(int dev); extern struct super_block * get_super(int dev);
extern int ROOT_DEV; extern int ROOT_DEV;
extern void mount_root(void); extern void mount_root(void);
extern int minix_file_read(struct inode *, struct file *, char *, int);
extern int pipe_read(struct inode *, struct file *, char *, int);
extern int char_read(struct inode *, struct file *, char *, int);
extern int block_read(struct inode *, struct file *, char *, int);
extern int minix_file_write(struct inode *, struct file *, char *, int);
extern int pipe_write(struct inode *, struct file *, char *, int);
extern int char_write(struct inode *, struct file *, char *, int);
extern int block_write(struct inode *, struct file *, char *, int);
#endif #endif
...@@ -49,15 +49,17 @@ ...@@ -49,15 +49,17 @@
#define ECC_ERR 0x40 /* ? */ #define ECC_ERR 0x40 /* ? */
#define BBD_ERR 0x80 /* ? */ #define BBD_ERR 0x80 /* ? */
#define EXTENDED_PARTITION 5
struct partition { struct partition {
unsigned char boot_ind; /* 0x80 - active (unused) */ unsigned char boot_ind; /* 0x80 - active */
unsigned char head; /* ? */ unsigned char head; /* starting head */
unsigned char sector; /* ? */ unsigned char sector; /* starting sector */
unsigned char cyl; /* ? */ unsigned char cyl; /* starting cylinder */
unsigned char sys_ind; /* ? */ unsigned char sys_ind; /* What partition type */
unsigned char end_head; /* ? */ unsigned char end_head; /* end head */
unsigned char end_sector; /* ? */ unsigned char end_sector; /* end sector */
unsigned char end_cyl; /* ? */ unsigned char end_cyl; /* end cylinder */
unsigned int start_sect; /* starting sector counting from 0 */ unsigned int start_sect; /* starting sector counting from 0 */
unsigned int nr_sects; /* nr of sectors in partition */ unsigned int nr_sects; /* nr of sectors in partition */
}; };
......
...@@ -10,15 +10,6 @@ void console_print(const char * str); ...@@ -10,15 +10,6 @@ void console_print(const char * str);
int tty_write(unsigned ch,char * buf,int count); int tty_write(unsigned ch,char * buf,int count);
void * malloc(unsigned int size); void * malloc(unsigned int size);
void free_s(void * obj, int size); void free_s(void * obj, int size);
extern void hd_times_out(void);
extern void sysbeepstop(void);
extern void blank_screen(void);
extern void unblank_screen(void);
extern int beepcount;
extern int hd_timeout;
extern int blankinterval;
extern int blankcount;
#define free(x) free_s((x), 0) #define free(x) free_s((x), 0)
......
...@@ -9,20 +9,20 @@ ...@@ -9,20 +9,20 @@
#include <linux/sched.h> #include <linux/sched.h>
struct info { struct info {
long ___math_ret;
long ___orig_eip; long ___orig_eip;
long ___edi; long ___ret_from_system_call;
long ___esi;
long ___ebp;
long ___sys_call_ret;
long ___eax;
long ___ebx; long ___ebx;
long ___ecx; long ___ecx;
long ___edx; long ___edx;
long ___orig_eax; long ___esi;
long ___fs; long ___edi;
long ___es; long ___ebp;
long ___eax;
long ___ds; long ___ds;
long ___es;
long ___fs;
long ___gs;
long ___orig_eax;
long ___eip; long ___eip;
long ___cs; long ___cs;
long ___eflags; long ___eflags;
...@@ -140,6 +140,7 @@ char * ea(struct info * __info, unsigned short __code); ...@@ -140,6 +140,7 @@ char * ea(struct info * __info, unsigned short __code);
/* convert.c */ /* convert.c */
void frndint(const temp_real * __a, temp_real * __b);
void short_to_temp(const short_real * __a, temp_real * __b); void short_to_temp(const short_real * __a, temp_real * __b);
void long_to_temp(const long_real * __a, temp_real * __b); void long_to_temp(const long_real * __a, temp_real * __b);
void temp_to_short(const temp_real * __a, short_real * __b); void temp_to_short(const temp_real * __a, short_real * __b);
......
/*
* The minix filesystem constants/structures
*/
#ifndef _MINIX_FS_H
#define _MINIX_FS_H
#include <sys/types.h>
#define MINIX_NAME_LEN 14
#define MINIX_ROOT_INO 1
#define MINIX_I_MAP_SLOTS 8
#define MINIX_Z_MAP_SLOTS 8
#define MINIX_SUPER_MAGIC 0x137F
#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
#define MINIX_DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_dir_entry)))
struct minix_inode {
unsigned short i_mode;
unsigned short i_uid;
unsigned long i_size;
unsigned long i_time;
unsigned char i_gid;
unsigned char i_nlinks;
unsigned short i_zone[9];
};
struct minix_super_block {
unsigned short s_ninodes;
unsigned short s_nzones;
unsigned short s_imap_blocks;
unsigned short s_zmap_blocks;
unsigned short s_firstdatazone;
unsigned short s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
};
struct minix_dir_entry {
unsigned short inode;
char name[MINIX_NAME_LEN];
};
extern int minix_open(struct inode * inode, struct file * filp);
extern void minix_release(struct inode * inode, struct file * filp);
extern struct inode * minix_follow_link(struct inode * dir, struct inode * inode);
extern int minix_lookup(struct inode * dir,const char * name, int len,
struct inode ** result);
extern int minix_create(struct inode * dir,const char * name, int len, int mode,
struct inode ** result);
extern int minix_mkdir(struct inode * dir, const char * name, int len, int mode);
extern int minix_rmdir(struct inode * dir, const char * name, int len);
extern int minix_unlink(struct inode * dir, const char * name, int len);
extern int minix_symlink(struct inode * inode, const char * name, int len,
const char * symname);
extern int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len);
extern int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
extern int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len);
extern int minix_readlink(struct inode * inode, char * buffer, int buflen);
extern struct inode * minix_new_inode(int dev);
extern void minix_free_inode(struct inode * inode);
extern int minix_new_block(int dev);
extern int minix_free_block(int dev, int block);
extern int minix_create_block(struct inode * inode, int block);
extern int minix_bmap(struct inode * inode,int block);
extern int minix_lseek(struct inode * inode, struct file * filp, off_t offset, int origin);
extern int minix_read(struct inode * inode, struct file * filp, char * buf, int count);
extern int minix_write(struct inode * inode, struct file * filp, char * buf, int count);
extern struct inode_operations minix_inode_operations;
extern struct file_operations minix_file_operations;
#endif
...@@ -3,13 +3,19 @@ ...@@ -3,13 +3,19 @@
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
#include <linux/fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <signal.h> #include <signal.h>
extern int SWAP_DEV; extern unsigned int swap_device;
extern struct inode * swap_file;
#define read_swap_page(nr,buffer) ll_rw_page(READ,SWAP_DEV,(nr),(buffer)); extern void rw_swap_page(int rw, unsigned int nr, char * buf);
#define write_swap_page(nr,buffer) ll_rw_page(WRITE,SWAP_DEV,(nr),(buffer));
#define read_swap_page(nr,buf) \
rw_swap_page(READ,(nr),(buf))
#define write_swap_page(nr,buf) \
rw_swap_page(WRITE,(nr),(buf))
extern unsigned long get_free_page(void); extern unsigned long get_free_page(void);
extern unsigned long put_dirty_page(unsigned long page,unsigned long address); extern unsigned long put_dirty_page(unsigned long page,unsigned long address);
......
...@@ -129,12 +129,13 @@ struct task_struct { ...@@ -129,12 +129,13 @@ struct task_struct {
unsigned int flags; /* per process flags, defined below */ unsigned int flags; /* per process flags, defined below */
unsigned short used_math; unsigned short used_math;
/* file system info */ /* file system info */
int link_count;
int tty; /* -1 if no tty, so it must be signed */ int tty; /* -1 if no tty, so it must be signed */
unsigned short umask; unsigned short umask;
struct m_inode * pwd; struct inode * pwd;
struct m_inode * root; struct inode * root;
struct m_inode * executable; struct inode * executable;
struct m_inode * library; struct inode * library;
unsigned long close_on_exec; unsigned long close_on_exec;
struct file * filp[NR_OPEN]; struct file * filp[NR_OPEN];
/* ldt for this task 0 - zero 1 - cs 2 - ds&ss */ /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
...@@ -148,6 +149,10 @@ struct task_struct { ...@@ -148,6 +149,10 @@ struct task_struct {
*/ */
#define PF_ALIGNWARN 0x00000001 /* Print alignment warning msgs */ #define PF_ALIGNWARN 0x00000001 /* Print alignment warning msgs */
/* Not implemented yet, only for 486*/ /* Not implemented yet, only for 486*/
#define PF_PTRACED 0x00000010 /* set if ptrace (0) has been called. */
#define PF_VM86 0x00000020 /* set if process can execute a vm86 */
/* task. */
/* not impelmented. */
/* /*
* INIT_TASK is used to set up the first task table, touch at * INIT_TASK is used to set up the first task table, touch at
...@@ -167,7 +172,7 @@ struct task_struct { ...@@ -167,7 +172,7 @@ struct task_struct {
{0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}}, \ {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}}, \
/* flags */ 0, \ /* flags */ 0, \
/* math */ 0, \ /* math */ 0, \
/* fs info */ -1,0022,NULL,NULL,NULL,NULL,0, \ /* fs info */ 0,-1,0022,NULL,NULL,NULL,NULL,0, \
/* filp */ {NULL,}, \ /* filp */ {NULL,}, \
{ \ { \
{0,0}, \ {0,0}, \
...@@ -212,7 +217,7 @@ __asm__("str %%ax\n\t" \ ...@@ -212,7 +217,7 @@ __asm__("str %%ax\n\t" \
"subl %2,%%eax\n\t" \ "subl %2,%%eax\n\t" \
"shrl $4,%%eax" \ "shrl $4,%%eax" \
:"=a" (n) \ :"=a" (n) \
:"a" (0),"i" (FIRST_TSS_ENTRY<<3)) :"0" (0),"i" (FIRST_TSS_ENTRY<<3))
/* /*
* switch_to(n) should switch tasks to task nr n, first * switch_to(n) should switch tasks to task nr n, first
* checking that n isn't the current task, in which case it does nothing. * checking that n isn't the current task, in which case it does nothing.
...@@ -231,7 +236,8 @@ __asm__("cmpl %%ecx,_current\n\t" \ ...@@ -231,7 +236,8 @@ __asm__("cmpl %%ecx,_current\n\t" \
"clts\n" \ "clts\n" \
"1:" \ "1:" \
::"m" (*&__tmp.a),"m" (*&__tmp.b), \ ::"m" (*&__tmp.a),"m" (*&__tmp.b), \
"d" (_TSS(n)),"c" ((long) task[n])); \ "d" (_TSS(n)),"c" ((long) task[n]) \
:"cx"); \
} }
#define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000) #define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000)
...@@ -262,23 +268,28 @@ __asm__("movw %%dx,%0\n\t" \ ...@@ -262,23 +268,28 @@ __asm__("movw %%dx,%0\n\t" \
#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base ) #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 ) #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
#define _get_base(addr) ({\ static unsigned long inline _get_base(char * addr)
unsigned long __base; \ {
__asm__("movb %3,%%dh\n\t" \ unsigned long __base;
"movb %2,%%dl\n\t" \ __asm__("movb %3,%%dh\n\t"
"shll $16,%%edx\n\t" \ "movb %2,%%dl\n\t"
"movw %1,%%dx" \ "shll $16,%%edx\n\t"
:"=d" (__base) \ "movw %1,%%dx"
:"m" (*((addr)+2)), \ :"=&d" (__base)
"m" (*((addr)+4)), \ :"m" (*((addr)+2)),
"m" (*((addr)+7))); \ "m" (*((addr)+4)),
__base;}) "m" (*((addr)+7)));
return __base;
}
#define get_base(ldt) _get_base( ((char *)&(ldt)) ) #define get_base(ldt) _get_base( ((char *)&(ldt)) )
#define get_limit(segment) ({ \ static unsigned long inline get_limit(unsigned long segment)
unsigned long __limit; \ {
__asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \ unsigned long __limit;
__limit;}) __asm__("lsll %1,%0"
:"=r" (__limit):"r" (segment));
return __limit+1;
}
#endif #endif
...@@ -89,6 +89,8 @@ extern int sys_symlink(); ...@@ -89,6 +89,8 @@ extern int sys_symlink();
extern int sys_lstat(); extern int sys_lstat();
extern int sys_readlink(); extern int sys_readlink();
extern int sys_uselib(); extern int sys_uselib();
extern int sys_swapon();
extern int sys_reboot();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read, fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link, sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
...@@ -105,7 +107,7 @@ sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask, ...@@ -105,7 +107,7 @@ sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname, sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname,
sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday, sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday,
sys_settimeofday, sys_getgroups, sys_setgroups, sys_select, sys_symlink, sys_settimeofday, sys_getgroups, sys_setgroups, sys_select, sys_symlink,
sys_lstat, sys_readlink, sys_uselib }; sys_lstat, sys_readlink, sys_uselib, sys_swapon, sys_reboot };
/* So we don't have to do any more manual updating.... */ /* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr); int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
#ifndef _TIMER_H
#define _TIMER_H
/*
* DON'T CHANGE THESE!! Most of them are hardcoded into some assembly language
* as well as being defined here.
*/
/*
* The timers are:
*
* BLANK_TIMER console screen-saver timer
*
* BEEP_TIMER console beep timer
*
* SERx_TIMER serial incoming characters timer
*
* SERx_TIMEOUT timeout for serial writes
*
* HD_TIMER harddisk timer
*
* FLOPPY_TIMER floppy disk timer (not used right now)
*/
#define BLANK_TIMER 0
#define BEEP_TIMER 1
#define SER1_TIMER 2
#define SER2_TIMER 3
#define SER1_TIMEOUT 8
#define SER2_TIMEOUT 9
#define HD_TIMER 16
#define FLOPPY_TIMER 17
struct timer_struct {
unsigned long expires;
void (*fn)(void);
};
extern unsigned long timer_active;
extern struct timer_struct timer_table[32];
#endif
...@@ -60,6 +60,7 @@ struct tty_struct { ...@@ -60,6 +60,7 @@ struct tty_struct {
int pgrp; int pgrp;
int session; int session;
int stopped; int stopped;
struct winsize winsize;
void (*write)(struct tty_struct * tty); void (*write)(struct tty_struct * tty);
struct tty_queue *read_q; struct tty_queue *read_q;
struct tty_queue *write_q; struct tty_queue *write_q;
...@@ -68,6 +69,9 @@ struct tty_struct { ...@@ -68,6 +69,9 @@ struct tty_struct {
extern struct tty_struct tty_table[]; extern struct tty_struct tty_table[];
extern int fg_console; extern int fg_console;
extern unsigned long video_num_columns;
extern unsigned long video_num_lines;
#define TTY_TABLE(nr) \ #define TTY_TABLE(nr) \
(tty_table + ((nr) ? (((nr) < 64)? (nr)-1:(nr)) : fg_console)) (tty_table + ((nr) ? (((nr) < 64)? (nr)-1:(nr)) : fg_console))
...@@ -84,7 +88,7 @@ void rs_init(void); ...@@ -84,7 +88,7 @@ void rs_init(void);
void con_init(void); void con_init(void);
void tty_init(void); void tty_init(void);
int tty_read(unsigned c, char * buf, int n); int tty_read(unsigned c, char * buf, int n, unsigned short flags);
int tty_write(unsigned c, char * buf, int n); int tty_write(unsigned c, char * buf, int n);
void con_write(struct tty_struct * tty); void con_write(struct tty_struct * tty);
...@@ -94,6 +98,6 @@ void spty_write(struct tty_struct * tty); ...@@ -94,6 +98,6 @@ void spty_write(struct tty_struct * tty);
void copy_to_cooked(struct tty_struct * tty); void copy_to_cooked(struct tty_struct * tty);
void update_screen(void); void update_screen(int new_console);
#endif #endif
...@@ -33,6 +33,26 @@ typedef unsigned int sigset_t; /* 32 bits */ ...@@ -33,6 +33,26 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIGTTIN 21 #define SIGTTIN 21
#define SIGTTOU 22 #define SIGTTOU 22
/*
* Most of these aren't used yet (and perhaps never will),
* so they are commented out.
*/
/*
#define SIGIO 23
#define SIGPOLL SIGIO
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
*/
#define SIGWINCH 28
/*
#define SIGLOST 29
*/
/* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */ /* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */
#define SA_NOCLDSTOP 1 #define SA_NOCLDSTOP 1
#define SA_INTERRUPT 0x20000000 #define SA_INTERRUPT 0x20000000
......
This diff is collapsed.
This diff is collapsed.
...@@ -24,6 +24,7 @@ struct timezone { ...@@ -24,6 +24,7 @@ struct timezone {
#define DST_TUR 9 /* Turkey */ #define DST_TUR 9 /* Turkey */
#define DST_AUSTALT 10 /* Australian style with shift in 1986 */ #define DST_AUSTALT 10 /* Australian style with shift in 1986 */
#define FD_SETSIZE (8*sizeof(fd_set))
#define FD_SET(fd,fdsetp) (*(fdsetp) |= (1 << (fd))) #define FD_SET(fd,fdsetp) (*(fdsetp) |= (1 << (fd)))
#define FD_CLR(fd,fdsetp) (*(fdsetp) &= ~(1 << (fd))) #define FD_CLR(fd,fdsetp) (*(fdsetp) &= ~(1 << (fd)))
#define FD_ISSET(fd,fdsetp) ((*(fdsetp) >> fd) & 1) #define FD_ISSET(fd,fdsetp) ((*(fdsetp) >> fd) & 1)
......
This diff is collapsed.
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define TIOCSSOFTCAR 0x541A #define TIOCSSOFTCAR 0x541A
#define FIONREAD 0x541B #define FIONREAD 0x541B
#define TIOCINQ FIONREAD #define TIOCINQ FIONREAD
#define TIOCLINUX 0x541C
struct winsize { struct winsize {
unsigned short ws_row; unsigned short ws_row;
......
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