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 @@
# if you want the ram-disk device, define this to be the
# size in blocks.
#
RAMDISK = #-DRAMDISK=512
#RAMDISK = -DRAMDISK=512
AS86 =as86 -0 -a
LD86 =ld86 -0
AS =gas
LD =gld
AS =as
LD =ld
LDFLAGS =-s -x -M
CC =gcc $(RAMDISK)
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
-fcombine-regs -mstring-insns
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer
CPP =cpp -nostdinc -Iinclude
#
# ROOT_DEV specifies the default root-device when making the image.
# 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
SWAP_DEV=/dev/hd2
ROOT_DEV=/dev/hdb1
ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
MATH =kernel/math/math.a
LIBS =lib/lib.a
ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o
FILESYSTEMS =fs/minix/minix.o
DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
MATH =kernel/math/math.a
LIBS =lib/lib.a
.c.s:
$(CC) $(CFLAGS) \
......@@ -40,8 +39,7 @@ LIBS =lib/lib.a
all: Image
Image: boot/bootsect boot/setup tools/system tools/build
tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) \
$(SWAP_DEV) > Image
tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) > Image
sync
disk: Image
......@@ -54,9 +52,10 @@ tools/build: tools/build.c
boot/head.o: boot/head.s
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 \
$(ARCHIVES) \
$(FILESYSTEMS) \
$(DRIVERS) \
$(MATH) \
$(LIBS) \
......@@ -80,6 +79,9 @@ mm/mm.o:
fs/fs.o:
(cd fs; make)
fs/minix/minix.o:
(cd fs/minix; make)
lib/lib.a:
(cd lib; make)
......@@ -99,7 +101,7 @@ boot/bootsect: boot/bootsect.s
clean:
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
(cd mm;make clean)
(cd fs;make clean)
......
......@@ -53,6 +53,7 @@ start:
mov cx,#256
sub si,si
sub di,di
cld
rep
movw
jmpi go,INITSEG
......@@ -83,7 +84,6 @@ go: mov ax,cs
* fs = 0, gs = parameter table segment
*/
push #0
pop fs
mov bx,#0x78 ! fs:bx is parameter table address
......
......@@ -12,9 +12,10 @@
* the page directory.
*/
.text
.globl _idt,_gdt,_pg_dir,_tmp_floppy_area
.globl _idt,_gdt,_pg_dir,_tmp_floppy_area,_floppy_track_buffer
_pg_dir:
startup_32:
cld
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
......@@ -34,17 +35,39 @@ startup_32:
movl %eax,0x000000 # loop forever if it isn't
cmpl %eax,0x100000
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
* 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
* 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
/* "orl $0x10020,%eax" here for 486 might be good */
orl $2,%eax # set MP
movl %eax,%cr0
orl $0x10022,%eax # set NE and MP
2: movl %eax,%cr0
call check_x87
jmp after_page_tables
......@@ -55,8 +78,8 @@ check_x87:
fninit
fstsw %ax
cmpb $0,%al
je 1f /* no coprocessor: have to set bits */
movl %cr0,%eax
je 1f
movl %cr0,%eax /* no coprocessor: have to set bits */
xorl $6,%eax /* reset MP, set EM */
movl %eax,%cr0
ret
......@@ -131,14 +154,22 @@ pg3:
*/
_tmp_floppy_area:
.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:
call setup_paging
pushl $0 # These are the parameters to main :-)
pushl $0
pushl $0
pushl $L6 # return address for main, if it decides to.
pushl $_main
jmp setup_paging
cld # gcc2 wants the direction flag cleared at all times
call _start_kernel
L6:
jmp L6 # main should never return here, but
# just in case, we know what happens.
......@@ -148,6 +179,7 @@ int_msg:
.asciz "Unknown interrupt\n\r"
.align 2
ignore_int:
cld
pushl %eax
pushl %ecx
pushl %edx
......@@ -210,6 +242,7 @@ setup_paging:
1: stosl /* fill pages backwards - more efficient :-) */
subl $0x1000,%eax
jge 1b
cld
xorl %eax,%eax /* pg_dir is at 0x0000 */
movl %eax,%cr3 /* cr3 - page directory start */
movl %cr0,%eax
......
......@@ -77,6 +77,7 @@ novga: mov [14],ax
mov es,ax
mov di,#0x0080
mov cx,#0x10
cld
rep
movsb
......@@ -89,6 +90,7 @@ novga: mov [14],ax
mov es,ax
mov di,#0x0090
mov cx,#0x10
cld
rep
movsb
......@@ -106,6 +108,7 @@ no_disk1:
mov di,#0x0090
mov cx,#0x10
mov ax,#0x00
cld
rep
stosb
is_disk1:
......@@ -220,6 +223,10 @@ chsvga: cld
mov es,ax
lea si,msg1
call prtstr
flush: in al,#0x60 ! Flush the keyboard buffer
cmp al,#0x82
jb nokey
jmp flush
nokey: in al,#0x60
cmp al,#0x82
jb nokey
......@@ -230,7 +237,8 @@ nokey: in al,#0x60
mov ax,#0x5019
pop ds
ret
svga: lea si,idati ! Check ATI 'clues'
svga: cld
lea si,idati ! Check ATI 'clues'
mov di,#0x31
mov cx,#0x09
repe
......@@ -354,7 +362,8 @@ l1: inc si
lea di,mogenoa
lea cx,selmod
jmp cx
nogen: lea si,idparadise ! Check Paradise 'clues'
nogen: cld
lea si,idparadise ! Check Paradise 'clues'
mov di,#0x7d
mov cx,#0x04
repe
......
AR =gar
AS =gas
AR =ar
AS =as
CC =gcc
LD =gld
CFLAGS =-Wall -O -fstrength-reduce -fcombine-regs -fomit-frame-pointer \
-fno-defer-pop -mstring-insns -nostdinc -I../include
LD =ld
CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
-fno-defer-pop -nostdinc -I../include
CPP =gcc -E -nostdinc -I../include
.c.s:
......@@ -16,8 +16,8 @@ CPP =gcc -E -nostdinc -I../include
$(AS) -o $*.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 \
bitmap.o fcntl.o ioctl.o truncate.o select.o
block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
fcntl.o ioctl.o select.o
fs.o: $(OBJS)
$(LD) -r -o fs.o $(OBJS)
......@@ -25,18 +25,15 @@ fs.o: $(OBJS)
clean:
rm -f core *.o *.a tmp_make
for i in *.c;do rm -f `basename $$i .c`.s;done
cd minix; make clean
dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
(for i in *.c;do $(CPP) -M $$i;done) >> tmp_make
cp tmp_make Makefile
cd minix; make dep
### 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 \
../include/linux/head.h ../include/linux/fs.h ../include/sys/types.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 \
../include/signal.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/asm/segment.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
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/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 \
../include/sys/stat.h ../include/sys/types.h ../include/linux/sched.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 \
../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/asm/segment.h ../include/string.h ../include/fcntl.h \
../include/errno.h ../include/const.h ../include/sys/stat.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
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/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/tty.h ../include/termios.h \
../include/asm/segment.h
../include/sys/resource.h ../include/asm/segment.h
pipe.o : pipe.c ../include/signal.h ../include/sys/types.h \
../include/errno.h ../include/termios.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/sys/param.h ../include/sys/time.h \
../include/time.h ../include/sys/resource.h ../include/asm/segment.h
../include/errno.h ../include/termios.h ../include/fcntl.h \
../include/linux/sched.h ../include/linux/head.h ../include/linux/fs.h \
../include/linux/mm.h ../include/linux/kernel.h ../include/sys/param.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 \
../include/errno.h ../include/linux/kernel.h ../include/linux/sched.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 \
../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/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
../include/sys/resource.h ../include/linux/minix_fs.h \
../include/asm/system.h ../include/errno.h ../include/sys/stat.h
......@@ -13,23 +13,25 @@
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 offset = *pos & (BLOCK_SIZE-1);
int block = filp->f_pos >> BLOCK_SIZE_BITS;
int offset = filp->f_pos & (BLOCK_SIZE-1);
int chars;
int written = 0;
int size;
unsigned int dev;
struct buffer_head * bh;
register char * p;
dev = inode->i_rdev;
if (blk_size[MAJOR(dev)])
size = blk_size[MAJOR(dev)][MINOR(dev)];
else
size = 0x7fffffff;
while (count>0) {
if (block >= size)
return written?written:-EIO;
return written;
chars = BLOCK_SIZE - offset;
if (chars > count)
chars=count;
......@@ -42,7 +44,7 @@ int block_write(int dev, long * pos, char * buf, int count)
return written?written:-EIO;
p = offset + bh->b_data;
offset = 0;
*pos += chars;
filp->f_pos += chars;
written += chars;
count -= chars;
while (chars-->0)
......@@ -53,23 +55,25 @@ int block_write(int dev, long * pos, char * buf, int count)
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;
int offset = *pos & (BLOCK_SIZE-1);
int chars;
int size;
unsigned int block = filp->f_pos >> BLOCK_SIZE_BITS;
unsigned int offset = filp->f_pos & (BLOCK_SIZE-1);
unsigned int chars;
unsigned int size;
unsigned int dev;
int read = 0;
struct buffer_head * bh;
register char * p;
dev = inode->i_rdev;
if (blk_size[MAJOR(dev)])
size = blk_size[MAJOR(dev)][MINOR(dev)];
else
size = 0x7fffffff;
while (count>0) {
if (block >= size)
return read?read:-EIO;
return read;
chars = BLOCK_SIZE-offset;
if (chars > count)
chars = count;
......@@ -78,7 +82,7 @@ int block_read(int dev, unsigned long * pos, char * buf, int count)
block++;
p = offset + bh->b_data;
offset = 0;
*pos += chars;
filp->f_pos += chars;
read += chars;
count -= chars;
while (chars-->0)
......
......@@ -41,43 +41,39 @@ static inline void wait_on_buffer(struct buffer_head * bh)
sti();
}
int sys_sync(void)
static void sync_buffers(int dev)
{
int i;
struct buffer_head * bh;
sync_inodes(); /* write out inodes into buffers */
bh = start_buffer;
for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
bh = free_list;
for (i=0 ; i<NR_BUFFERS ; i++,bh = bh->b_next_free) {
#if 0
if (dev && (bh->b_dev != dev))
continue;
#endif
wait_on_buffer(bh);
#if 0
if (dev && (bh->b_dev != dev))
continue;
#endif
if (bh->b_dirt)
ll_rw_block(WRITE,bh);
}
}
int sys_sync(void)
{
sync_inodes(); /* write out inodes into buffers */
sync_buffers(0);
return 0;
}
int sync_dev(int dev)
{
int i;
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_buffers(dev);
sync_inodes();
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_buffers(dev);
return 0;
}
......@@ -128,22 +124,61 @@ void check_disk_change(int dev)
#define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
#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)
bh->b_next->b_prev = bh->b_prev;
if (bh->b_prev)
bh->b_prev->b_next = bh->b_next;
if (hash(bh->b_dev,bh->b_blocknr) == bh)
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))
panic("Free block list corrupted");
bh->b_prev_free->b_next_free = bh->b_next_free;
bh->b_next_free->b_prev_free = bh->b_prev_free;
if (free_list == bh)
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)
......@@ -189,8 +224,10 @@ struct buffer_head * get_hash_table(int dev, int block)
return NULL;
bh->b_count++;
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;
}
bh->b_count--;
}
}
......@@ -201,17 +238,23 @@ struct buffer_head * get_hash_table(int dev, int block)
* so it should be much more efficient than it looks.
*
* 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)
struct buffer_head * getblk(int dev,int block)
{
struct buffer_head * tmp, * bh;
struct buffer_head * bh, * tmp;
int buffers;
repeat:
if (bh = get_hash_table(dev,block))
return bh;
buffers = NR_BUFFERS;
tmp = free_list;
do {
tmp = tmp->b_next_free;
if (tmp->b_count)
continue;
if (!bh || BADNESS(tmp)<BADNESS(bh)) {
......@@ -219,8 +262,10 @@ struct buffer_head * getblk(int dev,int block)
if (!BADNESS(tmp))
break;
}
if (tmp->b_dirt)
ll_rw_block(WRITEA,tmp);
/* and repeat until we find something good */
} while ((tmp = tmp->b_next_free) != free_list);
} while (buffers--);
if (!bh) {
sleep_on(&buffer_wait);
goto repeat;
......@@ -377,5 +422,5 @@ void buffer_init(long buffer_end)
free_list->b_prev_free = h;
h->b_next_free = free_list;
for (i=0;i<NR_HASH;i++)
hash_table[i]=NULL;
hash_table[i] = NULL;
}
......@@ -13,22 +13,22 @@
#include <asm/segment.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);
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));
}
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)
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)
......@@ -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)
{
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)
......@@ -62,7 +76,8 @@ static int rw_port(int rw,char * buf, int count, off_t * pos)
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) {
case 0:
......@@ -92,13 +107,30 @@ static crw_ptr crw_table[]={
NULL, /* /dev/lp */
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;
if (MAJOR(dev)>=NRDEVS)
major = MAJOR(inode->i_rdev);
minor = MINOR(inode->i_rdev);
if (major >= NRDEVS)
return -ENODEV;
if (!(call_addr=crw_table[MAJOR(dev)]))
if (!(call_addr=crw_table[major]))
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);
int sys_uselib(const char * library)
{
struct m_inode * inode;
struct inode * inode;
unsigned long base;
if (get_limit(0x17) != TASK_SIZE)
......@@ -148,7 +148,7 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
do {
len++;
} 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);
return 0;
}
......@@ -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,
char ** argv, char ** envp)
{
struct m_inode * inode;
struct inode * inode;
struct buffer_head * bh;
struct exec ex;
unsigned long page[MAX_ARG_PAGES];
......@@ -232,18 +232,24 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
goto exec_error2;
}
i = inode->i_mode;
e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
/* make sure we don't let suid, sgid files be ptraced. */
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)
i >>= 6;
else if (in_group_p(inode->i_gid))
i >>= 3;
if (!(i & 1) &&
!((inode->i_mode & 0111) && suser())) {
retval = -ENOEXEC;
retval = -EACCES;
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;
goto exec_error2;
}
......@@ -367,11 +373,13 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
current->brk = ex.a_bss +
(current->end_data = ex.a_data +
(current->end_code = ex.a_text));
current->start_stack = p & 0xfffff000;
current->start_stack = p;
current->suid = current->euid = e_uid;
current->sgid = current->egid = e_gid;
eip[0] = ex.a_entry; /* eip, magic happens :-) */
eip[3] = p; /* stack pointer */
if (current->flags & PF_PTRACED)
send_sig(SIGTRAP, current, 0);
return 0;
exec_error2:
iput(inode);
......
......@@ -35,6 +35,8 @@ static int dupfd(unsigned int fd, unsigned int arg)
int sys_dup2(unsigned int oldfd, unsigned int newfd)
{
if (newfd == oldfd)
return newfd;
sys_close(newfd);
return dupfd(oldfd,newfd);
}
......@@ -68,8 +70,8 @@ int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
return 0;
case F_GETLK: case F_SETLK: case F_SETLKW:
return -1;
return -ENOSYS;
default:
return -1;
return -EINVAL;
}
}
......@@ -8,18 +8,17 @@
#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>
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 void write_inode(struct m_inode * inode);
static inline void wait_on_inode(struct m_inode * inode)
static inline void wait_on_inode(struct inode * inode)
{
cli();
while (inode->i_lock)
......@@ -27,7 +26,7 @@ static inline void wait_on_inode(struct m_inode * inode)
sti();
}
static inline void lock_inode(struct m_inode * inode)
static inline void lock_inode(struct inode * inode)
{
cli();
while (inode->i_lock)
......@@ -36,16 +35,39 @@ static inline void lock_inode(struct m_inode * inode)
sti();
}
static inline void unlock_inode(struct m_inode * inode)
static inline void unlock_inode(struct inode * inode)
{
inode->i_lock=0;
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)
{
int i;
struct m_inode * inode;
struct inode * inode;
inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) {
......@@ -61,7 +83,7 @@ void invalidate_inodes(int dev)
void sync_inodes(void)
{
int i;
struct m_inode * inode;
struct inode * inode;
inode = 0+inode_table;
for(i=0 ; i<NR_INODE ; i++,inode++) {
......@@ -71,85 +93,7 @@ void sync_inodes(void)
}
}
static int _bmap(struct m_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_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)
void iput(struct inode * inode)
{
if (!inode)
return;
......@@ -172,7 +116,7 @@ void iput(struct m_inode * inode)
return;
}
if (S_ISBLK(inode->i_mode)) {
sync_dev(inode->i_zone[0]);
sync_dev(inode->i_rdev);
wait_on_inode(inode);
}
repeat:
......@@ -180,9 +124,9 @@ void iput(struct m_inode * inode)
inode->i_count--;
return;
}
if (!inode->i_nlinks) {
truncate(inode);
free_inode(inode);
if (!inode->i_nlink) {
minix_truncate(inode);
minix_free_inode(inode);
return;
}
if (inode->i_dirt) {
......@@ -194,10 +138,10 @@ void iput(struct m_inode * inode)
return;
}
struct m_inode * get_empty_inode(void)
struct inode * get_empty_inode(void)
{
struct m_inode * inode;
static struct m_inode * last_inode = inode_table;
struct inode * inode;
static struct inode * last_inode = inode_table;
int i;
do {
......@@ -213,8 +157,8 @@ struct m_inode * get_empty_inode(void)
}
if (!inode) {
for (i=0 ; i<NR_INODE ; i++)
printk("%04x: %6d\t",inode_table[i].i_dev,
inode_table[i].i_num);
printk("(%04x: %d (%o)) ",inode_table[i].i_dev,
inode_table[i].i_ino,inode_table[i].i_mode);
panic("No free inodes in mem");
}
wait_on_inode(inode);
......@@ -228,9 +172,9 @@ struct m_inode * get_empty_inode(void)
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()))
return NULL;
......@@ -244,21 +188,21 @@ struct m_inode * get_pipe_inode(void)
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)
panic("iget with dev==0");
empty = get_empty_inode();
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++;
continue;
}
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;
continue;
}
......@@ -267,7 +211,7 @@ struct m_inode * iget(int dev,int nr)
int i;
for (i = 0 ; i<NR_SUPER ; i++)
if (super_block[i].s_imount==inode)
if (super_block[i].s_covered==inode)
break;
if (i >= NR_SUPER) {
printk("Mounted inode hasn't got sb\n");
......@@ -276,10 +220,12 @@ struct m_inode * iget(int dev,int nr)
return inode;
}
iput(inode);
dev = super_block[i].s_dev;
nr = ROOT_INO;
inode = inode_table;
continue;
if (!(inode = super_block[i].s_mounted))
printk("iget: mounted dev has no rootinode\n");
else {
inode->i_count++;
wait_on_inode(inode);
}
}
if (empty)
iput(empty);
......@@ -287,62 +233,14 @@ struct m_inode * iget(int dev,int nr)
}
if (!empty)
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_num = nr;
inode->i_ino = nr;
read_inode(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 @@
#include <linux/sched.h>
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);
......@@ -40,7 +40,7 @@ int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
mode=filp->f_inode->i_mode;
if (!S_ISCHR(mode) && !S_ISBLK(mode))
return -EINVAL;
dev = filp->f_inode->i_zone[0];
dev = filp->f_inode->i_rdev;
if (MAJOR(dev) >= NRDEVS)
return -ENODEV;
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 @@
#include <string.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h>
#define clear_block(addr) \
......@@ -17,15 +18,15 @@ __asm__("cld\n\t" \
::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
#define set_bit(nr,addr) ({\
register int res __asm__("ax"); \
__asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
char res; \
__asm__ __volatile__("btsl %1,%2\n\tsetb %0": \
"=q" (res):"r" (nr),"m" (*(addr))); \
res;})
#define clear_bit(nr,addr) ({\
register int res __asm__("ax"); \
__asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \
"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
char res; \
__asm__ __volatile__("btrl %1,%2\n\tsetnb %0": \
"=q" (res):"r" (nr),"m" (*(addr))); \
res;})
#define find_first_zero(addr) ({ \
......@@ -34,20 +35,20 @@ __asm__("cld\n" \
"1:\tlodsl\n\t" \
"notl %%eax\n\t" \
"bsfl %%eax,%%edx\n\t" \
"je 2f\n\t" \
"addl %%edx,%%ecx\n\t" \
"jmp 3f\n" \
"2:\taddl $32,%%ecx\n\t" \
"jne 2f\n\t" \
"addl $32,%%ecx\n\t" \
"cmpl $8192,%%ecx\n\t" \
"jl 1b\n" \
"3:" \
:"=c" (__res):"c" (0),"S" (addr):"ax","dx","si"); \
"jl 1b\n\t" \
"xorl %%edx,%%edx\n" \
"2:\taddl %%edx,%%ecx" \
:"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
__res;})
int free_block(int dev, int block)
int minix_free_block(int dev, int block)
{
struct super_block * sb;
struct buffer_head * bh;
unsigned int bit,zone;
if (!(sb = get_super(dev)))
panic("trying to free block on nonexistent device");
......@@ -64,16 +65,17 @@ int free_block(int dev, int block)
if (bh->b_count)
brelse(bh);
}
block -= sb->s_firstdatazone - 1 ;
if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {
printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);
printk("free_block: bit already cleared\n");
}
sb->s_zmap[block/8192]->b_dirt = 1;
zone = block - sb->s_firstdatazone + 1;
bit = zone & 8191;
zone >>= 13;
bh = sb->s_zmap[zone];
if (clear_bit(bit,bh->b_data))
printk("free_block (%04x:%d): bit already cleared\n",dev,block);
bh->b_dirt = 1;
return 1;
}
int new_block(int dev)
int minix_new_block(int dev)
{
struct buffer_head * bh;
struct super_block * sb;
......@@ -105,9 +107,8 @@ int new_block(int dev)
return j;
}
void free_inode(struct m_inode * inode)
void minix_free_inode(struct inode * inode)
{
struct super_block * sb;
struct buffer_head * bh;
if (!inode)
......@@ -117,53 +118,67 @@ void free_inode(struct m_inode * inode)
return;
}
if (inode->i_count>1) {
printk("trying to free inode with count=%d\n",inode->i_count);
panic("free_inode");
printk("free_inode: inode has count=%d\n",inode->i_count);
return;
}
if (inode->i_nlink) {
printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
return;
}
if (inode->i_nlinks)
panic("trying to free inode with links");
if (!(sb = get_super(inode->i_dev)))
panic("trying to free inode on nonexistent device");
if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)
panic("trying to free inode 0 or nonexistant inode");
if (!(bh=sb->s_imap[inode->i_num>>13]))
panic("nonexistent imap in superblock");
if (clear_bit(inode->i_num&8191,bh->b_data))
if (!inode->i_sb) {
printk("free_inode: inode on nonexistent device\n");
return;
}
if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->s_ninodes) {
printk("free_inode: inode 0 or nonexistent inode\n");
return;
}
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");
bh->b_dirt = 1;
memset(inode,0,sizeof(*inode));
}
struct m_inode * new_inode(int dev)
struct inode * minix_new_inode(int dev)
{
struct m_inode * inode;
struct super_block * sb;
struct inode * inode;
struct buffer_head * bh;
int i,j;
if (!(inode=get_empty_inode()))
return NULL;
if (!(sb = get_super(dev)))
panic("new_inode with unknown device");
if (!(inode->i_sb = get_super(dev))) {
printk("new_inode: unknown device\n");
iput(inode);
return NULL;
}
j = 8192;
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)
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);
return NULL;
}
if (set_bit(j,bh->b_data))
panic("new_inode: bit already set");
bh->b_dirt = 1;
inode->i_count=1;
inode->i_nlinks=1;
inode->i_dev=dev;
inode->i_uid=current->euid;
inode->i_gid=current->egid;
inode->i_dirt=1;
inode->i_num = j + i*8192;
inode->i_count = 1;
inode->i_nlink = 1;
inode->i_dev = dev;
inode->i_uid = current->euid;
inode->i_gid = current->egid;
inode->i_dirt = 1;
inode->i_ino = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = &minix_inode_operations;
return inode;
}
......@@ -8,29 +8,36 @@
#include <fcntl.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#define MIN(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;
if ((left=count)<=0)
return 0;
while (left) {
if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {
if (filp->f_pos > inode->i_size)
left = 0;
else
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)))
break;
return read?read:-EIO;
} else
bh = NULL;
nr = filp->f_pos % BLOCK_SIZE;
nr = filp->f_pos & (BLOCK_SIZE-1);
chars = MIN( BLOCK_SIZE-nr , left );
filp->f_pos += chars;
left -= chars;
read += chars;
if (bh) {
char * p = nr + bh->b_data;
while (chars-->0)
......@@ -42,16 +49,15 @@ int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
}
}
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;
int block,c;
int written,block,c;
struct buffer_head * bh;
char * p;
int i=0;
/*
* 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
pos = inode->i_size;
else
pos = filp->f_pos;
while (i<count) {
if (!(block = create_block(inode,pos/BLOCK_SIZE)))
written = 0;
while (written<count) {
if (!(block = minix_create_block(inode,pos/BLOCK_SIZE))) {
if (!written)
written = -ENOSPC;
break;
if (!(bh=bread(inode->i_dev,block)))
}
if (!(bh=bread(inode->i_dev,block))) {
if (!written)
written = -EIO;
break;
}
c = pos % BLOCK_SIZE;
p = c + bh->b_data;
bh->b_dirt = 1;
c = BLOCK_SIZE-c;
if (c > count-i) c = count-i;
if (c > count-written)
c = count-written;
pos += c;
if (pos > inode->i_size) {
inode->i_size = pos;
inode->i_dirt = 1;
}
i += c;
written += c;
while (c-->0)
*(p++) = get_fs_byte(buf++);
brelse(bh);
......@@ -85,6 +99,7 @@ int file_write(struct m_inode * inode, struct file * filp, char * buf, int count
if (!(filp->f_flags & O_APPEND)) {
filp->f_pos = pos;
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 @@
*/
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/tty.h>
#include <errno.h>
#include <fcntl.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;
unsigned short * p;
......@@ -22,7 +26,7 @@ static int free_ind(int dev,int block)
p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++)
if (*p)
if (free_block(dev,*p)) {
if (minix_free_block(dev,*p)) {
*p = 0;
bh->b_dirt = 1;
} else
......@@ -32,10 +36,10 @@ static int free_ind(int dev,int block)
if (block_busy)
return 0;
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;
unsigned short * p;
......@@ -49,7 +53,7 @@ static int free_dind(int dev,int block)
p = (unsigned short *) bh->b_data;
for (i=0;i<512;i++,p++)
if (*p)
if (free_ind(dev,*p)) {
if (minix_free_ind(dev,*p)) {
*p = 0;
bh->b_dirt = 1;
} else
......@@ -59,10 +63,10 @@ static int free_dind(int dev,int block)
if (block_busy)
return 0;
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 block_busy;
......@@ -73,18 +77,18 @@ void truncate(struct m_inode * inode)
repeat:
block_busy = 0;
for (i=0;i<7;i++)
if (inode->i_zone[i]) {
if (free_block(inode->i_dev,inode->i_zone[i]))
inode->i_zone[i]=0;
if (inode->i_data[i]) {
if (minix_free_block(inode->i_dev,inode->i_data[i]))
inode->i_data[i]=0;
else
block_busy = 1;
}
if (free_ind(inode->i_dev,inode->i_zone[7]))
inode->i_zone[7] = 0;
if (minix_free_ind(inode->i_dev,inode->i_data[7]))
inode->i_data[7] = 0;
else
block_busy = 1;
if (free_dind(inode->i_dev,inode->i_zone[8]))
inode->i_zone[8] = 0;
if (minix_free_dind(inode->i_dev,inode->i_data[8]))
inode->i_data[8] = 0;
else
block_busy = 1;
inode->i_dirt = 1;
......@@ -97,3 +101,54 @@ void truncate(struct m_inode * inode)
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 @@
#include <sys/stat.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/kernel.h>
#include <asm/segment.h>
......@@ -24,7 +23,7 @@ int sys_ustat(int dev, struct ustat * ubuf)
int sys_utime(char * filename, struct utimbuf * times)
{
struct m_inode * inode;
struct inode * inode;
long actime,modtime;
if (!(inode=namei(filename)))
......@@ -47,7 +46,7 @@ int sys_utime(char * filename, struct utimbuf * times)
*/
int sys_access(const char * filename,int mode)
{
struct m_inode * inode;
struct inode * inode;
int res, i_mode;
mode &= 0007;
......@@ -75,7 +74,7 @@ int sys_access(const char * filename,int mode)
int sys_chdir(const char * filename)
{
struct m_inode * inode;
struct inode * inode;
if (!(inode = namei(filename)))
return -ENOENT;
......@@ -90,7 +89,7 @@ int sys_chdir(const char * filename)
int sys_chroot(const char * filename)
{
struct m_inode * inode;
struct inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
......@@ -105,7 +104,7 @@ int sys_chroot(const char * filename)
int sys_chmod(const char * filename,int mode)
{
struct m_inode * inode;
struct inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
......@@ -121,7 +120,7 @@ int sys_chmod(const char * filename,int mode)
int sys_chown(const char * filename,int uid,int gid)
{
struct m_inode * inode;
struct inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
......@@ -136,45 +135,12 @@ int sys_chown(const char * filename,int uid,int gid)
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)
{
struct m_inode * inode;
struct inode * inode;
struct file * f;
int i,fd;
mode &= 0777 & ~current->umask;
for(fd=0 ; fd<NR_OPEN ; fd++)
if (!current->filp[fd])
break;
......@@ -192,28 +158,25 @@ int sys_open(const char * filename,int flag,int mode)
f->f_count=0;
return i;
}
/* ttys are somewhat special (ttyxx major==4, tty major==5) */
if (S_ISCHR(inode->i_mode))
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_op = NULL;
f->f_mode = "\001\002\003\000"[flag & O_ACCMODE];
f->f_flags = flag;
f->f_count = 1;
f->f_inode = inode;
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);
}
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)
......
......@@ -7,25 +7,26 @@
#include <signal.h>
#include <errno.h>
#include <termios.h>
#include <fcntl.h>
#include <linux/sched.h>
#include <linux/mm.h> /* for get_free_page */
#include <asm/segment.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;
while (count>0) {
while (!(size=PIPE_SIZE(*inode))) {
if (!(filp->f_flags & O_NONBLOCK))
while (!PIPE_SIZE(*inode)) {
wake_up(& PIPE_WRITE_WAIT(*inode));
if (inode->i_count != 2) /* are there any writers? */
return read;
return 0;
if (current->signal & ~current->blocked)
return read?read:-ERESTARTSYS;
return -ERESTARTSYS;
interruptible_sleep_on(& PIPE_READ_WAIT(*inode));
}
while (count>0 && (size = PIPE_SIZE(*inode))) {
chars = PAGE_SIZE-PIPE_TAIL(*inode);
if (chars > count)
chars = count;
......@@ -43,7 +44,7 @@ int read_pipe(struct m_inode * inode, char * buf, int count)
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;
......@@ -52,9 +53,11 @@ int write_pipe(struct m_inode * inode, char * buf, int count)
wake_up(& PIPE_READ_WAIT(*inode));
if (inode->i_count != 2) { /* no readers */
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);
if (chars > count)
......@@ -75,7 +78,7 @@ int write_pipe(struct m_inode * inode, char * buf, int count)
int sys_pipe(unsigned long * fildes)
{
struct m_inode * inode;
struct inode * inode;
struct file * f[2];
int fd[2];
int i,j;
......@@ -115,7 +118,7 @@ int sys_pipe(unsigned long * fildes)
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) {
case FIONREAD:
......
......@@ -12,26 +12,20 @@
#include <linux/sched.h>
#include <asm/segment.h>
extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos);
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)
int sys_lseek(unsigned int fd,off_t offset, unsigned int origin)
{
struct file * file;
int tmp;
if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode)
|| !IS_SEEKABLE(MAJOR(file->f_inode->i_dev)))
if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode))
return -EBADF;
if (origin > 2)
return -EINVAL;
if (file->f_inode->i_pipe)
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) {
case 0:
if (offset<0) return -EINVAL;
......@@ -45,59 +39,59 @@ int sys_lseek(unsigned int fd,off_t offset, int origin)
if ((tmp=file->f_inode->i_size+offset) < 0)
return -EINVAL;
file->f_pos = tmp;
break;
default:
return -EINVAL;
}
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 m_inode * inode;
struct inode * inode;
if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd]))
return -EINVAL;
if (fd>=NR_OPEN || !(file=current->filp[fd]) || !(inode=file->f_inode))
return -EBADF;
if (!(file->f_mode & 1))
return -EBADF;
if (!count)
return 0;
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)
return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;
return pipe_read(inode,file,buf,count);
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))
return block_read(inode->i_zone[0],&file->f_pos,buf,count);
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {
if (count+file->f_pos > inode->i_size)
count = inode->i_size - file->f_pos;
if (count<=0)
return 0;
return file_read(inode,file,buf,count);
}
return block_read(inode,file,buf,count);
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode))
return minix_file_read(inode,file,buf,count);
printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
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 m_inode * inode;
struct inode * inode;
if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd]))
return -EINVAL;
if (fd>=NR_OPEN || !(file=current->filp[fd]) || !(inode=file->f_inode))
return -EBADF;
if (!(file->f_mode&2))
return -EBADF;
if (!count)
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)
return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;
return pipe_write(inode,file,buf,count);
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))
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))
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);
return -EINVAL;
}
......@@ -79,18 +79,18 @@ static void free_wait(select_table * p)
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;
if (!S_ISCHR(inode->i_mode))
return NULL;
if ((major = MAJOR(inode->i_zone[0])) != 5 && major != 4)
if ((major = MAJOR(inode->i_rdev)) != 5 && major != 4)
return NULL;
if (major == 5)
minor = current->tty;
else
minor = MINOR(inode->i_zone[0]);
minor = MINOR(inode->i_rdev);
if (minor < 0)
return NULL;
return TTY_TABLE(minor);
......@@ -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
* 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;
......@@ -110,14 +110,14 @@ static int check_in(select_table * wait, struct m_inode * inode)
else
add_wait(&tty->secondary->proc_list, wait);
else if (inode->i_pipe)
if (!PIPE_EMPTY(*inode))
if (!PIPE_EMPTY(*inode) || inode->i_count < 2)
return 1;
else
add_wait(&inode->i_wait, wait);
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;
......@@ -134,7 +134,7 @@ static int check_out(select_table * wait, struct m_inode * inode)
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;
......@@ -198,7 +198,7 @@ int do_select(fd_set in, fd_set out, fd_set ex,
}
}
if (!(current->signal & ~current->blocked) &&
(wait_table.nr || current->timeout) && !count) {
current->timeout && !count) {
current->state = TASK_INTERRUPTIBLE;
schedule();
free_wait(&wait_table);
......@@ -224,7 +224,11 @@ int sys_select( unsigned long *buffer )
struct timeval *tvp;
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++);
outp = (fd_set *) get_fs_long(buffer++);
exp = (fd_set *) get_fs_long(buffer++);
......
......@@ -12,19 +12,19 @@
#include <linux/kernel.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;
int i;
verify_area(statbuf,sizeof (struct stat));
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_nlink = inode->i_nlinks;
tmp.st_nlink = inode->i_nlink;
tmp.st_uid = inode->i_uid;
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_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
......@@ -35,7 +35,7 @@ static void cp_stat(struct m_inode * inode, struct stat * statbuf)
int sys_stat(char * filename, struct stat * statbuf)
{
struct m_inode * inode;
struct inode * inode;
if (!(inode=namei(filename)))
return -ENOENT;
......@@ -46,7 +46,7 @@ int sys_stat(char * filename, struct stat * statbuf)
int sys_lstat(char * filename, struct stat * statbuf)
{
struct m_inode * inode;
struct inode * inode;
if (!(inode = lnamei(filename)))
return -ENOENT;
......@@ -58,7 +58,7 @@ int sys_lstat(char * filename, struct stat * statbuf)
int sys_fstat(unsigned int fd, struct stat * statbuf)
{
struct file * f;
struct m_inode * inode;
struct inode * inode;
if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
return -EBADF;
......@@ -68,30 +68,16 @@ int sys_fstat(unsigned int fd, struct stat * statbuf)
int sys_readlink(const char * path, char * buf, int bufsiz)
{
struct m_inode * inode;
struct buffer_head * bh;
int i;
char c;
struct inode * inode;
if (bufsiz <= 0)
return -EBADF;
if (bufsiz > 1023)
bufsiz = 1023;
return -EINVAL;
verify_area(buf,bufsiz);
if (!(inode = lnamei(path)))
return -ENOENT;
if (inode->i_zone[0])
bh = bread(inode->i_dev, inode->i_zone[0]);
else
bh = NULL;
iput(inode);
if (!bh)
return 0;
i = 0;
while (i<bufsiz && (c = bh->b_data[i])) {
i++;
put_fs_byte(c,buf++);
if (!inode->i_op || !inode->i_op->readlink) {
iput(inode);
return -EINVAL;
}
brelse(bh);
return i;
return inode->i_op->readlink(inode,buf,bufsiz);
}
......@@ -9,6 +9,7 @@
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/kernel.h>
#include <asm/system.h>
......@@ -82,15 +83,15 @@ void put_super(int dev)
}
if (!(sb = get_super(dev)))
return;
if (sb->s_imount) {
if (sb->s_covered) {
printk("Mounted disk changed - tssk, tssk\n\r");
return;
}
lock_super(sb);
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]);
for(i=0;i<Z_MAP_SLOTS;i++)
for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
brelse(sb->s_zmap[i]);
free_super(sb);
return;
......@@ -114,8 +115,8 @@ static struct super_block * read_super(int dev)
break;
}
s->s_dev = dev;
s->s_isup = NULL;
s->s_imount = NULL;
s->s_mounted = NULL;
s->s_covered = NULL;
s->s_time = 0;
s->s_rd_only = 0;
s->s_dirt = 0;
......@@ -125,17 +126,17 @@ static struct super_block * read_super(int dev)
free_super(s);
return NULL;
}
*((struct d_super_block *) s) =
*((struct d_super_block *) bh->b_data);
*((struct minix_super_block *) s) =
*((struct minix_super_block *) bh->b_data);
brelse(bh);
if (s->s_magic != SUPER_MAGIC) {
if (s->s_magic != MINIX_SUPER_MAGIC) {
s->s_dev = 0;
free_super(s);
return NULL;
}
for (i=0;i<I_MAP_SLOTS;i++)
for (i=0;i < MINIX_I_MAP_SLOTS;i++)
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;
block=2;
for (i=0 ; i < s->s_imap_blocks ; i++)
......@@ -149,9 +150,9 @@ static struct super_block * read_super(int dev)
else
break;
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]);
for(i=0;i<Z_MAP_SLOTS;i++)
for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
brelse(s->s_zmap[i]);
s->s_dev=0;
free_super(s);
......@@ -165,13 +166,13 @@ static struct super_block * read_super(int dev)
int sys_umount(char * dev_name)
{
struct m_inode * inode;
struct inode * inode;
struct super_block * sb;
int dev;
if (!(inode=namei(dev_name)))
return -ENOENT;
dev = inode->i_zone[0];
dev = inode->i_rdev;
if (!S_ISBLK(inode->i_mode)) {
iput(inode);
return -ENOTBLK;
......@@ -179,18 +180,21 @@ int sys_umount(char * dev_name)
iput(inode);
if (dev==ROOT_DEV)
return -EBUSY;
if (!(sb=get_super(dev)) || !(sb->s_imount))
if (!(sb=get_super(dev)) || !(sb->s_covered))
return -ENOENT;
if (!sb->s_imount->i_mount)
if (!sb->s_covered->i_mount)
printk("Mounted inode has i_mount=0\n");
for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
if (inode->i_dev==dev && inode->i_count)
if (inode == sb->s_mounted && inode->i_count == 1)
continue;
else
return -EBUSY;
sb->s_imount->i_mount=0;
iput(sb->s_imount);
sb->s_imount = NULL;
iput(sb->s_isup);
sb->s_isup = NULL;
sb->s_covered->i_mount=0;
iput(sb->s_covered);
sb->s_covered = NULL;
iput(sb->s_mounted);
sb->s_mounted = NULL;
put_super(dev);
sync_dev(dev);
return 0;
......@@ -198,13 +202,13 @@ int sys_umount(char * dev_name)
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;
int dev;
if (!(dev_i=namei(dev_name)))
return -ENOENT;
dev = dev_i->i_zone[0];
dev = dev_i->i_rdev;
if (!S_ISBLK(dev_i->i_mode)) {
iput(dev_i);
return -EPERM;
......@@ -212,7 +216,7 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag)
iput(dev_i);
if (!(dir_i=namei(dir_name)))
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);
return -EBUSY;
}
......@@ -224,7 +228,7 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag)
iput(dir_i);
return -EBUSY;
}
if (sb->s_imount) {
if (sb->s_covered) {
iput(dir_i);
return -EBUSY;
}
......@@ -232,7 +236,11 @@ int sys_mount(char * dev_name, char * dir_name, int rw_flag)
iput(dir_i);
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_dirt=1; /* NOTE! we don't iput(dir_i) */
return 0; /* we do that in umount */
......@@ -242,9 +250,9 @@ void mount_root(void)
{
int i,free;
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");
for(i=0;i<NR_FILE;i++)
file_table[i].f_count=0;
......@@ -259,10 +267,10 @@ void mount_root(void)
}
if (!(p=read_super(ROOT_DEV)))
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");
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->root = mi;
free=0;
......
#define outb(value,port) \
__asm__ ("outb %%al,%%dx"::"a" (value),"d" (port))
static void inline outb(char value, unsigned short 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) ({ \
unsigned char _v; \
__asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \
_v; \
})
static unsigned char inline inb(unsigned short port)
{
unsigned char _v;
__asm__ volatile ("inb %1,%0":"=a" (_v):"d" (port));
return _v;
}
#define outb_p(value,port) \
__asm__ ("outb %%al,%%dx\n" \
"\tjmp 1f\n" \
"1:\tjmp 1f\n" \
"1:"::"a" (value),"d" (port))
#define inb_p(port) ({ \
unsigned char _v; \
__asm__ volatile ("inb %%dx,%%al\n" \
"\tjmp 1f\n" \
"1:\tjmp 1f\n" \
"1:":"=a" (_v):"d" (port)); \
_v; \
})
static unsigned char inb_p(unsigned short port)
{
unsigned char _v;
__asm__ volatile ("inb %1,%0\n"
"\tjmp 1f\n"
"1:\tjmp 1f\n"
"1:":"=a" (_v):"d" ((unsigned short) port));
return _v;
}
......@@ -2,7 +2,7 @@ extern inline unsigned char get_fs_byte(const char * addr)
{
unsigned register char _v;
__asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
__asm__ ("movb %%fs:%1,%0":"=q" (_v):"m" (*addr));
return _v;
}
......@@ -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)
{
__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)
......@@ -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.
* It seems to work, but I don't know if I'm doing something subtly wrong.
* --- 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()
{
unsigned short _v;
__asm__("mov %%fs,%%ax":"=a" (_v):);
__asm__("mov %%fs,%0":"=r" (_v):);
return _v;
}
extern inline unsigned long get_ds()
{
unsigned short _v;
__asm__("mov %%ds,%%ax":"=a" (_v):);
__asm__("mov %%ds,%0":"=r" (_v):);
return _v;
}
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" \
"movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \
"movl %%edx,%2" \
: \
: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
"o" (*((char *) (gate_addr))), \
"o" (*(4+(char *) (gate_addr))), \
"d" ((char *) (addr)),"a" (0x00080000))
:: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
"m" (*((char *) (gate_addr))), \
"m" (*(4+(char *) (gate_addr))), \
"d" ((char *) (addr)),"a" (0x00080000) \
:"ax","dx")
#define set_intr_gate(n,addr) \
_set_gate(&idt[n],14,0,addr)
......
......@@ -56,6 +56,7 @@ extern int errno;
#define ENOLCK 37
#define ENOSYS 38
#define ENOTEMPTY 39
#define ELOOP 40
/* Should never be seen by user programs */
#define ERESTARTSYS 512
......
......@@ -13,7 +13,7 @@
#define O_NOCTTY 00400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */
#define O_APPEND 02000
#define O_NONBLOCK 04000 /* not fcntl */
#define O_NONBLOCK 04000
#define O_NDELAY O_NONBLOCK
/* Defines for fcntl-commands. Note that currently
......
#ifndef _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
*/
......@@ -14,7 +23,7 @@
#define DEF_INITSEG 0x9000
#define DEF_SYSSEG 0x1000
#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
......
......@@ -23,6 +23,10 @@
#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3)
#define MAY_EXEC 1
#define MAY_WRITE 2
#define MAY_READ 4
#define READ 0
#define WRITE 1
#define READA 2 /* read-ahead - don't pause */
......@@ -33,15 +37,8 @@ void buffer_init(long buffer_end);
#define MAJOR(a) (((unsigned)(a))>>8)
#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_INODE 64
#define NR_INODE 128
#define NR_FILE 64
#define NR_SUPER 8
#define NR_HASH 307
......@@ -52,13 +49,10 @@ void buffer_init(long buffer_end);
#define NULL ((void *) 0)
#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_WRITE_WAIT(inode) ((inode).i_wait2)
#define PIPE_HEAD(inode) ((inode).i_zone[0])
#define PIPE_TAIL(inode) ((inode).i_zone[1])
#define PIPE_HEAD(inode) ((inode).i_data[0])
#define PIPE_TAIL(inode) ((inode).i_data[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_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
......@@ -85,31 +79,23 @@ struct buffer_head {
struct buffer_head * b_next_free;
};
struct d_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 m_inode {
unsigned short i_mode;
unsigned short i_uid;
unsigned long i_size;
unsigned long i_mtime;
unsigned char i_gid;
unsigned char i_nlinks;
unsigned short i_zone[9];
/* these are in memory also */
struct inode {
dev_t i_dev;
ino_t i_ino;
umode_t i_mode;
nlink_t i_nlink;
uid_t i_uid;
gid_t i_gid;
dev_t i_rdev;
off_t i_size;
time_t i_atime;
time_t i_mtime;
time_t i_ctime;
unsigned long i_data[16];
struct inode_operations * i_op;
struct super_block * i_sb;
struct task_struct * i_wait;
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 char i_lock;
unsigned char i_dirt;
......@@ -123,7 +109,8 @@ struct file {
unsigned short f_mode;
unsigned short f_flags;
unsigned short f_count;
struct m_inode * f_inode;
struct inode * f_inode;
struct file_operations * f_op;
off_t f_pos;
};
......@@ -140,8 +127,8 @@ struct super_block {
struct buffer_head * s_imap[8];
struct buffer_head * s_zmap[8];
unsigned short s_dev;
struct m_inode * s_isup;
struct m_inode * s_imount;
struct inode * s_covered;
struct inode * s_mounted;
unsigned long s_time;
struct task_struct * s_wait;
unsigned char s_lock;
......@@ -149,23 +136,29 @@ struct super_block {
unsigned char s_dirt;
};
struct d_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 file_operations {
int (*lseek) (struct inode *, struct file *, off_t, int);
int (*read) (struct inode *, struct file *, char *, int);
int (*write) (struct inode *, struct file *, char *, int);
};
struct dir_entry {
unsigned short inode;
char name[NAME_LEN];
struct inode_operations {
int (*create) (struct inode *,const char *,int,int,struct inode **);
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 super_block super_block[NR_SUPER];
extern struct buffer_head * start_buffer;
......@@ -176,35 +169,41 @@ extern int floppy_change(unsigned int nr);
extern int ticks_to_floppy_on(unsigned int dev);
extern void floppy_on(unsigned int dev);
extern void floppy_off(unsigned int dev);
extern void truncate(struct m_inode * inode);
extern void truncate(struct inode * inode);
extern void sync_inodes(void);
extern void wait_on(struct m_inode * inode);
extern int bmap(struct m_inode * inode,int block);
extern int create_block(struct m_inode * inode,int block);
extern struct m_inode * namei(const char * pathname);
extern struct m_inode * lnamei(const char * pathname);
extern void wait_on(struct inode * inode);
extern int bmap(struct inode * inode,int block);
extern struct inode * namei(const char * pathname);
extern struct inode * lnamei(const char * pathname);
extern int open_namei(const char * pathname, int flag, int mode,
struct m_inode ** res_inode);
extern void iput(struct m_inode * inode);
extern struct m_inode * iget(int dev,int nr);
extern struct m_inode * get_empty_inode(void);
extern struct m_inode * get_pipe_inode(void);
struct inode ** res_inode);
extern void iput(struct inode * inode);
extern struct inode * iget(int dev,int nr);
extern struct inode * get_empty_inode(void);
extern struct inode * get_pipe_inode(void);
extern struct buffer_head * get_hash_table(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_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 struct buffer_head * bread(int dev,int block);
extern void bread_page(unsigned long addr,int dev,int b[4]);
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 struct super_block * get_super(int dev);
extern int ROOT_DEV;
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
......@@ -49,15 +49,17 @@
#define ECC_ERR 0x40 /* ? */
#define BBD_ERR 0x80 /* ? */
#define EXTENDED_PARTITION 5
struct partition {
unsigned char boot_ind; /* 0x80 - active (unused) */
unsigned char head; /* ? */
unsigned char sector; /* ? */
unsigned char cyl; /* ? */
unsigned char sys_ind; /* ? */
unsigned char end_head; /* ? */
unsigned char end_sector; /* ? */
unsigned char end_cyl; /* ? */
unsigned char boot_ind; /* 0x80 - active */
unsigned char head; /* starting head */
unsigned char sector; /* starting sector */
unsigned char cyl; /* starting cylinder */
unsigned char sys_ind; /* What partition type */
unsigned char end_head; /* end head */
unsigned char end_sector; /* end sector */
unsigned char end_cyl; /* end cylinder */
unsigned int start_sect; /* starting sector counting from 0 */
unsigned int nr_sects; /* nr of sectors in partition */
};
......
......@@ -10,15 +10,6 @@ void console_print(const char * str);
int tty_write(unsigned ch,char * buf,int count);
void * malloc(unsigned 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)
......
......@@ -9,20 +9,20 @@
#include <linux/sched.h>
struct info {
long ___math_ret;
long ___orig_eip;
long ___edi;
long ___esi;
long ___ebp;
long ___sys_call_ret;
long ___eax;
long ___ret_from_system_call;
long ___ebx;
long ___ecx;
long ___edx;
long ___orig_eax;
long ___fs;
long ___es;
long ___esi;
long ___edi;
long ___ebp;
long ___eax;
long ___ds;
long ___es;
long ___fs;
long ___gs;
long ___orig_eax;
long ___eip;
long ___cs;
long ___eflags;
......@@ -140,6 +140,7 @@ char * ea(struct info * __info, unsigned short __code);
/* convert.c */
void frndint(const temp_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 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 @@
#define PAGE_SIZE 4096
#include <linux/fs.h>
#include <linux/kernel.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));
#define write_swap_page(nr,buffer) ll_rw_page(WRITE,SWAP_DEV,(nr),(buffer));
extern void rw_swap_page(int rw, unsigned int nr, char * buf);
#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 put_dirty_page(unsigned long page,unsigned long address);
......
......@@ -129,12 +129,13 @@ struct task_struct {
unsigned int flags; /* per process flags, defined below */
unsigned short used_math;
/* file system info */
int link_count;
int tty; /* -1 if no tty, so it must be signed */
unsigned short umask;
struct m_inode * pwd;
struct m_inode * root;
struct m_inode * executable;
struct m_inode * library;
struct inode * pwd;
struct inode * root;
struct inode * executable;
struct inode * library;
unsigned long close_on_exec;
struct file * filp[NR_OPEN];
/* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
......@@ -148,6 +149,10 @@ struct task_struct {
*/
#define PF_ALIGNWARN 0x00000001 /* Print alignment warning msgs */
/* 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
......@@ -167,7 +172,7 @@ struct task_struct {
{0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}}, \
/* flags */ 0, \
/* math */ 0, \
/* fs info */ -1,0022,NULL,NULL,NULL,NULL,0, \
/* fs info */ 0,-1,0022,NULL,NULL,NULL,NULL,0, \
/* filp */ {NULL,}, \
{ \
{0,0}, \
......@@ -212,7 +217,7 @@ __asm__("str %%ax\n\t" \
"subl %2,%%eax\n\t" \
"shrl $4,%%eax" \
:"=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
* checking that n isn't the current task, in which case it does nothing.
......@@ -231,7 +236,8 @@ __asm__("cmpl %%ecx,_current\n\t" \
"clts\n" \
"1:" \
::"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)
......@@ -262,23 +268,28 @@ __asm__("movw %%dx,%0\n\t" \
#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
#define _get_base(addr) ({\
unsigned long __base; \
__asm__("movb %3,%%dh\n\t" \
"movb %2,%%dl\n\t" \
"shll $16,%%edx\n\t" \
"movw %1,%%dx" \
:"=d" (__base) \
:"m" (*((addr)+2)), \
"m" (*((addr)+4)), \
"m" (*((addr)+7))); \
__base;})
static unsigned long inline _get_base(char * addr)
{
unsigned long __base;
__asm__("movb %3,%%dh\n\t"
"movb %2,%%dl\n\t"
"shll $16,%%edx\n\t"
"movw %1,%%dx"
:"=&d" (__base)
:"m" (*((addr)+2)),
"m" (*((addr)+4)),
"m" (*((addr)+7)));
return __base;
}
#define get_base(ldt) _get_base( ((char *)&(ldt)) )
#define get_limit(segment) ({ \
unsigned long __limit; \
__asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \
__limit;})
static unsigned long inline get_limit(unsigned long segment)
{
unsigned long __limit;
__asm__("lsll %1,%0"
:"=r" (__limit):"r" (segment));
return __limit+1;
}
#endif
......@@ -89,6 +89,8 @@ extern int sys_symlink();
extern int sys_lstat();
extern int sys_readlink();
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,
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,
sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname,
sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday,
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.... */
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 {
int pgrp;
int session;
int stopped;
struct winsize winsize;
void (*write)(struct tty_struct * tty);
struct tty_queue *read_q;
struct tty_queue *write_q;
......@@ -68,6 +69,9 @@ struct tty_struct {
extern struct tty_struct tty_table[];
extern int fg_console;
extern unsigned long video_num_columns;
extern unsigned long video_num_lines;
#define TTY_TABLE(nr) \
(tty_table + ((nr) ? (((nr) < 64)? (nr)-1:(nr)) : fg_console))
......@@ -84,7 +88,7 @@ void rs_init(void);
void con_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);
void con_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 update_screen(void);
void update_screen(int new_console);
#endif
......@@ -33,6 +33,26 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIGTTIN 21
#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 */
#define SA_NOCLDSTOP 1
#define SA_INTERRUPT 0x20000000
......
This diff is collapsed.
This diff is collapsed.
......@@ -24,6 +24,7 @@ struct timezone {
#define DST_TUR 9 /* Turkey */
#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_CLR(fd,fdsetp) (*(fdsetp) &= ~(1 << (fd)))
#define FD_ISSET(fd,fdsetp) ((*(fdsetp) >> fd) & 1)
......
This diff is collapsed.
......@@ -35,6 +35,7 @@
#define TIOCSSOFTCAR 0x541A
#define FIONREAD 0x541B
#define TIOCINQ FIONREAD
#define TIOCLINUX 0x541C
struct winsize {
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