Commit ce823b44 authored by Linus Torvalds's avatar Linus Torvalds

[PATCH] Linux-0.97.1 (August 6, 1992)

Make the page allocator use a free page list instead of a silly
linear search.

Add sys_vhangup() and stubs for send/rcv/sendto/recvfrom/shutdown.
We're making ready for real networking..

Remove nonworking extfs bitmap allocators. We'll have them in ext2.

[Original announcement below]

Patch 1 is essentially a performance-release, but it also contains some
other patches: Ross Biro's tcp-ip stubs are there (but not the tcpip
subdirectory: alpha-testers should know where to find that), as are the
ext-fs superblock cleanups. The first header-file patch by hlu is also
in there.

The resulting patch is pretty big - it's also not as cleaned up as I'd
like it to be.  The swapping/buffer-block handling heuristics are
better, but could still do with some tuning.  Also, the idle task in
this version doesn't do very much: it will be expanded to do some more
page-table calculations.

I will be unable to hack on linux for a couple of weeks (I'll still
answer mails, read the newsgroup and fix bugs, but no heavy-duty
hacking) due to some "circumstances beyond my control".  That probably
means that this patch is the last one for a while (three weeks) unless
some bad bugs show up.

                Linus
parent ddc733f4
...@@ -6,6 +6,13 @@ ...@@ -6,6 +6,13 @@
ROOT_DEV = /dev/hdb1 ROOT_DEV = /dev/hdb1
#
# uncomment this if you want kernel profiling: the profile_shift is the
# granularity of the profiling (5 = 32-byte granularity)
#
#PROFILING = -DPROFILE_SHIFT=2
# #
# uncomment the correct keyboard: # uncomment the correct keyboard:
# #
...@@ -71,7 +78,7 @@ LD86 =ld86 -0 ...@@ -71,7 +78,7 @@ LD86 =ld86 -0
AS =as AS =as
LD =ld LD =ld
HOSTCC =gcc -static HOSTCC =gcc -static
CC =gcc -nostdinc -I$(KERNELHDRS) CC =gcc -nostdinc -I$(KERNELHDRS) $(PROFILING)
MAKE =make MAKE =make
CPP =$(CC) -E CPP =$(CC) -E
AR =ar AR =ar
......
...@@ -557,16 +557,24 @@ static int try_to_free(struct buffer_head * bh) ...@@ -557,16 +557,24 @@ static int try_to_free(struct buffer_head * bh)
/* /*
* Try to free up some pages by shrinking the buffer-cache * Try to free up some pages by shrinking the buffer-cache
*
* Priority tells the routine how hard to try to shrink the
* buffers: 0 means "don't bother too much", while a value
* of 3 means "we'd better get some free pages now".
*/ */
int shrink_buffers(void) int shrink_buffers(unsigned int priority)
{ {
struct buffer_head *bh; struct buffer_head *bh;
int i; int i;
if (priority > 2) {
priority = 3;
sync_buffers(0);
}
bh = free_list; bh = free_list;
for (i = nr_buffers*2 ; i-- > 0 ; bh = bh->b_next_free) { i = nr_buffers >> (3-priority);
wait_on_buffer(bh); for ( ; i-- > 0 ; bh = bh->b_next_free) {
if (bh->b_count || !bh->b_this_page) if (bh->b_lock || bh->b_count || !bh->b_this_page)
continue; continue;
if (bh->b_dirt) { if (bh->b_dirt) {
ll_rw_block(WRITEA,bh); ll_rw_block(WRITEA,bh);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
.s.o: .s.o:
$(AS) -o $*.o $< $(AS) -o $*.o $<
OBJS= bitmap.o freelists.o truncate.o namei.o inode.o \ OBJS= freelists.o truncate.o namei.o inode.o \
file.o dir.o symlink.o blkdev.o chrdev.o fifo.o file.o dir.o symlink.o blkdev.o chrdev.o fifo.o
ext.o: $(OBJS) ext.o: $(OBJS)
......
...@@ -62,8 +62,6 @@ static int ext_readdir(struct inode * inode, struct file * filp, ...@@ -62,8 +62,6 @@ static int ext_readdir(struct inode * inode, struct file * filp,
if (!inode || !S_ISDIR(inode->i_mode)) if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF; return -EBADF;
/* if (filp->f_pos & (sizeof (struct ext_dir_entry) - 1))
return -EBADF; */
while (filp->f_pos < inode->i_size) { while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023; offset = filp->f_pos & 1023;
block = ext_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS); block = ext_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
...@@ -89,8 +87,8 @@ static int ext_readdir(struct inode * inode, struct file * filp, ...@@ -89,8 +87,8 @@ static int ext_readdir(struct inode * inode, struct file * filp,
return i; return i;
} }
} }
/* de++; */ de = (struct ext_dir_entry *) ((char *) de
de = (struct ext_dir_entry *) ((char *) de + de->rec_len); + de->rec_len);
} }
brelse(bh); brelse(bh);
} }
......
...@@ -15,21 +15,18 @@ ...@@ -15,21 +15,18 @@
free blocks and the number of the next block in the list. free blocks and the number of the next block in the list.
When an ext fs is mounted, the number of the first free block is stored When an ext fs is mounted, the number of the first free block is stored
in s->u.ext_sb.s_zmap[0] and the block header is stored in s->u.ext_sb.s_zmap[1]. u.ext_sb.s_zmap[2] in s->u.ext_sb.s_firstfreeblocknumber and the block header is stored in
contains the count of free blocks. s->u.ext_sb.s_firstfreeblock. u.ext_sb.s_freeblockscount contains the count
of free blocks.
Currently, it is a hack to allow this kind of management with the super_block
structure.
Perhaps, in the future, we may have to change the super_block structure to
include dedicated fields.
The free inodes are also managed by a linked list in a similar way. The The free inodes are also managed by a linked list in a similar way. The
super block contains the number of the first free inode. This inode contains super block contains the number of the first free inode. This inode contains
14 numbers of other free inodes and the number of the next inode in the list. 14 numbers of other free inodes and the number of the next inode in the list.
The number of the first free inode is stored in s->u.ext_sb.s_imap[0] and the header The number of the first free inode is stored in
of the block containing the inode is stored in s->u.ext_sb.s_imap[1]. u.ext_sb.s_imap[2] contains s->u.ext_sb.s_firstfreeinodenumber and the header of the block containing
the count of free inodes. the inode is stored in s->u.ext_sb.s_firstfreeinodeblock.
u.ext_sb.s_freeinodescount contains the count of free inodes.
*/ */
...@@ -38,8 +35,6 @@ ...@@ -38,8 +35,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#ifdef EXTFS_FREELIST
#define clear_block(addr) \ #define clear_block(addr) \
__asm__("cld\n\t" \ __asm__("cld\n\t" \
"rep\n\t" \ "rep\n\t" \
...@@ -55,7 +50,8 @@ int ext_free_block(int dev, int block) ...@@ -55,7 +50,8 @@ int ext_free_block(int dev, int block)
if (!(sb = get_super(dev))) if (!(sb = get_super(dev)))
panic("trying to free block on nonexistent device"); panic("trying to free block on nonexistent device");
lock_super (sb); lock_super (sb);
if (block < sb->u.ext_sb.s_firstdatazone || block >= sb->u.ext_sb.s_nzones) if (block < sb->u.ext_sb.s_firstdatazone
|| block >= sb->u.ext_sb.s_nzones)
panic("trying to free block not in datazone"); panic("trying to free block not in datazone");
bh = get_hash_table(dev, block, sb->s_blocksize); bh = get_hash_table(dev, block, sb->s_blocksize);
if (bh) { if (bh) {
...@@ -69,26 +65,27 @@ int ext_free_block(int dev, int block) ...@@ -69,26 +65,27 @@ int ext_free_block(int dev, int block)
if (bh->b_count) if (bh->b_count)
brelse(bh); brelse(bh);
} }
if (sb->u.ext_sb.s_zmap[1]) if (sb->u.ext_sb.s_firstfreeblock)
efb = (struct ext_free_block *) sb->u.ext_sb.s_zmap[1]->b_data; efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
if (!sb->u.ext_sb.s_zmap[1] || efb->count == 254) { if (!sb->u.ext_sb.s_firstfreeblock || efb->count == 254) {
#ifdef EXTFS_DEBUG #ifdef EXTFS_DEBUG
printk("ext_free_block: block full, skipping to %d\n", block); printk("ext_free_block: block full, skipping to %d\n", block);
#endif #endif
if (sb->u.ext_sb.s_zmap[1]) if (sb->u.ext_sb.s_firstfreeblock)
brelse (sb->u.ext_sb.s_zmap[1]); brelse (sb->u.ext_sb.s_firstfreeblock);
if (!(sb->u.ext_sb.s_zmap[1] = bread (dev, block, sb->s_blocksize))) if (!(sb->u.ext_sb.s_firstfreeblock = bread (dev,
block, sb->s_blocksize)))
panic ("ext_free_block: unable to read block to free\n"); panic ("ext_free_block: unable to read block to free\n");
efb = (struct ext_free_block *) sb->u.ext_sb.s_zmap[1]->b_data; efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
efb->next = (unsigned long) sb->u.ext_sb.s_zmap[0]; efb->next = sb->u.ext_sb.s_firstfreeblocknumber;
efb->count = 0; efb->count = 0;
sb->u.ext_sb.s_zmap[0] = (struct buffer_head *) block; sb->u.ext_sb.s_firstfreeblocknumber = block;
} else { } else {
efb->free[efb->count++] = block; efb->free[efb->count++] = block;
} }
sb->u.ext_sb.s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->u.ext_sb.s_zmap[2]) + 1); sb->u.ext_sb.s_freeblockscount ++;
sb->s_dirt = 1; sb->s_dirt = 1;
sb->u.ext_sb.s_zmap[1]->b_dirt = 1; sb->u.ext_sb.s_firstfreeblock->b_dirt = 1;
free_super (sb); free_super (sb);
return 1; return 1;
} }
...@@ -98,28 +95,30 @@ int ext_new_block(int dev) ...@@ -98,28 +95,30 @@ int ext_new_block(int dev)
struct buffer_head * bh; struct buffer_head * bh;
struct super_block * sb; struct super_block * sb;
struct ext_free_block * efb; struct ext_free_block * efb;
int /* i, */ j; int j;
if (!(sb = get_super(dev))) if (!(sb = get_super(dev)))
panic("trying to get new block from nonexistant device"); panic("trying to get new block from nonexistant device");
if (!sb->u.ext_sb.s_zmap[1]) if (!sb->u.ext_sb.s_firstfreeblock)
return 0; return 0;
lock_super (sb); lock_super (sb);
efb = (struct ext_free_block *) sb->u.ext_sb.s_zmap[1]->b_data; efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
if (efb->count) { if (efb->count) {
j = efb->free[--efb->count]; j = efb->free[--efb->count];
sb->u.ext_sb.s_zmap[1]->b_dirt = 1; sb->u.ext_sb.s_firstfreeblock->b_dirt = 1;
} else { } else {
#ifdef EXTFS_DEBUG #ifdef EXTFS_DEBUG
printk("ext_new_block: block empty, skipping to %d\n", efb->next); printk("ext_new_block: block empty, skipping to %d\n", efb->next);
#endif #endif
j = (unsigned long) sb->u.ext_sb.s_zmap[0]; j = sb->u.ext_sb.s_firstfreeblocknumber;
sb->u.ext_sb.s_zmap[0] = (struct buffer_head *) efb->next; sb->u.ext_sb.s_firstfreeblocknumber = efb->next;
brelse (sb->u.ext_sb.s_zmap[1]); brelse (sb->u.ext_sb.s_firstfreeblock);
if (!sb->u.ext_sb.s_zmap[0]) { if (!sb->u.ext_sb.s_firstfreeblocknumber) {
sb->u.ext_sb.s_zmap[1] = NULL; sb->u.ext_sb.s_firstfreeblock = NULL;
} else { } else {
if (!(sb->u.ext_sb.s_zmap[1] = bread (dev, (unsigned long) sb->u.ext_sb.s_zmap[0], sb->s_blocksize))) if (!(sb->u.ext_sb.s_firstfreeblock = bread (dev,
sb->u.ext_sb.s_firstfreeblocknumber,
sb->s_blocksize)))
panic ("ext_new_block: unable to read next free block\n"); panic ("ext_new_block: unable to read next free block\n");
} }
} }
...@@ -127,7 +126,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next); ...@@ -127,7 +126,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next);
printk ("ext_new_block: blk = %d\n", j); printk ("ext_new_block: blk = %d\n", j);
panic ("allocating block not in data zone\n"); panic ("allocating block not in data zone\n");
} }
sb->u.ext_sb.s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->u.ext_sb.s_zmap[2]) - 1); sb->u.ext_sb.s_freeblockscount --;
sb->s_dirt = 1; sb->s_dirt = 1;
if (!(bh=getblk(dev, j, sb->s_blocksize))) if (!(bh=getblk(dev, j, sb->s_blocksize)))
...@@ -153,10 +152,10 @@ unsigned long ext_count_free_blocks(struct super_block *sb) ...@@ -153,10 +152,10 @@ unsigned long ext_count_free_blocks(struct super_block *sb)
unsigned long count, block; unsigned long count, block;
lock_super (sb); lock_super (sb);
if (!sb->u.ext_sb.s_zmap[1]) if (!sb->u.ext_sb.s_firstfreeblock)
count = 0; count = 0;
else { else {
efb = (struct ext_free_block *) sb->u.ext_sb.s_zmap[1]->b_data; efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
count = efb->count + 1; count = efb->count + 1;
block = efb->next; block = efb->next;
while (block) { while (block) {
...@@ -172,11 +171,11 @@ unsigned long ext_count_free_blocks(struct super_block *sb) ...@@ -172,11 +171,11 @@ unsigned long ext_count_free_blocks(struct super_block *sb)
} }
} }
printk("ext_count_free_blocks: stored = %d, computed = %d\n", printk("ext_count_free_blocks: stored = %d, computed = %d\n",
(unsigned long) sb->u.ext_sb.s_zmap[2], count); sb->u.ext_sb.s_freeblockscount, count);
free_super (sb); free_super (sb);
return count; return count;
#else #else
return (unsigned long) sb->u.ext_sb.s_zmap[2]; return sb->u.ext_sb.s_freeblockscount;
#endif #endif
} }
...@@ -210,30 +209,30 @@ void ext_free_inode(struct inode * inode) ...@@ -210,30 +209,30 @@ void ext_free_inode(struct inode * inode)
free_super (inode->i_sb); free_super (inode->i_sb);
return; return;
} }
if (inode->i_sb->u.ext_sb.s_imap[1]) if (inode->i_sb->u.ext_sb.s_firstfreeinodeblock)
efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_imap[1]->b_data) + efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
(((unsigned long) inode->i_sb->u.ext_sb.s_imap[0])-1)%EXT_INODES_PER_BLOCK; (inode->i_sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
if (!inode->i_sb->u.ext_sb.s_imap[1] || efi->count == 14) { if (!inode->i_sb->u.ext_sb.s_firstfreeinodeblock || efi->count == 14) {
#ifdef EXTFS_DEBUG #ifdef EXTFS_DEBUG
printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino); printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
#endif #endif
if (inode->i_sb->u.ext_sb.s_imap[1]) if (inode->i_sb->u.ext_sb.s_firstfreeinodeblock)
brelse (inode->i_sb->u.ext_sb.s_imap[1]); brelse (inode->i_sb->u.ext_sb.s_firstfreeinodeblock);
block = 2 + (inode->i_ino - 1) / EXT_INODES_PER_BLOCK; block = 2 + (inode->i_ino - 1) / EXT_INODES_PER_BLOCK;
if (!(bh = bread(inode->i_dev, block, inode->i_sb->s_blocksize))) if (!(bh = bread(inode->i_dev, block, inode->i_sb->s_blocksize)))
panic("ext_free_inode: unable to read inode block\n"); panic("ext_free_inode: unable to read inode block\n");
efi = ((struct ext_free_inode *) bh->b_data) + efi = ((struct ext_free_inode *) bh->b_data) +
(inode->i_ino - 1) % EXT_INODES_PER_BLOCK; (inode->i_ino - 1) % EXT_INODES_PER_BLOCK;
efi->next = (unsigned long) inode->i_sb->u.ext_sb.s_imap[0]; efi->next = inode->i_sb->u.ext_sb.s_firstfreeinodenumber;
efi->count = 0; efi->count = 0;
inode->i_sb->u.ext_sb.s_imap[0] = (struct buffer_head *) inode->i_ino; inode->i_sb->u.ext_sb.s_firstfreeinodenumber = inode->i_ino;
inode->i_sb->u.ext_sb.s_imap[1] = bh; inode->i_sb->u.ext_sb.s_firstfreeinodeblock = bh;
} else { } else {
efi->free[efi->count++] = inode->i_ino; efi->free[efi->count++] = inode->i_ino;
} }
inode->i_sb->u.ext_sb.s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->u.ext_sb.s_imap[2]) + 1); inode->i_sb->u.ext_sb.s_freeinodescount ++;
inode->i_sb->s_dirt = 1; inode->i_sb->s_dirt = 1;
inode->i_sb->u.ext_sb.s_imap[1]->b_dirt = 1; inode->i_sb->u.ext_sb.s_firstfreeinodeblock->b_dirt = 1;
free_super (inode->i_sb); free_super (inode->i_sb);
memset(inode,0,sizeof(*inode)); memset(inode,0,sizeof(*inode));
} }
...@@ -243,7 +242,7 @@ struct inode * ext_new_inode(int dev) ...@@ -243,7 +242,7 @@ struct inode * ext_new_inode(int dev)
struct inode * inode; struct inode * inode;
struct ext_free_inode * efi; struct ext_free_inode * efi;
unsigned long block; unsigned long block;
int /* i, */ j; int j;
if (!(inode=get_empty_inode())) if (!(inode=get_empty_inode()))
return NULL; return NULL;
...@@ -253,34 +252,34 @@ struct inode * ext_new_inode(int dev) ...@@ -253,34 +252,34 @@ struct inode * ext_new_inode(int dev)
return NULL; return NULL;
} }
inode->i_flags = inode->i_sb->s_flags; inode->i_flags = inode->i_sb->s_flags;
if (!inode->i_sb->u.ext_sb.s_imap[1]) if (!inode->i_sb->u.ext_sb.s_firstfreeinodeblock)
return 0; return 0;
lock_super (inode->i_sb); lock_super (inode->i_sb);
efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_imap[1]->b_data) + efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
(((unsigned long) inode->i_sb->u.ext_sb.s_imap[0])-1)%EXT_INODES_PER_BLOCK; (inode->i_sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
if (efi->count) { if (efi->count) {
j = efi->free[--efi->count]; j = efi->free[--efi->count];
inode->i_sb->u.ext_sb.s_imap[1]->b_dirt = 1; inode->i_sb->u.ext_sb.s_firstfreeinodeblock->b_dirt = 1;
} else { } else {
#ifdef EXTFS_DEBUG #ifdef EXTFS_DEBUG
printk("ext_free_inode: inode empty, skipping to %d\n", efi->next); printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
#endif #endif
j = (unsigned long) inode->i_sb->u.ext_sb.s_imap[0]; j = inode->i_sb->u.ext_sb.s_firstfreeinodenumber;
if (efi->next > inode->i_sb->u.ext_sb.s_ninodes) { if (efi->next > inode->i_sb->u.ext_sb.s_ninodes) {
printk ("efi->next = %d\n", efi->next); printk ("efi->next = %d\n", efi->next);
panic ("ext_new_inode: bad inode number in free list\n"); panic ("ext_new_inode: bad inode number in free list\n");
} }
inode->i_sb->u.ext_sb.s_imap[0] = (struct buffer_head *) efi->next; inode->i_sb->u.ext_sb.s_firstfreeinodenumber = efi->next;
block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK; block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK;
brelse (inode->i_sb->u.ext_sb.s_imap[1]); brelse (inode->i_sb->u.ext_sb.s_firstfreeinodeblock);
if (!inode->i_sb->u.ext_sb.s_imap[0]) { if (!inode->i_sb->u.ext_sb.s_firstfreeinodenumber) {
inode->i_sb->u.ext_sb.s_imap[1] = NULL; inode->i_sb->u.ext_sb.s_firstfreeinodeblock = NULL;
} else { } else {
if (!(inode->i_sb->u.ext_sb.s_imap[1] = bread (dev, block, inode->i_sb->s_blocksize))) if (!(inode->i_sb->u.ext_sb.s_firstfreeinodeblock = bread (dev, block, inode->i_sb->s_blocksize)))
panic ("ext_new_inode: unable to read next free inode block\n"); panic ("ext_new_inode: unable to read next free inode block\n");
} }
} }
inode->i_sb->u.ext_sb.s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->u.ext_sb.s_imap[2]) - 1); inode->i_sb->u.ext_sb.s_freeinodescount --;
inode->i_sb->s_dirt = 1; inode->i_sb->s_dirt = 1;
inode->i_count = 1; inode->i_count = 1;
inode->i_nlink = 1; inode->i_nlink = 1;
...@@ -306,17 +305,17 @@ unsigned long ext_count_free_inodes(struct super_block *sb) ...@@ -306,17 +305,17 @@ unsigned long ext_count_free_inodes(struct super_block *sb)
unsigned long count, block, ino; unsigned long count, block, ino;
lock_super (sb); lock_super (sb);
if (!sb->u.ext_sb.s_imap[1]) if (!sb->u.ext_sb.s_firstfreeinodeblock)
count = 0; count = 0;
else { else {
efi = ((struct ext_free_inode *) sb->u.ext_sb.s_imap[1]->b_data) + efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
((((unsigned long) sb->u.ext_sb.s_imap[0])-1)%EXT_INODES_PER_BLOCK); ((sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK);
count = efi->count + 1; count = efi->count + 1;
ino = efi->next; ino = efi->next;
while (ino) { while (ino) {
if (ino < 1 || ino > sb->u.ext_sb.s_ninodes) { if (ino < 1 || ino > sb->u.ext_sb.s_ninodes) {
printk ("u.ext_sb.s_imap[0] = %d, ino = %d\n", printk ("u.ext_sb.s_firstfreeinodenumber = %d, ino = %d\n",
(int) sb->u.ext_sb.s_imap[0],ino); (int) sb->u.ext_sb.s_firstfreeinodenumber,ino);
panic ("ext_count_fre_inodes: bad inode number in free list\n"); panic ("ext_count_fre_inodes: bad inode number in free list\n");
} }
block = 2 + ((ino - 1) / EXT_INODES_PER_BLOCK); block = 2 + ((ino - 1) / EXT_INODES_PER_BLOCK);
...@@ -333,12 +332,10 @@ unsigned long ext_count_free_inodes(struct super_block *sb) ...@@ -333,12 +332,10 @@ unsigned long ext_count_free_inodes(struct super_block *sb)
} }
} }
printk("ext_count_free_inodes: stored = %d, computed = %d\n", printk("ext_count_free_inodes: stored = %d, computed = %d\n",
(unsigned long) sb->u.ext_sb.s_imap[2], count); sb->u.ext_sb.s_freeinodescount, count);
free_super (sb); free_super (sb);
return count; return count;
#else #else
return (unsigned long) sb->u.ext_sb.s_imap[2]; return sb->u.ext_sb.s_freeinodescount;
#endif #endif
} }
#endif
...@@ -31,24 +31,13 @@ void ext_put_inode(struct inode *inode) ...@@ -31,24 +31,13 @@ void ext_put_inode(struct inode *inode)
void ext_put_super(struct super_block *sb) void ext_put_super(struct super_block *sb)
{ {
#ifdef EXTFS_BITMAP
int i;
#endif
lock_super(sb); lock_super(sb);
sb->s_dev = 0; sb->s_dev = 0;
#ifdef EXTFS_BITMAP if (sb->u.ext_sb.s_firstfreeinodeblock)
for(i = 0 ; i < EXT_I_MAP_SLOTS ; i++) brelse (sb->u.ext_sb.s_firstfreeinodeblock);
brelse(sb->u.ext_sb.s_imap[i]); if (sb->u.ext_sb.s_firstfreeblock)
for(i = 0 ; i < EXT_Z_MAP_SLOTS ; i++) brelse (sb->u.ext_sb.s_firstfreeblock);
brelse(sb->u.ext_sb.s_zmap[i]);
#endif
#ifdef EXTFS_FREELIST
if (sb->u.ext_sb.s_imap[1])
brelse (sb->u.ext_sb.s_imap[1]);
if (sb->u.ext_sb.s_zmap[1])
brelse (sb->u.ext_sb.s_zmap[1]);
#endif
free_super(sb); free_super(sb);
return; return;
} }
...@@ -67,9 +56,6 @@ struct super_block *ext_read_super(struct super_block *s,void *data) ...@@ -67,9 +56,6 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
struct buffer_head *bh; struct buffer_head *bh;
struct ext_super_block *es; struct ext_super_block *es;
int dev = s->s_dev,block; int dev = s->s_dev,block;
#ifdef EXTFS_BITMAP
int i;
#endif
lock_super(s); lock_super(s);
if (!(bh = bread(dev, 1, BLOCK_SIZE))) { if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
...@@ -78,26 +64,18 @@ struct super_block *ext_read_super(struct super_block *s,void *data) ...@@ -78,26 +64,18 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
printk("bread failed\n"); printk("bread failed\n");
return NULL; return NULL;
} }
/* *((struct ext_super_block *) s) =
*((struct ext_super_block *) bh->b_data); */
es = (struct ext_super_block *) bh->b_data; es = (struct ext_super_block *) bh->b_data;
s->s_blocksize = 1024; s->s_blocksize = 1024;
s->u.ext_sb.s_ninodes = es->s_ninodes; s->u.ext_sb.s_ninodes = es->s_ninodes;
s->u.ext_sb.s_nzones = es->s_nzones; s->u.ext_sb.s_nzones = es->s_nzones;
#ifdef EXTFS_BITMAP
s->u.ext_sb.s_imap_blocks = es->s_imap_blocks;
s->u.ext_sb.s_zmap_blocks = es->s_zmap_blocks;
#endif
s->u.ext_sb.s_firstdatazone = es->s_firstdatazone; s->u.ext_sb.s_firstdatazone = es->s_firstdatazone;
s->u.ext_sb.s_log_zone_size = es->s_log_zone_size; s->u.ext_sb.s_log_zone_size = es->s_log_zone_size;
s->u.ext_sb.s_max_size = es->s_max_size; s->u.ext_sb.s_max_size = es->s_max_size;
s->s_magic = es->s_magic; s->s_magic = es->s_magic;
#ifdef EXTFS_FREELIST s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock;
s->u.ext_sb.s_zmap[0] = (struct buffer_head *) es->s_firstfreeblock; s->u.ext_sb.s_freeblockscount = es->s_freeblockscount;
s->u.ext_sb.s_zmap[2] = (struct buffer_head *) es->s_freeblockscount; s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode;
s->u.ext_sb.s_imap[0] = (struct buffer_head *) es->s_firstfreeinode; s->u.ext_sb.s_freeinodescount = es->s_freeinodescount;
s->u.ext_sb.s_imap[2] = (struct buffer_head *) es->s_freeinodescount;
#endif
brelse(bh); brelse(bh);
if (s->s_magic != EXT_SUPER_MAGIC) { if (s->s_magic != EXT_SUPER_MAGIC) {
s->s_dev = 0; s->s_dev = 0;
...@@ -105,59 +83,28 @@ struct super_block *ext_read_super(struct super_block *s,void *data) ...@@ -105,59 +83,28 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
printk("magic match failed\n"); printk("magic match failed\n");
return NULL; return NULL;
} }
#ifdef EXTFS_BITMAP if (!s->u.ext_sb.s_firstfreeblocknumber)
for (i=0;i < EXT_I_MAP_SLOTS;i++) s->u.ext_sb.s_firstfreeblock = NULL;
s->u.ext_sb.s_imap[i] = NULL;
for (i=0;i < EXT_Z_MAP_SLOTS;i++)
s->u.ext_sb.s_zmap[i] = NULL;
block=2;
for (i=0 ; i < s->u.ext_sb.s_imap_blocks ; i++)
if (s->u.ext_sb.s_imap[i]=bread(dev, block, BLOCK_SIZE))
block++;
else
break;
for (i=0 ; i < s->u.ext_sb.s_zmap_blocks ; i++)
if (s->u.ext_sb.s_zmap[i]=bread(dev, block, BLOCK_SIZE))
block++;
else
break;
if (block != 2+s->u.ext_sb.s_imap_blocks+s->u.ext_sb.s_zmap_blocks) {
for(i=0;i<EXT_I_MAP_SLOTS;i++)
brelse(s->u.ext_sb.s_imap[i]);
for(i=0;i<EXT_Z_MAP_SLOTS;i++)
brelse(s->u.ext_sb.s_zmap[i]);
s->s_dev=0;
free_super(s);
printk("block failed\n");
return NULL;
}
s->u.ext_sb.s_imap[0]->b_data[0] |= 1;
s->u.ext_sb.s_zmap[0]->b_data[0] |= 1;
#endif
#ifdef EXTFS_FREELIST
if (!s->u.ext_sb.s_zmap[0])
s->u.ext_sb.s_zmap[1] = NULL;
else else
if (!(s->u.ext_sb.s_zmap[1] = bread(dev, (unsigned long) s->u.ext_sb.s_zmap[0], BLOCK_SIZE))) { if (!(s->u.ext_sb.s_firstfreeblock = bread(dev,
s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) {
printk ("ext_read_super: unable to read first free block\n"); printk ("ext_read_super: unable to read first free block\n");
s->s_dev = 0; s->s_dev = 0;
free_super(s); free_super(s);
return NULL; return NULL;
} }
if (!s->u.ext_sb.s_imap[0]) if (!s->u.ext_sb.s_firstfreeinodenumber)
s->u.ext_sb.s_imap[1] = NULL; s->u.ext_sb.s_firstfreeinodeblock = NULL;
else { else {
block = 2 + (((unsigned long) s->u.ext_sb.s_imap[0]) - 1) / EXT_INODES_PER_BLOCK; block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK;
if (!(s->u.ext_sb.s_imap[1] = bread(dev, block, BLOCK_SIZE))) { if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) {
printk ("ext_read_super: unable to read first free inode block\n"); printk ("ext_read_super: unable to read first free inode block\n");
brelse(s->u.ext_sb.s_zmap[1]); brelse(s->u.ext_sb.s_firstfreeblock);
s->s_dev = 0; s->s_dev = 0;
free_super (s); free_super (s);
return NULL; return NULL;
} }
} }
#endif
free_super(s); free_super(s);
/* set up enough so that it can read an inode */ /* set up enough so that it can read an inode */
s->s_dev = dev; s->s_dev = dev;
...@@ -172,26 +119,21 @@ struct super_block *ext_read_super(struct super_block *s,void *data) ...@@ -172,26 +119,21 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
void ext_write_super (struct super_block *sb) void ext_write_super (struct super_block *sb)
{ {
#ifdef EXTFS_FREELIST
struct buffer_head * bh; struct buffer_head * bh;
struct ext_super_block * es; struct ext_super_block * es;
#ifdef EXTFS_DEBUG
printk ("ext_write_super called\n");
#endif
if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) { if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) {
printk ("ext_write_super: bread failed\n"); printk ("ext_write_super: bread failed\n");
return; return;
} }
es = (struct ext_super_block *) bh->b_data; es = (struct ext_super_block *) bh->b_data;
es->s_firstfreeblock = (unsigned long) sb->u.ext_sb.s_zmap[0]; es->s_firstfreeblock = sb->u.ext_sb.s_firstfreeblocknumber;
es->s_freeblockscount = (unsigned long) sb->u.ext_sb.s_zmap[2]; es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
es->s_firstfreeinode = (unsigned long) sb->u.ext_sb.s_imap[0]; es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
es->s_freeinodescount = (unsigned long) sb->u.ext_sb.s_imap[2]; es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
bh->b_dirt = 1; bh->b_dirt = 1;
brelse (bh); brelse (bh);
sb->s_dirt = 0; sb->s_dirt = 0;
#endif
} }
void ext_statfs (struct super_block *sb, struct statfs *buf) void ext_statfs (struct super_block *sb, struct statfs *buf)
...@@ -200,7 +142,8 @@ void ext_statfs (struct super_block *sb, struct statfs *buf) ...@@ -200,7 +142,8 @@ void ext_statfs (struct super_block *sb, struct statfs *buf)
put_fs_long(EXT_SUPER_MAGIC, &buf->f_type); put_fs_long(EXT_SUPER_MAGIC, &buf->f_type);
put_fs_long(1024, &buf->f_bsize); put_fs_long(1024, &buf->f_bsize);
put_fs_long(sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size, &buf->f_blocks); put_fs_long(sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size,
&buf->f_blocks);
tmp = ext_count_free_blocks(sb); tmp = ext_count_free_blocks(sb);
put_fs_long(tmp, &buf->f_bfree); put_fs_long(tmp, &buf->f_bfree);
put_fs_long(tmp, &buf->f_bavail); put_fs_long(tmp, &buf->f_bavail);
...@@ -341,13 +284,7 @@ void ext_read_inode(struct inode * inode) ...@@ -341,13 +284,7 @@ void ext_read_inode(struct inode * inode)
struct ext_inode * raw_inode; struct ext_inode * raw_inode;
int block; int block;
#ifdef EXTFS_BITMAP
block = 2 + inode->i_sb->u.ext_sb.s_imap_blocks + inode->i_sb->u.ext_sb.s_zmap_blocks +
(inode->i_ino-1)/EXT_INODES_PER_BLOCK;
#endif
#ifdef EXTFS_FREELIST
block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK; block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
#endif
if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
panic("unable to read i-node block"); panic("unable to read i-node block");
raw_inode = ((struct ext_inode *) bh->b_data) + raw_inode = ((struct ext_inode *) bh->b_data) +
...@@ -389,13 +326,7 @@ void ext_write_inode(struct inode * inode) ...@@ -389,13 +326,7 @@ void ext_write_inode(struct inode * inode)
struct ext_inode * raw_inode; struct ext_inode * raw_inode;
int block; int block;
#ifdef EXTFS_BITMAP
block = 2 + inode->i_sb->u.ext_sb.s_imap_blocks + inode->i_sb->u.ext_sb.s_zmap_blocks +
(inode->i_ino-1)/EXT_INODES_PER_BLOCK;
#endif
#ifdef EXTFS_FREELIST
block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK; block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
#endif
if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
panic("unable to read i-node block"); panic("unable to read i-node block");
raw_inode = ((struct ext_inode *)bh->b_data) + raw_inode = ((struct ext_inode *)bh->b_data) +
......
...@@ -64,8 +64,6 @@ static int ext_match(int len,const char * name,struct ext_dir_entry * de) ...@@ -64,8 +64,6 @@ static int ext_match(int len,const char * name,struct ext_dir_entry * de)
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */ /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
if (!len && (de->name[0]=='.') && (de->name[1]=='\0')) if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
return 1; return 1;
/* if (len < EXT_NAME_LEN && de->name[len])
return 0; */
if (len < EXT_NAME_LEN && len != de->name_len) if (len < EXT_NAME_LEN && len != de->name_len)
return 0; return 0;
__asm__("cld\n\t" __asm__("cld\n\t"
...@@ -92,8 +90,7 @@ static struct buffer_head * ext_find_entry(struct inode * dir, ...@@ -92,8 +90,7 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
const char * name, int namelen, struct ext_dir_entry ** res_dir, const char * name, int namelen, struct ext_dir_entry ** res_dir,
struct ext_dir_entry ** prev_dir, struct ext_dir_entry ** next_dir) struct ext_dir_entry ** prev_dir, struct ext_dir_entry ** next_dir)
{ {
/* int entries; */ int block;
int block /* ,i */;
long offset; long offset;
struct buffer_head * bh; struct buffer_head * bh;
struct ext_dir_entry * de; struct ext_dir_entry * de;
...@@ -108,7 +105,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir, ...@@ -108,7 +105,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
if (namelen > EXT_NAME_LEN) if (namelen > EXT_NAME_LEN)
namelen = EXT_NAME_LEN; namelen = EXT_NAME_LEN;
#endif #endif
/* entries = dir->i_size / (sizeof (struct ext_dir_entry)); */
if (!(block = dir->i_data[0])) if (!(block = dir->i_data[0]))
return NULL; return NULL;
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
...@@ -117,7 +113,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir, ...@@ -117,7 +113,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
*prev_dir = NULL; *prev_dir = NULL;
if (next_dir) if (next_dir)
*next_dir = NULL; *next_dir = NULL;
/* i = 0; */
offset = 0; offset = 0;
de = (struct ext_dir_entry *) bh->b_data; de = (struct ext_dir_entry *) bh->b_data;
while (offset < dir->i_size) { while (offset < dir->i_size) {
...@@ -126,8 +121,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir, ...@@ -126,8 +121,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
bh = NULL; bh = NULL;
if (!(block = ext_bmap(dir,offset>>BLOCK_SIZE_BITS)) || if (!(block = ext_bmap(dir,offset>>BLOCK_SIZE_BITS)) ||
!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) { !(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
/* i += EXT_DIR_ENTRIES_PER_BLOCK; */
/* offset += BLOCK_SIZE; */
continue; continue;
} }
de = (struct ext_dir_entry *) bh->b_data; de = (struct ext_dir_entry *) bh->b_data;
...@@ -148,7 +141,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir, ...@@ -148,7 +141,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
if (prev_dir) if (prev_dir)
*prev_dir = de; *prev_dir = de;
de = (struct ext_dir_entry *) ((char *) de + de->rec_len); de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
/* i++; */
} }
brelse(bh); brelse(bh);
return NULL; return NULL;
...@@ -218,7 +210,6 @@ static struct buffer_head * ext_add_entry(struct inode * dir, ...@@ -218,7 +210,6 @@ static struct buffer_head * ext_add_entry(struct inode * dir,
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
return NULL; return NULL;
rec_len = ((8 + namelen + EXT_DIR_PAD - 1) / EXT_DIR_PAD) * EXT_DIR_PAD; rec_len = ((8 + namelen + EXT_DIR_PAD - 1) / EXT_DIR_PAD) * EXT_DIR_PAD;
/* i = 0; */
offset = 0; offset = 0;
de = (struct ext_dir_entry *) bh->b_data; de = (struct ext_dir_entry *) bh->b_data;
while (1) { while (1) {
...@@ -232,7 +223,6 @@ printk ("ext_add_entry: skipping to next block\n"); ...@@ -232,7 +223,6 @@ printk ("ext_add_entry: skipping to next block\n");
if (!block) if (!block)
return NULL; return NULL;
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) { if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
/* i += EXT_DIR_ENTRIES_PER_BLOCK; */
offset += BLOCK_SIZE; offset += BLOCK_SIZE;
continue; continue;
} }
...@@ -271,7 +261,6 @@ printk ("ext_add_entry : creating next block\n"); ...@@ -271,7 +261,6 @@ printk ("ext_add_entry : creating next block\n");
/* Allocate the entry */ /* Allocate the entry */
de->inode=0; de->inode=0;
de->rec_len = rec_len; de->rec_len = rec_len;
/* dir->i_size = (i+1)*sizeof(struct ext_dir_entry); */
dir->i_size += de->rec_len; dir->i_size += de->rec_len;
dir->i_dirt = 1; dir->i_dirt = 1;
dir->i_ctime = CURRENT_TIME; dir->i_ctime = CURRENT_TIME;
...@@ -292,7 +281,7 @@ printk ("ext_add_entry : creating next block\n"); ...@@ -292,7 +281,7 @@ printk ("ext_add_entry : creating next block\n");
dir->i_mtime = CURRENT_TIME; dir->i_mtime = CURRENT_TIME;
de->name_len = namelen; de->name_len = namelen;
for (i=0; i < namelen ; i++) for (i=0; i < namelen ; i++)
de->name[i]=/*(i<namelen)?*/get_fs_byte(name+i)/*:0*/; de->name[i]=get_fs_byte(name+i);
bh->b_dirt = 1; bh->b_dirt = 1;
*res_dir = de; *res_dir = de;
return bh; return bh;
...@@ -441,7 +430,6 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode) ...@@ -441,7 +430,6 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
de->rec_len=16; de->rec_len=16;
de->name_len=1; de->name_len=1;
strcpy(de->name,"."); strcpy(de->name,".");
/* de++; */
de = (struct ext_dir_entry *) ((char *) de + de->rec_len); de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
de->inode = dir->i_ino; de->inode = dir->i_ino;
de->rec_len=16; de->rec_len=16;
...@@ -474,13 +462,11 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode) ...@@ -474,13 +462,11 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
*/ */
static int empty_dir(struct inode * inode) static int empty_dir(struct inode * inode)
{ {
int /* nr, */ block; int block;
/* int len; */
unsigned long offset; unsigned long offset;
struct buffer_head * bh; struct buffer_head * bh;
struct ext_dir_entry * de, * de1; struct ext_dir_entry * de, * de1;
/* len = inode->i_size / sizeof (struct ext_dir_entry); */
if (inode->i_size < 2 * 12 || !inode->i_data[0] || if (inode->i_size < 2 * 12 || !inode->i_data[0] ||
!(bh=bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) { !(bh=bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
printk("warning - bad directory on dev %04x\n",inode->i_dev); printk("warning - bad directory on dev %04x\n",inode->i_dev);
...@@ -493,7 +479,6 @@ static int empty_dir(struct inode * inode) ...@@ -493,7 +479,6 @@ static int empty_dir(struct inode * inode)
printk("warning - bad directory on dev %04x\n",inode->i_dev); printk("warning - bad directory on dev %04x\n",inode->i_dev);
return 0; return 0;
} }
/* nr = 2; */
offset = de->rec_len + de1->rec_len; offset = de->rec_len + de1->rec_len;
de = (struct ext_dir_entry *) ((char *) de1 + de1->rec_len); de = (struct ext_dir_entry *) ((char *) de1 + de1->rec_len);
while (offset < inode->i_size ) { while (offset < inode->i_size ) {
...@@ -749,12 +734,10 @@ static int subdir(struct inode * new, struct inode * old) ...@@ -749,12 +734,10 @@ static int subdir(struct inode * new, struct inode * old)
#define PARENT_INO(buffer) \ #define PARENT_INO(buffer) \
((struct ext_dir_entry *) ((char *) buffer + \ ((struct ext_dir_entry *) ((char *) buffer + \
((struct ext_dir_entry *) buffer)->rec_len))->inode ((struct ext_dir_entry *) buffer)->rec_len))->inode
/* (((struct ext_dir_entry *) (buffer))[1].inode) */
#define PARENT_NAME(buffer) \ #define PARENT_NAME(buffer) \
((struct ext_dir_entry *) ((char *) buffer + \ ((struct ext_dir_entry *) ((char *) buffer + \
((struct ext_dir_entry *) buffer)->rec_len))->name ((struct ext_dir_entry *) buffer)->rec_len))->name
/* (((struct ext_dir_entry *) (buffer))[1].name) */
/* /*
* rename uses retrying to avoid race-conditions: at least they should be minimal. * rename uses retrying to avoid race-conditions: at least they should be minimal.
......
...@@ -166,8 +166,6 @@ void ext_truncate(struct inode * inode) ...@@ -166,8 +166,6 @@ void ext_truncate(struct inode * inode)
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode))) S_ISLNK(inode->i_mode)))
return; return;
/* if (inode->i_data[7] & 0xffff0000)
printk("BAD! ext inode has 16 high bits set\n"); */
while (1) { while (1) {
flag = trunc_direct(inode); flag = trunc_direct(inode);
flag |= trunc_indirect(inode,9,(unsigned long *)&inode->i_data[9]); flag |= trunc_indirect(inode,9,(unsigned long *)&inode->i_data[9]);
......
...@@ -51,7 +51,8 @@ int sys_dup(unsigned int fildes) ...@@ -51,7 +51,8 @@ int sys_dup(unsigned int fildes)
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{ {
struct file * filp; struct file * filp;
extern int sock_fcntl (struct file *, unsigned int cmd,
unsigned long arg);
if (fd >= NR_OPEN || !(filp = current->filp[fd])) if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF; return -EBADF;
switch (cmd) { switch (cmd) {
...@@ -74,6 +75,11 @@ int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -74,6 +75,11 @@ int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
case F_GETLK: case F_SETLK: case F_SETLKW: case F_GETLK: case F_SETLK: case F_SETLKW:
return -ENOSYS; return -ENOSYS;
default: default:
/* sockets need a few special fcntls. */
if (S_ISSOCK (filp->f_inode->i_mode))
{
return (sock_fcntl (filp, cmd, arg));
}
return -EINVAL; return -EINVAL;
} }
} }
...@@ -79,10 +79,15 @@ int minix_free_block(int dev, int block) ...@@ -79,10 +79,15 @@ int minix_free_block(int dev, int block)
struct buffer_head * bh; struct buffer_head * bh;
unsigned int bit,zone; unsigned int bit,zone;
if (!(sb = get_super(dev))) if (!(sb = get_super(dev))) {
panic("trying to free block on nonexistent device"); printk("trying to free block on nonexistent device\n");
if (block < sb->u.minix_sb.s_firstdatazone || block >= sb->u.minix_sb.s_nzones) return 1;
panic("trying to free block not in datazone"); }
if (block < sb->u.minix_sb.s_firstdatazone ||
block >= sb->u.minix_sb.s_nzones) {
printk("trying to free block not in datazone\n");
return 1;
}
bh = get_hash_table(dev,block,BLOCK_SIZE); bh = get_hash_table(dev,block,BLOCK_SIZE);
if (bh) { if (bh) {
if (bh->b_count > 1) { if (bh->b_count > 1) {
...@@ -110,8 +115,11 @@ int minix_new_block(int dev) ...@@ -110,8 +115,11 @@ int minix_new_block(int dev)
struct super_block * sb; struct super_block * sb;
int i,j; int i,j;
if (!(sb = get_super(dev))) if (!(sb = get_super(dev))) {
panic("trying to get new block from nonexistant device"); printk("trying to get new block from nonexistant device\n");
return 0;
}
repeat:
j = 8192; j = 8192;
for (i=0 ; i<8 ; i++) for (i=0 ; i<8 ; i++)
if (bh=sb->u.minix_sb.s_zmap[i]) if (bh=sb->u.minix_sb.s_zmap[i])
...@@ -119,16 +127,22 @@ int minix_new_block(int dev) ...@@ -119,16 +127,22 @@ int minix_new_block(int dev)
break; break;
if (i>=8 || !bh || j>=8192) if (i>=8 || !bh || j>=8192)
return 0; return 0;
if (set_bit(j,bh->b_data)) if (set_bit(j,bh->b_data)) {
panic("new_block: bit already set"); printk("new_block: bit already set");
goto repeat;
}
bh->b_dirt = 1; bh->b_dirt = 1;
j += i*8192 + sb->u.minix_sb.s_firstdatazone-1; j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
if (j >= sb->u.minix_sb.s_nzones) if (j >= sb->u.minix_sb.s_nzones)
return 0; return 0;
if (!(bh=getblk(dev,j,BLOCK_SIZE))) if (!(bh=getblk(dev,j,BLOCK_SIZE))) {
panic("new_block: cannot get block"); printk("new_block: cannot get block");
if (bh->b_count != 1) return 0;
panic("new block: count is != 1"); }
if (bh->b_count != 1) {
printk("new block: count is != 1");
return 0;
}
clear_block(bh->b_data); clear_block(bh->b_data);
bh->b_uptodate = 1; bh->b_uptodate = 1;
bh->b_dirt = 1; bh->b_dirt = 1;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/tty.h>
#include <asm/segment.h> #include <asm/segment.h>
struct file_operations * chrdev_fops[MAX_CHRDEV] = { struct file_operations * chrdev_fops[MAX_CHRDEV] = {
...@@ -338,35 +338,132 @@ int sys_creat(const char * pathname, int mode) ...@@ -338,35 +338,132 @@ int sys_creat(const char * pathname, int mode)
return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
} }
int sys_close(unsigned int fd) static int
{ close_fp (struct file *filp)
struct file * filp; {
struct inode * inode; struct inode *inode;
if (fd >= NR_OPEN)
return -EINVAL;
current->close_on_exec &= ~(1<<fd);
if (!(filp = current->filp[fd]))
return -EINVAL;
current->filp[fd] = NULL;
if (filp->f_count == 0) { if (filp->f_count == 0) {
printk("Close: file count is 0\n"); printk("Close: file count is 0\n");
return 0; return 0;
} }
if (filp->f_count > 1) { if (filp->f_count > 1) {
filp->f_count--; filp->f_count--;
return 0; return 0;
} }
inode = filp->f_inode; inode = filp->f_inode;
if (filp->f_op && filp->f_op->release) if (filp->f_op && filp->f_op->release)
filp->f_op->release(inode,filp); filp->f_op->release(inode,filp);
filp->f_count--; filp->f_count--;
filp->f_inode = NULL; filp->f_inode = NULL;
iput(inode); iput(inode);
return 0; return 0;
} }
int sys_vhangup(void) int sys_close(unsigned int fd)
{
struct file * filp;
if (fd >= NR_OPEN)
return -EINVAL;
current->close_on_exec &= ~(1<<fd);
if (!(filp = current->filp[fd]))
return -EINVAL;
current->filp[fd] = NULL;
return (close_fp (filp));
}
/* This routine looks through all the process's and closes any
references to the current processes tty. To avoid problems with
process sleeping on an inode which has already been iput, anyprocess
which is sleeping on the tty is sent a sigkill (It's probably a rogue
process.) Also no process should ever have /dev/console as it's
controlling tty, or have it open for reading. So we don't have to
worry about messing with all the daemons abilities to write messages
to the console. (Besides they should be using syslog.) */
int
sys_vhangup(void)
{ {
return -ENOSYS; int i;
int j;
struct file *filep;
struct tty_struct *tty;
extern void kill_wait (struct wait_queue **q, int signal);
extern int kill_pg (int pgrp, int sig, int priv);
if (!suser()) return (-EPERM);
/* send the SIGHUP signal. */
kill_pg (current->pgrp, SIGHUP, 0);
/* See if there is a controlling tty. */
if (current->tty < 0) return (0);
for (i = 0; i < NR_TASKS; i++)
{
if (task[i] == NULL) continue;
for (j = 0; j < NR_OPEN; j++)
{
filep = task[i]->filp[j];
if (filep == NULL) continue;
/* now we need to check to see if this file points to the
device we are trying to close. */
if (!S_ISCHR (filep->f_inode->i_mode)) continue;
/* This will catch both /dev/tty and the explicit terminal
device. However, we must make sure that f_rdev is
defined and correct. */
if ((MAJOR(filep->f_inode->i_rdev) == 5 ||
MAJOR(filep->f_inode->i_rdev) == 4 ) &&
(MAJOR(filep->f_rdev) == 4 &&
MINOR(filep->f_rdev) == MINOR (current->tty)))
{
task[i]->filp[j] = NULL;
/* so now we have found something to close. We
need to kill every process waiting on the
inode. */
kill_wait (&filep->f_inode->i_wait, SIGKILL);
/* now make sure they are awake before we close the
file. */
wake_up (&filep->f_inode->i_wait);
/* finally close the file. */
current->close_on_exec &= ~(1<<j);
close_fp (filep);
}
}
/* can't let them keep a reference to it around.
But we can't touch current->tty until after the
loop is complete. */
if (task[i]->tty == current->tty && task[i] != current)
{
task[i]->tty = -1;
}
}
/* need to do tty->session = 0 */
tty = TTY_TABLE(MINOR(current->tty));
tty->session = 0;
tty->pgrp = -1;
current->tty = -1;
return (0);
} }
#ifndef _CONFIG_DIST_H #ifndef _LINUX_CONFIG_DIST_H
#define _CONFIG_DIST_H #define _LINUX_CONFIG_DIST_H
#ifdef CONFIG_DISTRIBUTION #ifdef CONFIG_DISTRIBUTION
#undef CONFG_SCSI #undef CONFG_SCSI
......
#ifndef _CONFIG_H #ifndef _LINUX_CONFIG_H
#define _CONFIG_H #define _LINUX_CONFIG_H
#define CONFIG_DISTRIBUTION #define CONFIG_DISTRIBUTION
......
#ifndef _CONFIG_SITE_H #ifndef _LINUX_CONFIG_SITE_H
#define _CONFIG_SITE_H #define _LINUX_CONFIG_SITE_H
/* /*
This configuration file contains site specific things, things This configuration file contains site specific things, things
......
#ifndef _CTYPE_H #ifndef _LINUX_CTYPE_H
#define _CTYPE_H #define _LINUX_CTYPE_H
#define _U 0x01 /* upper */ #define _U 0x01 /* upper */
#define _L 0x02 /* lower */ #define _L 0x02 /* lower */
......
#ifndef _EXT_FS_H #ifndef _LINUX_EXT_FS_H
#define _EXT_FS_H #define _LINUX_EXT_FS_H
/* /*
* The ext filesystem constants/structures * The ext filesystem constants/structures
*/ */
/*
* Free blocks/inodes management style
*
* One of these two constants must be defined
*
*/
/* #define EXTFS_BITMAP */ /* use a bitmap */
#define EXTFS_FREELIST /* use a linked list */
#define EXT_NAME_LEN 255 #define EXT_NAME_LEN 255
#define EXT_ROOT_INO 1 #define EXT_ROOT_INO 1
#define EXT_I_MAP_SLOTS 8
#define EXT_Z_MAP_SLOTS 8
#define EXT_SUPER_MAGIC 0x137D #define EXT_SUPER_MAGIC 0x137D
#define EXT_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct ext_inode))) #define EXT_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct ext_inode)))
/* #define EXT_DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct ext_dir_entry))) */
struct ext_inode { struct ext_inode {
unsigned short i_mode; unsigned short i_mode;
...@@ -49,16 +37,10 @@ struct ext_free_block { ...@@ -49,16 +37,10 @@ struct ext_free_block {
struct ext_super_block { struct ext_super_block {
unsigned long s_ninodes; unsigned long s_ninodes;
unsigned long s_nzones; unsigned long s_nzones;
#ifdef EXTFS_BITMAP
unsigned long s_imap_blocks;
unsigned long s_zmap_blocks;
#endif
#ifdef EXTFS_FREELIST
unsigned long s_firstfreeblock; unsigned long s_firstfreeblock;
unsigned long s_freeblockscount; unsigned long s_freeblockscount;
unsigned long s_firstfreeinode; unsigned long s_firstfreeinode;
unsigned long s_freeinodescount; unsigned long s_freeinodescount;
#endif
unsigned long s_firstdatazone; unsigned long s_firstdatazone;
unsigned long s_log_zone_size; unsigned long s_log_zone_size;
unsigned long s_max_size; unsigned long s_max_size;
......
...@@ -2,18 +2,20 @@ ...@@ -2,18 +2,20 @@
#define _EXT_FS_SB #define _EXT_FS_SB
/* /*
* extended-fs super-block data in memory (same as minix: has to change) * extended-fs super-block data in memory
*/ */
struct ext_sb_info { struct ext_sb_info {
unsigned long s_ninodes; unsigned long s_ninodes;
unsigned long s_nzones; unsigned long s_nzones;
unsigned long s_imap_blocks;
unsigned long s_zmap_blocks;
unsigned long s_firstdatazone; unsigned long s_firstdatazone;
unsigned long s_log_zone_size; unsigned long s_log_zone_size;
unsigned long s_max_size; unsigned long s_max_size;
struct buffer_head * s_imap[8]; unsigned long s_firstfreeblocknumber;
struct buffer_head * s_zmap[8]; unsigned long s_freeblockscount;
struct buffer_head * s_firstfreeblock;
unsigned long s_firstfreeinodenumber;
unsigned long s_freeinodescount;
struct buffer_head * s_firstfreeinodeblock;
}; };
#endif #endif
#ifndef _FCNTL_H #ifndef _LINUX_FCNTL_H
#define _FCNTL_H #define _LINUX_FCNTL_H
/* open/fcntl - O_SYNC isn't implemented yet */ /* open/fcntl - O_SYNC isn't implemented yet */
#define O_ACCMODE 0003 #define O_ACCMODE 0003
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#define F_SETLK 6 #define F_SETLK 6
#define F_SETLKW 7 #define F_SETLKW 7
#define F_SETOWN 8 /* for sockets. */
#define F_GETOWN 9 /* for sockets. */
/* for F_[GET|SET]FL */ /* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */
......
...@@ -225,7 +225,7 @@ extern struct file file_table[NR_FILE]; ...@@ -225,7 +225,7 @@ extern struct file file_table[NR_FILE];
extern struct super_block super_block[NR_SUPER]; extern struct super_block super_block[NR_SUPER];
extern void grow_buffers(int size); extern void grow_buffers(int size);
extern int shrink_buffers(void); extern int shrink_buffers(unsigned int priority);
extern int nr_buffers; extern int nr_buffers;
extern int nr_buffer_heads; extern int nr_buffer_heads;
......
#ifndef _GENHD_H #ifndef _LINUX_GENHD_H
#define _GENHD_H #define _LINUX_GENHD_H
/* /*
* genhd.h Copyright (C) 1992 Drew Eckhardt * genhd.h Copyright (C) 1992 Drew Eckhardt
......
...@@ -7,14 +7,14 @@ ...@@ -7,14 +7,14 @@
#define NR_INODE 128 #define NR_INODE 128
#define NR_FILE 128 #define NR_FILE 128
#define NR_SUPER 8 #define NR_SUPER 8
#define NR_HASH 307 #define NR_HASH 997
#define BLOCK_SIZE 1024 #define BLOCK_SIZE 1024
#define BLOCK_SIZE_BITS 10 #define BLOCK_SIZE_BITS 10
#define MAX_CHRDEV 16 #define MAX_CHRDEV 16
#define MAX_BLKDEV 16 #define MAX_BLKDEV 16
#define NGROUPS_MAX 32 /* supplemental group IDs are available */ #define NGROUPS_MAX 32 /* supplemental group IDs are available */
#define ARG_MAX 40960 /* # bytes of args + environ for exec() */ #define ARG_MAX 131072 /* # bytes of args + environ for exec() */
#define CHILD_MAX 999 /* no limit :-) */ #define CHILD_MAX 999 /* no limit :-) */
#define OPEN_MAX 32 /* # open files a process may have */ #define OPEN_MAX 32 /* # open files a process may have */
#define LINK_MAX 127 /* # links a file may have */ #define LINK_MAX 127 /* # links a file may have */
......
#ifndef _MINIX_FS_H #ifndef _LINUX_MINIX_FS_H
#define _MINIX_FS_H #define _LINUX_MINIX_FS_H
/* /*
* The minix filesystem constants/structures * The minix filesystem constants/structures
......
#ifndef _MM_H #ifndef _LINUX_MM_H
#define _MM_H #define _LINUX_MM_H
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/signal.h>
/* /*
* BAD_PAGE is the page that is used for page faults when linux * BAD_PAGE is the page that is used for page faults when linux
......
#ifndef _MSDOS_FS_H #ifndef _LINUX_MSDOS_FS_H
#define _MSDOS_FS_H #define _LINUX_MSDOS_FS_H
/* /*
* The MS-DOS filesystem constants/structures * The MS-DOS filesystem constants/structures
......
#ifndef _SYS_PARAM_H #ifndef _LINUX_PARAM_H
#define _SYS_PARAM_H #define _LINUX_PARAM_H
#ifndef HZ
#define HZ 100 #define HZ 100
#define EXEC_PAGESIZE 4096 #endif
#define EXEC_PAGESIZE 4096
#define NGROUPS 32 /* Max number of groups per user */ #ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP
#define NOGROUP -1 #define NOGROUP -1
#endif
#define MAXHOSTNAMELEN 8 #define MAXHOSTNAMELEN 64 /* max length of hostname */
#endif #endif
...@@ -221,6 +221,7 @@ extern struct task_struct *current; ...@@ -221,6 +221,7 @@ extern struct task_struct *current;
extern unsigned long volatile jiffies; extern unsigned long volatile jiffies;
extern unsigned long startup_time; extern unsigned long startup_time;
extern int jiffies_offset; extern int jiffies_offset;
extern int need_resched;
#define CURRENT_TIME (startup_time+(jiffies+jiffies_offset)/HZ) #define CURRENT_TIME (startup_time+(jiffies+jiffies_offset)/HZ)
......
...@@ -35,12 +35,13 @@ typedef unsigned int sigset_t; /* 32 bits */ ...@@ -35,12 +35,13 @@ typedef unsigned int sigset_t; /* 32 bits */
* so they are commented out. * so they are commented out.
*/ */
/*
#define SIGIO 23 #define SIGIO 23
#define SIGPOLL SIGIO #define SIGPOLL SIGIO
#define SIGURG SIGIO
#define SIGXCPU 24 #define SIGXCPU 24
#define SIGXFSZ 25 #define SIGXFSZ 25
*/
#define SIGVTALRM 26 #define SIGVTALRM 26
#define SIGPROF 27 #define SIGPROF 27
...@@ -60,12 +61,15 @@ typedef unsigned int sigset_t; /* 32 bits */ ...@@ -60,12 +61,15 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIG_UNBLOCK 1 /* for unblocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */
#define SIG_SETMASK 2 /* for setting the signal mask */ #define SIG_SETMASK 2 /* for setting the signal mask */
#define SIG_DFL ((void (*)(int))0) /* default signal handling */ /* Type of a signal handler. */
#define SIG_IGN ((void (*)(int))1) /* ignore signal */ typedef void (*__sighandler_t)(int);
#define SIG_ERR ((void (*)(int))-1) /* error return from signal */
#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
struct sigaction { struct sigaction {
void (*sa_handler)(int); __sighandler_t sa_handler;
sigset_t sa_mask; sigset_t sa_mask;
int sa_flags; int sa_flags;
void (*sa_restorer)(void); void (*sa_restorer)(void);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#define _LINUX_SOCKET_H #define _LINUX_SOCKET_H
struct sockaddr { struct sockaddr {
u_short sa_family; /* address family, AF_xxx */ unsigned short sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */ char sa_data[14]; /* 14 bytes of protocol address */
}; };
...@@ -11,8 +11,9 @@ struct sockaddr { ...@@ -11,8 +11,9 @@ struct sockaddr {
*/ */
#define SOCK_STREAM 1 /* stream (connection) socket */ #define SOCK_STREAM 1 /* stream (connection) socket */
#define SOCK_DGRAM 2 /* datagram (connectionless) socket */ #define SOCK_DGRAM 2 /* datagram (connectionless) socket */
#define SOCK_SEQPACKET 3 /* sequential packet socket */ #define SOCK_RAW 3 /* raw socket */
#define SOCK_RAW 4 /* raw socket */ #define SOCK_RDM 4 /* reliably-delivered message */
#define SOCK_SEQPACKET 5 /* sequential packet socket */
/* /*
* supported address families * supported address families
...@@ -27,4 +28,22 @@ struct sockaddr { ...@@ -27,4 +28,22 @@ struct sockaddr {
#define PF_UNIX AF_UNIX #define PF_UNIX AF_UNIX
#define PF_INET AF_INET #define PF_INET AF_INET
#endif /* flags we can use with send/ and recv. */
#define MSG_OOB 1
#define MSG_PEEK 2
/* for setsockoptions */
#define SO_DEBUG 1
#define SO_REUSEADDR 2
#define SO_TYPE 3
#define SO_ERROR 4
#define SO_DONTROUTE 5
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
#define SO_KEEPALIVE 9
/* setsockoptions level */
#define SOL_SOCKET 1
#endif /* _LINUX_SOCKET_H */
#ifndef _LINUX_STAT_H #ifndef _LINUX_STAT_H
#define _LINUX_STAT_H #define _LINUX_STAT_H
#ifndef __NOT_KERNEL
struct old_stat { struct old_stat {
unsigned short st_dev; unsigned short st_dev;
unsigned short st_ino; unsigned short st_ino;
...@@ -38,6 +40,8 @@ struct new_stat { ...@@ -38,6 +40,8 @@ struct new_stat {
unsigned long __unused5; unsigned long __unused5;
}; };
#endif
#define S_IFMT 00170000 #define S_IFMT 00170000
#define S_IFSOCK 0140000 #define S_IFSOCK 0140000
#define S_IFLNK 0120000 #define S_IFLNK 0120000
......
...@@ -114,6 +114,7 @@ extern int sys_newfstat(); ...@@ -114,6 +114,7 @@ extern int sys_newfstat();
extern int sys_newuname(); extern int sys_newuname();
extern int sys_iopl(); extern int sys_iopl();
extern int sys_vhangup(); extern int sys_vhangup();
extern int sys_idle();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read, fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link, sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
...@@ -135,7 +136,8 @@ sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap, ...@@ -135,7 +136,8 @@ sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap,
sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority, sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority,
sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm, sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm,
sys_socketcall, sys_syslog, sys_setitimer, sys_getitimer, sys_newstat, sys_socketcall, sys_syslog, sys_setitimer, sys_getitimer, sys_newstat,
sys_newlstat, sys_newfstat, sys_newuname, sys_iopl, sys_vhangup }; sys_newlstat, sys_newfstat, sys_newuname, sys_iopl, sys_vhangup,
sys_idle };
/* So we don't have to do any more manual updating.... */ /* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr); int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* FLOPPY_TIMER floppy disk timer (not used right now) * FLOPPY_TIMER floppy disk timer (not used right now)
* *
* SCSI_TIMER scsi.c timeout timer * SCSI_TIMER scsi.c timeout timer
*
* NET_TIMER tcp/ip timeout timer
*/ */
#define BLANK_TIMER 0 #define BLANK_TIMER 0
...@@ -40,6 +42,7 @@ ...@@ -40,6 +42,7 @@
#define HD_TIMER 16 #define HD_TIMER 16
#define FLOPPY_TIMER 17 #define FLOPPY_TIMER 17
#define SCSI_TIMER 18 #define SCSI_TIMER 18
#define NET_TIMER 19
struct timer_struct { struct timer_struct {
unsigned long expires; unsigned long expires;
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
#define _LINUX_TIMES_H #define _LINUX_TIMES_H
struct tms { struct tms {
time_t tms_utime; clock_t tms_utime;
time_t tms_stime; clock_t tms_stime;
time_t tms_cutime; clock_t tms_cutime;
time_t tms_cstime; clock_t tms_cstime;
}; };
#endif #endif
...@@ -146,7 +146,9 @@ struct tty_struct { ...@@ -146,7 +146,9 @@ struct tty_struct {
struct termios termios; struct termios termios;
int pgrp; int pgrp;
int session; int session;
int stopped; unsigned char stopped:1, status_changed:1, packet:1;
unsigned char ctrl_status;
short unused; /* make everything a multiple of 4. */
int flags; int flags;
int count; int count;
struct winsize winsize; struct winsize winsize;
......
...@@ -23,7 +23,7 @@ typedef long clock_t; ...@@ -23,7 +23,7 @@ typedef long clock_t;
#ifndef _PTRDIFF_T #ifndef _PTRDIFF_T
#define _PTRDIFF_T #define _PTRDIFF_T
typedef long ptrdiff_t; typedef int ptrdiff_t;
#endif #endif
#ifndef NULL #ifndef NULL
...@@ -65,9 +65,6 @@ typedef unsigned long tcflag_t; ...@@ -65,9 +65,6 @@ typedef unsigned long tcflag_t;
typedef unsigned long fd_set; typedef unsigned long fd_set;
typedef struct { int quot,rem; } div_t;
typedef struct { long quot,rem; } ldiv_t;
struct ustat { struct ustat {
daddr_t f_tfree; daddr_t f_tfree;
ino_t f_tinode; ino_t f_tinode;
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
#define _LINUX_UN_H #define _LINUX_UN_H
struct sockaddr_un { struct sockaddr_un {
u_short sun_family; /* AF_UNIX */ unsigned short sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */ char sun_path[108]; /* pathname */
}; };
#endif /* _UN_H */ #endif /* _LINUX_UN_H */
...@@ -117,6 +117,8 @@ ...@@ -117,6 +117,8 @@
#define __NR_fstat 108 #define __NR_fstat 108
#define __NR_uname 109 #define __NR_uname 109
#define __NR_iopl 110 #define __NR_iopl 110
#define __NR_vhangup 111
#define __NR_idle 112
extern int errno; extern int errno;
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
#include <linux/head.h> #include <linux/head.h>
#include <linux/unistd.h> #include <linux/unistd.h>
extern unsigned long * prof_buffer;
extern unsigned long prof_len;
extern int end;
/* /*
* we need this inline - forking from kernel space will result * we need this inline - forking from kernel space will result
* in NO COPY ON WRITE (!!!), until an execve is executed. This * in NO COPY ON WRITE (!!!), until an execve is executed. This
...@@ -30,6 +34,7 @@ ...@@ -30,6 +34,7 @@
* won't be any messing with the stack from main(), but we define * won't be any messing with the stack from main(), but we define
* some others too. * some others too.
*/ */
static inline _syscall0(int,idle)
static inline _syscall0(int,fork) static inline _syscall0(int,fork)
static inline _syscall0(int,pause) static inline _syscall0(int,pause)
static inline _syscall1(int,setup,void *,BIOS) static inline _syscall1(int,setup,void *,BIOS)
...@@ -54,7 +59,6 @@ extern void init(void); ...@@ -54,7 +59,6 @@ extern void init(void);
extern void init_IRQ(void); extern void init_IRQ(void);
extern long blk_dev_init(long,long); extern long blk_dev_init(long,long);
extern long chr_dev_init(long,long); extern long chr_dev_init(long,long);
extern void hd_init(void);
extern void floppy_init(void); extern void floppy_init(void);
extern void sock_init(void); extern void sock_init(void);
extern long rd_init(long mem_start, int length); extern long rd_init(long mem_start, int length);
...@@ -157,23 +161,28 @@ void start_kernel(void) ...@@ -157,23 +161,28 @@ void start_kernel(void)
trap_init(); trap_init();
init_IRQ(); init_IRQ();
sched_init(); sched_init();
#ifdef PROFILE_SHIFT
prof_buffer = (unsigned long *) memory_start;
prof_len = (unsigned long) &end;
prof_len >>= PROFILE_SHIFT;
memory_start += prof_len * sizeof(unsigned long);
#endif
memory_start = chr_dev_init(memory_start,memory_end); memory_start = chr_dev_init(memory_start,memory_end);
memory_start = blk_dev_init(memory_start,memory_end); memory_start = blk_dev_init(memory_start,memory_end);
memory_start = mem_init(memory_start,memory_end); memory_start = mem_init(memory_start,memory_end);
buffer_init(); buffer_init();
time_init(); time_init();
printk("Linux version " UTS_RELEASE " " __DATE__ " " __TIME__ "\n"); printk("Linux version " UTS_RELEASE " " __DATE__ " " __TIME__ "\n");
hd_init();
floppy_init(); floppy_init();
sock_init(); sock_init();
sti(); sti();
#ifdef CONFIG_SCSI #ifdef CONFIG_SCSI
scsi_dev_init(); scsi_dev_init();
#endif #endif
sti();
move_to_user_mode(); move_to_user_mode();
if (!fork()) { /* we count on this going ok */ if (!fork()) /* we count on this going ok */
init(); init();
}
/* /*
* task[0] is meant to be used as an "idle" task: it may not sleep, but * task[0] is meant to be used as an "idle" task: it may not sleep, but
* it might do some general things like count free pages or it could be * it might do some general things like count free pages or it could be
...@@ -181,10 +190,10 @@ void start_kernel(void) ...@@ -181,10 +190,10 @@ void start_kernel(void)
* anything that can be useful, but shouldn't take time from the real * anything that can be useful, but shouldn't take time from the real
* processes. * processes.
* *
* Right now task[0] just does a infinite loop in user mode. * Right now task[0] just does a infinite idle loop.
*/ */
for(;;) for(;;)
/* nothing */ ; idle();
} }
static int printf(const char *fmt, ...) static int printf(const char *fmt, ...)
......
...@@ -593,7 +593,7 @@ static struct sigaction hd_sigaction = { ...@@ -593,7 +593,7 @@ static struct sigaction hd_sigaction = {
NULL NULL
}; };
void hd_init(void) unsigned long hd_init(unsigned long mem_start)
{ {
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blkdev_fops[MAJOR_NR] = &hd_fops; blkdev_fops[MAJOR_NR] = &hd_fops;
...@@ -602,6 +602,7 @@ void hd_init(void) ...@@ -602,6 +602,7 @@ void hd_init(void)
if (irqaction(HD_IRQ,&hd_sigaction)) if (irqaction(HD_IRQ,&hd_sigaction))
printk("Unable to get IRQ%d for the harddisk driver\n",HD_IRQ); printk("Unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
timer_table[HD_TIMER].fn = hd_times_out; timer_table[HD_TIMER].fn = hd_times_out;
return mem_start;
} }
#endif #endif
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/config.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -299,6 +300,9 @@ long blk_dev_init(long mem_start, long mem_end) ...@@ -299,6 +300,9 @@ long blk_dev_init(long mem_start, long mem_end)
request[i].next = NULL; request[i].next = NULL;
} }
memset(ro_bits,0,sizeof(ro_bits)); memset(ro_bits,0,sizeof(ro_bits));
#ifdef CONFIG_BLK_DEV_HD
mem_start = hd_init(mem_start,mem_end);
#endif
#ifdef RAMDISK #ifdef RAMDISK
mem_start += rd_init(mem_start, RAMDISK*1024); mem_start += rd_init(mem_start, RAMDISK*1024);
#endif #endif
......
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
#include <linux/config.h> #include <linux/config.h>
#ifdef RAMDISK #ifdef RAMDISK
#include <linux/string.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/minix_fs.h> #include <linux/minix_fs.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/memory.h> #include <asm/memory.h>
......
...@@ -929,13 +929,13 @@ void con_write(struct tty_struct * tty) ...@@ -929,13 +929,13 @@ void con_write(struct tty_struct * tty)
* Control characters can be used in the _middle_ * Control characters can be used in the _middle_
* of an escape sequence. * of an escape sequence.
*/ */
if (c < 32 || c == 127) switch(c) { switch (c) {
case 7: case 7:
sysbeep(); sysbeep();
break; continue;
case 8: case 8:
bs(currcons); bs(currcons);
break; continue;
case 9: case 9:
pos -= (x << 1); pos -= (x << 1);
while (x < video_num_columns - 1) { while (x < video_num_columns - 1) {
...@@ -944,80 +944,84 @@ void con_write(struct tty_struct * tty) ...@@ -944,80 +944,84 @@ void con_write(struct tty_struct * tty)
break; break;
} }
pos += (x << 1); pos += (x << 1);
break; continue;
case 10: case 11: case 12: case 10: case 11: case 12:
lf(currcons); lf(currcons);
if (!lfnlmode) if (!lfnlmode)
break; continue;
case 13: case 13:
cr(currcons); cr(currcons);
break; continue;
case 14: case 14:
charset = 1; charset = 1;
translate = G1_charset; translate = G1_charset;
break; continue;
case 15: case 15:
charset = 0; charset = 0;
translate = G0_charset; translate = G0_charset;
break; continue;
case 24: case 26: case 24: case 26:
state = ESnormal; state = ESnormal;
break; continue;
case 27: case 27:
state = ESesc; state = ESesc;
break; continue;
case 127: case 127:
del(currcons); del(currcons);
break; continue;
} else switch(state) { case 128+27:
state = ESsquare;
continue;
}
switch(state) {
case ESesc: case ESesc:
state = ESnormal; state = ESnormal;
switch (c) { switch (c) {
case '[': case '[':
state = ESsquare; state = ESsquare;
break; continue;
case 'E': case 'E':
cr(currcons); cr(currcons);
lf(currcons); lf(currcons);
break; continue;
case 'M': case 'M':
ri(currcons); ri(currcons);
break; continue;
case 'D': case 'D':
lf(currcons); lf(currcons);
break; continue;
case 'H': case 'H':
tab_stop[x >> 5] |= (1 << (x & 31)); tab_stop[x >> 5] |= (1 << (x & 31));
break; continue;
case 'Z': case 'Z':
respond_ID(currcons,tty); respond_ID(currcons,tty);
break; continue;
case '7': case '7':
save_cur(currcons); save_cur(currcons);
break; continue;
case '8': case '8':
restore_cur(currcons); restore_cur(currcons);
break; continue;
case '(': case '(':
state = ESsetG0; state = ESsetG0;
break; continue;
case ')': case ')':
state = ESsetG1; state = ESsetG1;
break; continue;
case '#': case '#':
state = EShash; state = EShash;
break; continue;
case 'c': case 'c':
reset_terminal(currcons,1); reset_terminal(currcons,1);
break; continue;
case '>': /* Numeric keypad */ case '>': /* Numeric keypad */
SET(kbdapplic,kapplic,0); SET(kbdapplic,kapplic,0);
break; continue;
case '=': /* Appl. keypad */ case '=': /* Appl. keypad */
SET(kbdapplic,kapplic,1); SET(kbdapplic,kapplic,1);
break; continue;
} }
break; continue;
case ESsquare: case ESsquare:
for(npar = 0 ; npar < NPAR ; npar++) for(npar = 0 ; npar < NPAR ; npar++)
par[npar] = 0; par[npar] = 0;
...@@ -1025,97 +1029,97 @@ void con_write(struct tty_struct * tty) ...@@ -1025,97 +1029,97 @@ void con_write(struct tty_struct * tty)
state = ESgetpars; state = ESgetpars;
if (c == '[') { /* Function key */ if (c == '[') { /* Function key */
state=ESfunckey; state=ESfunckey;
break; continue;
} }
if (ques=(c=='?')) if (ques=(c=='?'))
break; continue;
case ESgetpars: case ESgetpars:
if (c==';' && npar<NPAR-1) { if (c==';' && npar<NPAR-1) {
npar++; npar++;
break; continue;
} else if (c>='0' && c<='9') { } else if (c>='0' && c<='9') {
par[npar] *= 10; par[npar] *= 10;
par[npar] += c-'0'; par[npar] += c-'0';
break; continue;
} else state=ESgotpars; } else state=ESgotpars;
case ESgotpars: case ESgotpars:
state = ESnormal; state = ESnormal;
switch(c) { switch(c) {
case 'h': case 'h':
set_mode(currcons,1); set_mode(currcons,1);
break; continue;
case 'l': case 'l':
set_mode(currcons,0); set_mode(currcons,0);
break; continue;
case 'n': case 'n':
if (!ques) if (!ques)
if (par[0] == 5) if (par[0] == 5)
status_report(currcons,tty); status_report(currcons,tty);
else if (par[0] == 6) else if (par[0] == 6)
cursor_report(currcons,tty); cursor_report(currcons,tty);
break; continue;
} }
if (ques) { if (ques) {
ques = 0; ques = 0;
break; continue;
} }
switch(c) { switch(c) {
case 'G': case '`': case 'G': case '`':
if (par[0]) par[0]--; if (par[0]) par[0]--;
gotoxy(currcons,par[0],y); gotoxy(currcons,par[0],y);
break; continue;
case 'A': case 'A':
if (!par[0]) par[0]++; if (!par[0]) par[0]++;
gotoxy(currcons,x,y-par[0]); gotoxy(currcons,x,y-par[0]);
break; continue;
case 'B': case 'e': case 'B': case 'e':
if (!par[0]) par[0]++; if (!par[0]) par[0]++;
gotoxy(currcons,x,y+par[0]); gotoxy(currcons,x,y+par[0]);
break; continue;
case 'C': case 'a': case 'C': case 'a':
if (!par[0]) par[0]++; if (!par[0]) par[0]++;
gotoxy(currcons,x+par[0],y); gotoxy(currcons,x+par[0],y);
break; continue;
case 'D': case 'D':
if (!par[0]) par[0]++; if (!par[0]) par[0]++;
gotoxy(currcons,x-par[0],y); gotoxy(currcons,x-par[0],y);
break; continue;
case 'E': case 'E':
if (!par[0]) par[0]++; if (!par[0]) par[0]++;
gotoxy(currcons,0,y+par[0]); gotoxy(currcons,0,y+par[0]);
break; continue;
case 'F': case 'F':
if (!par[0]) par[0]++; if (!par[0]) par[0]++;
gotoxy(currcons,0,y-par[0]); gotoxy(currcons,0,y-par[0]);
break; continue;
case 'd': case 'd':
if (par[0]) par[0]--; if (par[0]) par[0]--;
gotoxy(currcons,x,par[0]); gotoxy(currcons,x,par[0]);
break; continue;
case 'H': case 'f': case 'H': case 'f':
if (par[0]) par[0]--; if (par[0]) par[0]--;
if (par[1]) par[1]--; if (par[1]) par[1]--;
gotoxy(currcons,par[1],par[0]); gotoxy(currcons,par[1],par[0]);
break; continue;
case 'J': case 'J':
csi_J(currcons,par[0]); csi_J(currcons,par[0]);
break; continue;
case 'K': case 'K':
csi_K(currcons,par[0]); csi_K(currcons,par[0]);
break; continue;
case 'L': case 'L':
csi_L(currcons,par[0]); csi_L(currcons,par[0]);
break; continue;
case 'M': case 'M':
csi_M(currcons,par[0]); csi_M(currcons,par[0]);
break; continue;
case 'P': case 'P':
csi_P(currcons,par[0]); csi_P(currcons,par[0]);
break; continue;
case 'c': case 'c':
if (!par[0]) if (!par[0])
respond_ID(currcons,tty); respond_ID(currcons,tty);
break; continue;
case 'g': case 'g':
if (!par[0]) if (!par[0])
tab_stop[x >> 5] &= ~(1 << (x & 31)); tab_stop[x >> 5] &= ~(1 << (x & 31));
...@@ -1126,10 +1130,10 @@ void con_write(struct tty_struct * tty) ...@@ -1126,10 +1130,10 @@ void con_write(struct tty_struct * tty)
tab_stop[3] = tab_stop[3] =
tab_stop[4] = 0; tab_stop[4] = 0;
} }
break; continue;
case 'm': case 'm':
csi_m(currcons); csi_m(currcons);
break; continue;
case 'r': case 'r':
if (!par[0]) if (!par[0])
par[0]++; par[0]++;
...@@ -1142,24 +1146,24 @@ void con_write(struct tty_struct * tty) ...@@ -1142,24 +1146,24 @@ void con_write(struct tty_struct * tty)
bottom=par[1]; bottom=par[1];
gotoxy(currcons,0,0); gotoxy(currcons,0,0);
} }
break; continue;
case 's': case 's':
save_cur(currcons); save_cur(currcons);
break; continue;
case 'u': case 'u':
restore_cur(currcons); restore_cur(currcons);
break; continue;
case '@': case '@':
csi_at(currcons,par[0]); csi_at(currcons,par[0]);
break; continue;
case ']': /* setterm functions */ case ']': /* setterm functions */
setterm_command(currcons); setterm_command(currcons);
break; continue;
} }
break; continue;
case ESfunckey: case ESfunckey:
state = ESnormal; state = ESnormal;
break; continue;
case EShash: case EShash:
state = ESnormal; state = ESnormal;
if (c == '8') { if (c == '8') {
...@@ -1170,7 +1174,7 @@ void con_write(struct tty_struct * tty) ...@@ -1170,7 +1174,7 @@ void con_write(struct tty_struct * tty)
video_erase_char = video_erase_char =
(video_erase_char & 0xff00) | ' '; (video_erase_char & 0xff00) | ' ';
} }
break; continue;
case ESsetG0: case ESsetG0:
if (c == '0') if (c == '0')
G0_charset = GRAF_TRANS; G0_charset = GRAF_TRANS;
...@@ -1181,7 +1185,7 @@ void con_write(struct tty_struct * tty) ...@@ -1181,7 +1185,7 @@ void con_write(struct tty_struct * tty)
if (charset == 0) if (charset == 0)
translate = G0_charset; translate = G0_charset;
state = ESnormal; state = ESnormal;
break; continue;
case ESsetG1: case ESsetG1:
if (c == '0') if (c == '0')
G1_charset = GRAF_TRANS; G1_charset = GRAF_TRANS;
...@@ -1192,7 +1196,7 @@ void con_write(struct tty_struct * tty) ...@@ -1192,7 +1196,7 @@ void con_write(struct tty_struct * tty)
if (charset == 1) if (charset == 1)
translate = G1_charset; translate = G1_charset;
state = ESnormal; state = ESnormal;
break; continue;
default: default:
state = ESnormal; state = ESnormal;
} }
......
...@@ -83,14 +83,12 @@ static int open_mouse(struct inode * inode, struct file * file) ...@@ -83,14 +83,12 @@ static int open_mouse(struct inode * inode, struct file * file)
mouse.dx = 0; mouse.dx = 0;
mouse.dy = 0; mouse.dy = 0;
mouse.buttons = mouse.latch_buttons = 0x80; mouse.buttons = mouse.latch_buttons = 0x80;
MSE_INT_ON();
if (request_irq(MOUSE_IRQ, mouse_interrupt)) { if (request_irq(MOUSE_IRQ, mouse_interrupt)) {
MSE_INT_OFF(); /* once we get to here mouse is unused, IRQ is busy */
mouse.active = 0; mouse.active = 0; /* it's not active, fix it */
mouse.ready = 0; return -EBUSY; /* IRQ is busy, so we're BUSY */
mouse.inode = NULL; } /* if we can't get the IRQ and mouse not active */
return -EBUSY; MSE_INT_ON();
}
return 0; return 0;
} }
......
...@@ -201,11 +201,15 @@ void copy_to_cooked(struct tty_struct * tty) ...@@ -201,11 +201,15 @@ void copy_to_cooked(struct tty_struct * tty)
if (I_IXON(tty)) { if (I_IXON(tty)) {
if ((STOP_CHAR(tty) != __DISABLED_CHAR) && if ((STOP_CHAR(tty) != __DISABLED_CHAR) &&
(c==STOP_CHAR(tty))) { (c==STOP_CHAR(tty))) {
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_STOP;
tty->stopped=1; tty->stopped=1;
continue; continue;
} }
if ((START_CHAR(tty) != __DISABLED_CHAR) && if ((START_CHAR(tty) != __DISABLED_CHAR) &&
(c==START_CHAR(tty))) { (c==START_CHAR(tty))) {
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_START;
tty->stopped=0; tty->stopped=0;
continue; continue;
} }
...@@ -338,10 +342,32 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n ...@@ -338,10 +342,32 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n
} }
if (file->f_flags & O_NONBLOCK) if (file->f_flags & O_NONBLOCK)
time = current->timeout = 0; time = current->timeout = 0;
else if (L_CANON(tty)) else if (L_CANON(tty)) {
wait_for_canon_input(tty); wait_for_canon_input(tty);
if (current->signal & ~current->blocked)
return -ERESTARTSYS;
}
if (minimum>nr) if (minimum>nr)
minimum = nr; minimum = nr;
/* deal with packet mode: First test for status change */
if (tty->packet && tty->link && tty->link->status_changed)
{
put_fs_byte (tty->link->ctrl_status, b);
tty->link->status_changed = 0;
return (1);
}
/* now bump the buffer up one. */
if (tty->packet)
{
put_fs_byte (0,b++);
nr --;
/* this really shouldn't happen, but we need to
put it here. */
if (nr == 0) return (1);
}
while (nr>0) { while (nr>0) {
TTY_READ_FLUSH(tty); TTY_READ_FLUSH(tty);
if (tty->link) if (tty->link)
...@@ -379,8 +405,20 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n ...@@ -379,8 +405,20 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n
if (tty->link && tty->link->write) if (tty->link && tty->link->write)
TTY_WRITE_FLUSH(tty->link); TTY_WRITE_FLUSH(tty->link);
current->timeout = 0; current->timeout = 0;
if (b-buf)
return b-buf; /* packet mode sticks in an extra 0. If that's all we've got,
we should count it a zero bytes. */
if (tty->packet)
{
if ((b-buf) > 1)
return b-buf;
}
else
{
if (b-buf)
return b-buf;
}
if (current->signal & ~current->blocked) if (current->signal & ~current->blocked)
return -ERESTARTSYS; return -ERESTARTSYS;
if (file->f_flags & O_NONBLOCK) if (file->f_flags & O_NONBLOCK)
...@@ -523,9 +561,20 @@ static int tty_open(struct inode * inode, struct file * filp) ...@@ -523,9 +561,20 @@ static int tty_open(struct inode * inode, struct file * filp)
return -EAGAIN; return -EAGAIN;
if (tty->link) if (tty->link)
tty->link->count++; tty->link->count++;
/* perhaps user applications that don't take care of
this deserve what the get, but I think my system
has hung do to this, esp. in X. -RAB */
tty->termios.c_lflag &= ~ECHO;
} }
tty->count++; tty->count++;
retval = 0; retval = 0;
/* clean up the packet stuff. */
tty->status_changed = 0;
tty->ctrl_status = 0;
tty->packet = 0;
if (!(filp->f_flags & O_NOCTTY) && if (!(filp->f_flags & O_NOCTTY) &&
current->leader && current->leader &&
current->tty<0 && current->tty<0 &&
...@@ -598,6 +647,12 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se ...@@ -598,6 +647,12 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se
return 1; return 1;
if (tty->link && !tty->link->count) if (tty->link && !tty->link->count)
return 1; return 1;
/* see if the status byte can be read. */
if (tty->packet && tty->link &&
tty->link->status_changed)
return 1;
select_wait(&tty->secondary->proc_list, wait); select_wait(&tty->secondary->proc_list, wait);
return 0; return 0;
case SEL_OUT: case SEL_OUT:
...@@ -639,7 +694,7 @@ long tty_init(long kmem_start) ...@@ -639,7 +694,7 @@ long tty_init(long kmem_start)
for (i=0 ; i<256 ; i++) { for (i=0 ; i<256 ; i++) {
tty_table[i] = (struct tty_struct) { tty_table[i] = (struct tty_struct) {
{0, 0, 0, 0, 0, INIT_C_CC}, {0, 0, 0, 0, 0, INIT_C_CC},
-1, 0, 0, 0, 0, {0,0,0,0}, -1, 0, 0, 0, 0, 0, 0, 0, 0, {0,0,0,0},
NULL, NULL, NULL, NULL, NULL NULL, NULL, NULL, NULL, NULL
}; };
} }
...@@ -655,6 +710,10 @@ long tty_init(long kmem_start) ...@@ -655,6 +710,10 @@ long tty_init(long kmem_start)
-1, /* initial pgrp */ -1, /* initial pgrp */
0, /* initial session */ 0, /* initial session */
0, /* initial stopped */ 0, /* initial stopped */
0, /* initial status_changed */
0, /* initial packet */
0, /* initial ctrl_status */
0, /* initial unused */
0, /* initial flags */ 0, /* initial flags */
0, /* initial count */ 0, /* initial count */
{video_num_lines,video_num_columns,0,0}, {video_num_lines,video_num_columns,0,0},
...@@ -673,7 +732,7 @@ long tty_init(long kmem_start) ...@@ -673,7 +732,7 @@ long tty_init(long kmem_start)
INIT_C_CC}, INIT_C_CC},
-1, -1,
0, 0,
0, 0, 0, 0, 0, 0,
0, 0,
0, 0,
{25,80,0,0}, {25,80,0,0},
...@@ -692,7 +751,7 @@ long tty_init(long kmem_start) ...@@ -692,7 +751,7 @@ long tty_init(long kmem_start)
INIT_C_CC}, INIT_C_CC},
-1, -1,
0, 0,
0, 0, 0, 0, 0, 0,
0, 0,
0, 0,
{25,80,0,0}, {25,80,0,0},
...@@ -709,7 +768,7 @@ long tty_init(long kmem_start) ...@@ -709,7 +768,7 @@ long tty_init(long kmem_start)
INIT_C_CC}, INIT_C_CC},
-1, -1,
0, 0,
0, 0, 0, 0, 0, 0,
0, 0,
0, 0,
{25,80,0,0}, {25,80,0,0},
......
...@@ -33,6 +33,8 @@ static void flush(struct tty_queue * queue) ...@@ -33,6 +33,8 @@ static void flush(struct tty_queue * queue)
void flush_input(struct tty_struct * tty) void flush_input(struct tty_struct * tty)
{ {
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_FLUSHREAD;
if (tty->read_q) { if (tty->read_q) {
flush(tty->read_q); flush(tty->read_q);
wake_up(&tty->read_q->proc_list); wake_up(&tty->read_q->proc_list);
...@@ -49,6 +51,8 @@ void flush_input(struct tty_struct * tty) ...@@ -49,6 +51,8 @@ void flush_input(struct tty_struct * tty)
void flush_output(struct tty_struct * tty) void flush_output(struct tty_struct * tty)
{ {
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
if (tty->write_q) { if (tty->write_q) {
flush(tty->write_q); flush(tty->write_q);
wake_up(&tty->write_q->proc_list); wake_up(&tty->write_q->proc_list);
...@@ -138,6 +142,12 @@ static int set_termios(struct tty_struct * tty, struct termios * termios, ...@@ -138,6 +142,12 @@ static int set_termios(struct tty_struct * tty, struct termios * termios,
((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios); ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag) if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
change_speed(channel-64); change_speed(channel-64);
/* puting mpty's into echo mode is very bad, and I think under
some situations can cause the kernel to do nothing but
copy characters back and forth. -RAB */
if (IS_A_PTY_MASTER(channel)) tty->termios.c_lflag &= ~ECHO;
return 0; return 0;
} }
...@@ -179,6 +189,22 @@ static int set_termio(struct tty_struct * tty, struct termio * termio, ...@@ -179,6 +189,22 @@ static int set_termio(struct tty_struct * tty, struct termio * termio,
} }
for (i=0 ; i< (sizeof (*termio)) ; i++) for (i=0 ; i< (sizeof (*termio)) ; i++)
((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio); ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
/* take care of the packet stuff. */
if ((tmp_termio.c_iflag & IXON) &&
~(tty->termios.c_iflag & IXON))
{
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_DOSTOP;
}
if (~(tmp_termio.c_iflag & IXON) &&
(tty->termios.c_iflag & IXON))
{
tty->status_changed = 1;
tty->ctrl_status |= TIOCPKT_NOSTOP;
}
*(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag; *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
*(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag; *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
*(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag; *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
...@@ -408,6 +434,21 @@ int tty_ioctl(struct inode * inode, struct file * file, ...@@ -408,6 +434,21 @@ int tty_ioctl(struct inode * inode, struct file * file,
tty->session = 0; tty->session = 0;
} }
return 0; return 0;
case TIOCPKT:
{
int on;
if (!IS_A_PTY_MASTER(dev))
return (-EINVAL);
verify_area ((unsigned long *)arg, sizeof (int));
on=get_fs_long ((unsigned long *)arg);
if (on )
tty->packet = 1;
else
tty->packet = 0;
return (0);
}
default: default:
return vt_ioctl(tty, dev, cmd, arg); return vt_ioctl(tty, dev, cmd, arg);
} }
......
...@@ -203,6 +203,30 @@ int kill_pg(int pgrp, int sig, int priv) ...@@ -203,6 +203,30 @@ int kill_pg(int pgrp, int sig, int priv)
return(found ? 0 : retval); return(found ? 0 : retval);
} }
/* This routine is used by vhangup. It send's sigkill to everything
waiting on a particular wait_queue. It assumes root privledges.
We don't want to destroy the wait queue here, because the caller
should call wake_up immediately after calling kill_wait. */
void
kill_wait (struct wait_queue **q, int sig)
{
struct wait_queue *next;
struct wait_queue *tmp;
struct task_struct *p;
if (!q || !(next = *q))
return;
do {
tmp = next;
next = tmp->next;
if (p = tmp->task)
{
send_sig (sig, p , 1);
}
} while (next && next != *q);
}
int kill_proc(int pid, int sig, int priv) int kill_proc(int pid, int sig, int priv)
{ {
struct task_struct **p; struct task_struct **p;
......
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
int need_resched = 0; int need_resched = 0;
unsigned long * prof_buffer = NULL;
unsigned long prof_len = 0;
#define _S(nr) (1<<((nr)-1)) #define _S(nr) (1<<((nr)-1))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
...@@ -157,12 +160,14 @@ void schedule(void) ...@@ -157,12 +160,14 @@ void schedule(void)
if ((*p)->state == TASK_RUNNING && (*p)->counter > c) if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
c = (*p)->counter, next = i; c = (*p)->counter, next = i;
} }
if (c) break; if (c)
break;
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p) if (*p)
(*p)->counter = ((*p)->counter >> 1) + (*p)->counter = ((*p)->counter >> 1) +
(*p)->priority; (*p)->priority;
} }
sti();
switch_to(next); switch_to(next);
} }
...@@ -396,21 +401,29 @@ static void do_timer(int regs) ...@@ -396,21 +401,29 @@ static void do_timer(int regs)
static int avg_cnt = 0; static int avg_cnt = 0;
jiffies++; jiffies++;
if (3 & ((struct pt_regs *) regs)->cs) if (3 & ((struct pt_regs *) regs)->cs) {
current->utime++; current->utime++;
else {
current->stime++;
/* Update ITIMER_VIRT for current task if not in a system call */ /* Update ITIMER_VIRT for current task if not in a system call */
if (current->it_virt_value && !(--current->it_virt_value)) { if (current->it_virt_value && !(--current->it_virt_value)) {
current->it_virt_value = current->it_virt_incr; current->it_virt_value = current->it_virt_incr;
send_sig(SIGVTALRM,current,1); send_sig(SIGVTALRM,current,1);
} }
} else {
current->stime++;
#ifdef PROFILE_SHIFT
if (prof_buffer && current != task[0]) {
unsigned long eip = ((struct pt_regs *) regs)->eip;
eip >>= PROFILE_SHIFT;
if (eip < prof_len)
prof_buffer[eip]++;
}
#endif
} }
if (--avg_cnt < 0) { if (--avg_cnt < 0) {
avg_cnt = 500; avg_cnt = 500;
update_avg(); update_avg();
} }
if ((--current->counter)<=0) { if (current == task[0] || (--current->counter)<=0) {
current->counter=0; current->counter=0;
need_resched = 1; need_resched = 1;
} }
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
* NOTE: This code handles signal-recognition, which happens every time * NOTE: This code handles signal-recognition, which happens every time
* after a timer-interrupt and after each system call. * after a timer-interrupt and after each system call.
* *
* I changed all the .align's to 4 (16 byte alignment), as that's faster
* on a 486.
*
* Stack layout in 'ret_from_system_call': * Stack layout in 'ret_from_system_call':
* ptrace needs to have all regs on the stack. * ptrace needs to have all regs on the stack.
* if the order here is changed, it needs to be * if the order here is changed, it needs to be
...@@ -75,10 +78,6 @@ sa_restorer = 12 ...@@ -75,10 +78,6 @@ sa_restorer = 12
ENOSYS = 38 ENOSYS = 38
/*
* Ok, I get parallel printer interrupts while using the floppy for some
* strange reason. Urgel. Now I just ignore them.
*/
.globl _system_call,_sys_execve .globl _system_call,_sys_execve
.globl _device_not_available, _coprocessor_error .globl _device_not_available, _coprocessor_error
.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
...@@ -107,11 +106,11 @@ ENOSYS = 38 ...@@ -107,11 +106,11 @@ ENOSYS = 38
movl $0x17,%edx; \ movl $0x17,%edx; \
mov %dx,%fs mov %dx,%fs
.align 2 .align 4
reschedule: reschedule:
pushl $ret_from_sys_call pushl $ret_from_sys_call
jmp _schedule jmp _schedule
.align 2 .align 4
_system_call: _system_call:
pushl %eax # save orig_eax pushl %eax # save orig_eax
SAVE_ALL SAVE_ALL
...@@ -120,6 +119,7 @@ _system_call: ...@@ -120,6 +119,7 @@ _system_call:
jae ret_from_sys_call jae ret_from_sys_call
call _sys_call_table(,%eax,4) call _sys_call_table(,%eax,4)
movl %eax,EAX(%esp) # save the return value movl %eax,EAX(%esp) # save the return value
.align 4,0x90
ret_from_sys_call: ret_from_sys_call:
cmpw $0x0f,CS(%esp) # was old code segment supervisor ? cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
jne 2f jne 2f
...@@ -128,14 +128,12 @@ ret_from_sys_call: ...@@ -128,14 +128,12 @@ ret_from_sys_call:
1: cmpl $0,_need_resched 1: cmpl $0,_need_resched
jne reschedule jne reschedule
movl _current,%eax movl _current,%eax
cmpl _task,%eax # task[0] cannot have signals
je 2f
cmpl $0,state(%eax) # state cmpl $0,state(%eax) # state
jne reschedule jne reschedule
cmpl $0,counter(%eax) # counter cmpl $0,counter(%eax) # counter
je reschedule je reschedule
movl $1,_need_resched
cmpl _task,%eax # task[0] cannot have signals
je 2f
movl $0,_need_resched
movl signal(%eax),%ebx movl signal(%eax),%ebx
movl blocked(%eax),%ecx movl blocked(%eax),%ecx
notl %ecx notl %ecx
...@@ -167,7 +165,7 @@ ret_from_sys_call: ...@@ -167,7 +165,7 @@ ret_from_sys_call:
addl $4,%esp # skip the orig_eax addl $4,%esp # skip the orig_eax
iret iret
.align 2 .align 4
_sys_execve: _sys_execve:
lea (EIP+4)(%esp),%eax # don't forget about the return address. lea (EIP+4)(%esp),%eax # don't forget about the return address.
pushl %eax pushl %eax
...@@ -175,9 +173,11 @@ _sys_execve: ...@@ -175,9 +173,11 @@ _sys_execve:
addl $4,%esp addl $4,%esp
ret ret
.align 4
_divide_error: _divide_error:
pushl $0 # no error code pushl $0 # no error code
pushl $_do_divide_error pushl $_do_divide_error
.align 4,0x90
error_code: error_code:
push %fs push %fs
push %es push %es
...@@ -207,13 +207,13 @@ error_code: ...@@ -207,13 +207,13 @@ error_code:
addl $8,%esp addl $8,%esp
jmp ret_from_sys_call jmp ret_from_sys_call
.align 2 .align 4
_coprocessor_error: _coprocessor_error:
pushl $0 pushl $0
pushl $_do_coprocessor_error pushl $_do_coprocessor_error
jmp error_code jmp error_code
.align 2 .align 4
_device_not_available: _device_not_available:
pushl $-1 # mark this as an int pushl $-1 # mark this as an int
SAVE_ALL SAVE_ALL
...@@ -227,70 +227,85 @@ _device_not_available: ...@@ -227,70 +227,85 @@ _device_not_available:
addl $4,%esp addl $4,%esp
ret ret
.align 4
_debug: _debug:
pushl $0 pushl $0
pushl $_do_debug pushl $_do_debug
jmp error_code jmp error_code
.align 4
_nmi: _nmi:
pushl $0 pushl $0
pushl $_do_nmi pushl $_do_nmi
jmp error_code jmp error_code
.align 4
_int3: _int3:
pushl $0 pushl $0
pushl $_do_int3 pushl $_do_int3
jmp error_code jmp error_code
.align 4
_overflow: _overflow:
pushl $0 pushl $0
pushl $_do_overflow pushl $_do_overflow
jmp error_code jmp error_code
.align 4
_bounds: _bounds:
pushl $0 pushl $0
pushl $_do_bounds pushl $_do_bounds
jmp error_code jmp error_code
.align 4
_invalid_op: _invalid_op:
pushl $0 pushl $0
pushl $_do_invalid_op pushl $_do_invalid_op
jmp error_code jmp error_code
.align 4
_coprocessor_segment_overrun: _coprocessor_segment_overrun:
pushl $0 pushl $0
pushl $_do_coprocessor_segment_overrun pushl $_do_coprocessor_segment_overrun
jmp error_code jmp error_code
.align 4
_reserved: _reserved:
pushl $0 pushl $0
pushl $_do_reserved pushl $_do_reserved
jmp error_code jmp error_code
.align 4
_double_fault: _double_fault:
pushl $_do_double_fault pushl $_do_double_fault
jmp error_code jmp error_code
.align 4
_invalid_TSS: _invalid_TSS:
pushl $_do_invalid_TSS pushl $_do_invalid_TSS
jmp error_code jmp error_code
.align 4
_segment_not_present: _segment_not_present:
pushl $_do_segment_not_present pushl $_do_segment_not_present
jmp error_code jmp error_code
.align 4
_stack_segment: _stack_segment:
pushl $_do_stack_segment pushl $_do_stack_segment
jmp error_code jmp error_code
.align 4
_general_protection: _general_protection:
pushl $_do_general_protection pushl $_do_general_protection
jmp error_code jmp error_code
.align 4
_alignment_check: _alignment_check:
pushl $_do_alignment_check pushl $_do_alignment_check
jmp error_code jmp error_code
.align 4
_page_fault: _page_fault:
pushl $_do_page_fault pushl $_do_page_fault
jmp error_code jmp error_code
...@@ -41,7 +41,7 @@ current->start_code + current->end_code) ...@@ -41,7 +41,7 @@ current->start_code + current->end_code)
unsigned long low_memory = 0; unsigned long low_memory = 0;
unsigned long high_memory = 0; unsigned long high_memory = 0;
unsigned long paging_pages = 0; unsigned long free_page_list = 0;
#define copy_page(from,to) \ #define copy_page(from,to) \
__asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si") __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")
...@@ -71,14 +71,16 @@ void free_page(unsigned long addr) ...@@ -71,14 +71,16 @@ void free_page(unsigned long addr)
if (addr < low_memory) if (addr < low_memory)
return; return;
if (addr < high_memory) { i = addr - low_memory;
i = addr - low_memory; i >>= 12;
i >>= 12; if (addr < high_memory && mem_map[i]) {
if (mem_map[i] == 1) if (--mem_map[i])
++nr_free_pages;
if (mem_map[i]--)
return; return;
mem_map[i] = 0; addr &= 0xfffff000;
*(unsigned long *) addr = free_page_list;
free_page_list = addr;
++nr_free_pages;
return;
} }
printk("trying to free free page (%08x): memory probably corrupted\n",addr); printk("trying to free free page (%08x): memory probably corrupted\n",addr);
} }
...@@ -170,7 +172,7 @@ int copy_page_tables(unsigned long from,unsigned long to,long size) ...@@ -170,7 +172,7 @@ int copy_page_tables(unsigned long from,unsigned long to,long size)
from_page_table = (unsigned long *) (0xfffff000 & *from_dir); from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
if (!(to_page_table = (unsigned long *) get_free_page(GFP_KERNEL))) if (!(to_page_table = (unsigned long *) get_free_page(GFP_KERNEL)))
return -1; /* Out of memory, see freeing */ return -1; /* Out of memory, see freeing */
*to_dir = ((unsigned long) to_page_table) | 7; *to_dir = ((unsigned long) to_page_table) | PAGE_ACCESSED | 7;
nr = (from==0)?0xA0:1024; nr = (from==0)?0xA0:1024;
for ( ; nr-- > 0 ; from_page_table++,to_page_table++) { for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
repeat: repeat:
...@@ -187,7 +189,7 @@ int copy_page_tables(unsigned long from,unsigned long to,long size) ...@@ -187,7 +189,7 @@ int copy_page_tables(unsigned long from,unsigned long to,long size)
goto repeat; goto repeat;
} }
*to_page_table = this_page; *to_page_table = this_page;
*from_page_table = new_page | (PAGE_DIRTY | 7); *from_page_table = new_page | (PAGE_DIRTY | PAGE_ACCESSED | 7);
continue; continue;
} }
this_page &= ~2; this_page &= ~2;
...@@ -294,7 +296,7 @@ int remap_page_range(unsigned long from, unsigned long to, unsigned long size, ...@@ -294,7 +296,7 @@ int remap_page_range(unsigned long from, unsigned long to, unsigned long size,
invalidate(); invalidate();
return -1; return -1;
} }
*dir++ = ((unsigned long) page_table) | 7; *dir++ = ((unsigned long) page_table) | PAGE_ACCESSED | 7;
} }
else else
page_table = (unsigned long *)(0xfffff000 & *dir++); page_table = (unsigned long *)(0xfffff000 & *dir++);
...@@ -384,7 +386,7 @@ static unsigned long put_page(unsigned long page,unsigned long address) ...@@ -384,7 +386,7 @@ static unsigned long put_page(unsigned long page,unsigned long address)
oom(current); oom(current);
tmp = BAD_PAGETABLE; tmp = BAD_PAGETABLE;
} }
*page_table = tmp | 7; *page_table = tmp | PAGE_ACCESSED | 7;
return 0; return 0;
} }
page_table += (address>>12) & 0x3ff; page_table += (address>>12) & 0x3ff;
...@@ -393,7 +395,7 @@ static unsigned long put_page(unsigned long page,unsigned long address) ...@@ -393,7 +395,7 @@ static unsigned long put_page(unsigned long page,unsigned long address)
*page_table = 0; *page_table = 0;
invalidate(); invalidate();
} }
*page_table = page | 7; *page_table = page | PAGE_ACCESSED | 7;
/* no need for invalidate */ /* no need for invalidate */
return page; return page;
} }
...@@ -429,7 +431,7 @@ unsigned long put_dirty_page(unsigned long page, unsigned long address) ...@@ -429,7 +431,7 @@ unsigned long put_dirty_page(unsigned long page, unsigned long address)
*page_table = 0; *page_table = 0;
invalidate(); invalidate();
} }
*page_table = page | (PAGE_DIRTY | 7); *page_table = page | (PAGE_DIRTY | PAGE_ACCESSED | 7);
/* no need for invalidate */ /* no need for invalidate */
return page; return page;
} }
...@@ -472,7 +474,7 @@ static void un_wp_page(unsigned long * table_entry, struct task_struct * task) ...@@ -472,7 +474,7 @@ static void un_wp_page(unsigned long * table_entry, struct task_struct * task)
new_page = BAD_PAGE; new_page = BAD_PAGE;
send_sig(SIGSEGV,task,1); send_sig(SIGSEGV,task,1);
} }
*table_entry = new_page | dirty | 7; *table_entry = new_page | dirty | PAGE_ACCESSED | 7;
free_page(old_page); free_page(old_page);
invalidate(); invalidate();
} }
...@@ -580,7 +582,7 @@ static int try_to_share(unsigned long address, struct task_struct * p) ...@@ -580,7 +582,7 @@ static int try_to_share(unsigned long address, struct task_struct * p)
to = get_free_page(GFP_KERNEL); to = get_free_page(GFP_KERNEL);
if (!to) if (!to)
return 0; return 0;
*(unsigned long *) to_page = to | 7; *(unsigned long *) to_page = to | PAGE_ACCESSED | 7;
} }
to &= 0xfffff000; to &= 0xfffff000;
to_page = to + ((address>>10) & 0xffc); to_page = to + ((address>>10) & 0xffc);
...@@ -650,7 +652,7 @@ static unsigned long get_empty_pgtable(unsigned long * p) ...@@ -650,7 +652,7 @@ static unsigned long get_empty_pgtable(unsigned long * p)
*p = 0; *p = 0;
} }
if (page) { if (page) {
*p = page | 7; *p = page | PAGE_ACCESSED | 7;
return *p; return *p;
} }
if (page = get_free_page(GFP_KERNEL)) if (page = get_free_page(GFP_KERNEL))
...@@ -764,7 +766,8 @@ void show_mem(void) ...@@ -764,7 +766,8 @@ void show_mem(void)
printk("Free pages: %6d\n",nr_free_pages); printk("Free pages: %6d\n",nr_free_pages);
printk("Buffer heads: %6d\n",nr_buffer_heads); printk("Buffer heads: %6d\n",nr_buffer_heads);
printk("Buffer blocks: %6d\n",nr_buffers); printk("Buffer blocks: %6d\n",nr_buffers);
for (i = 0 ; i < paging_pages ; i++) { i = (high_memory - low_memory) >> 12;
while (i-- > 0) {
total++; total++;
if (!mem_map[i]) if (!mem_map[i])
free++; free++;
...@@ -830,18 +833,26 @@ void do_page_fault(unsigned long *esp, unsigned long error_code) ...@@ -830,18 +833,26 @@ void do_page_fault(unsigned long *esp, unsigned long error_code)
unsigned long mem_init(unsigned long start_mem, unsigned long end_mem) unsigned long mem_init(unsigned long start_mem, unsigned long end_mem)
{ {
unsigned long tmp;
end_mem &= 0xfffff000; end_mem &= 0xfffff000;
high_memory = end_mem; high_memory = end_mem;
mem_map = (char *) start_mem; mem_map = (char *) start_mem;
paging_pages = (end_mem - start_mem) >> 12; tmp = (end_mem - start_mem) >> 12;
start_mem += paging_pages; start_mem += tmp;
start_mem += 0xfff; start_mem += 0xfff;
start_mem &= 0xfffff000; start_mem &= 0xfffff000;
low_memory = start_mem; low_memory = start_mem;
paging_pages = (high_memory - low_memory) >> 12; tmp = (high_memory - low_memory) >> 12;
swap_device = 0; swap_device = 0;
swap_file = NULL; swap_file = NULL;
memset(mem_map,0,paging_pages); memset(mem_map,0,tmp);
nr_free_pages = paging_pages; nr_free_pages = tmp;
free_page_list = low_memory;
*(unsigned long *) free_page_list = 0;
while ((tmp = free_page_list + 4096) < high_memory) {
*(unsigned long *) tmp = free_page_list;
free_page_list = tmp;
}
return start_mem; return start_mem;
} }
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
static int lowest_bit = 0; static int lowest_bit = 0;
static int highest_bit = 0; static int highest_bit = 0;
extern unsigned long free_page_list;
/* /*
* The following are used to make sure we don't thrash too much... * The following are used to make sure we don't thrash too much...
*/ */
...@@ -150,6 +152,9 @@ int try_to_swap_out(unsigned long * table_ptr) ...@@ -150,6 +152,9 @@ int try_to_swap_out(unsigned long * table_ptr)
page = *table_ptr; page = *table_ptr;
if (!(PAGE_PRESENT & page)) if (!(PAGE_PRESENT & page))
return 0; return 0;
*table_ptr &= ~PAGE_ACCESSED;
if (PAGE_ACCESSED & page)
return 0;
if (page < low_memory || page >= high_memory) if (page < low_memory || page >= high_memory)
return 0; return 0;
for (i = 0; i < NR_LAST_FREE_PAGES; i++) for (i = 0; i < NR_LAST_FREE_PAGES; i++)
...@@ -182,6 +187,40 @@ int try_to_swap_out(unsigned long * table_ptr) ...@@ -182,6 +187,40 @@ int try_to_swap_out(unsigned long * table_ptr)
#define LAST_VM_PAGE (1024*1024) #define LAST_VM_PAGE (1024*1024)
#define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE) #define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE)
static unsigned int dir_entry = 1024;
static unsigned int page_entry = 0;
/*
* sys_idle() does nothing much: it just searches for likely candidates for
* swapping out or forgetting about. This speeds up the search when we
* actually have to swap.
*/
int sys_idle(void)
{
struct task_struct * p;
unsigned long page;
need_resched = 1;
if (dir_entry >= 1024)
dir_entry = FIRST_VM_PAGE>>10;
p = task[dir_entry >> 4];
page = pg_dir[dir_entry];
if (!(page & 1) || !p || !p->swappable) {
dir_entry++;
return 0;
}
page &= 0xfffff000;
if (page_entry >= 1024) {
page_entry = 0;
dir_entry++;
return 0;
}
page = *(page_entry + (unsigned long *) page);
if ((page < low_memory) || !(page & PAGE_PRESENT) || (page & PAGE_ACCESSED))
page_entry++;
return 0;
}
/* /*
* Go through the page tables, searching for a user page that * Go through the page tables, searching for a user page that
* we can swap out. * we can swap out.
...@@ -190,11 +229,9 @@ int try_to_swap_out(unsigned long * table_ptr) ...@@ -190,11 +229,9 @@ int try_to_swap_out(unsigned long * table_ptr)
* is un-swappable), allowing high-priority processes which cannot be * is un-swappable), allowing high-priority processes which cannot be
* swapped out (things like user-level device drivers (Not implemented)). * swapped out (things like user-level device drivers (Not implemented)).
*/ */
int swap_out(void) int swap_out(unsigned int priority)
{ {
static int dir_entry = 1024; int counter = VM_PAGES / 2;
static int page_entry = -1;
int counter = VM_PAGES;
int pg_table; int pg_table;
struct task_struct * p; struct task_struct * p;
...@@ -203,7 +240,7 @@ int swap_out(void) ...@@ -203,7 +240,7 @@ int swap_out(void)
goto no_swap; goto no_swap;
if (dir_entry >= 1024) if (dir_entry >= 1024)
dir_entry = FIRST_VM_PAGE>>10; dir_entry = FIRST_VM_PAGE>>10;
if (!(p = task[dir_entry >> 4])) { if (!(p = task[dir_entry >> 4]) || !p->swappable) {
counter -= 1024; counter -= 1024;
dir_entry++; dir_entry++;
goto check_dir; goto check_dir;
...@@ -222,24 +259,41 @@ int swap_out(void) ...@@ -222,24 +259,41 @@ int swap_out(void)
check_table: check_table:
if (counter < 0) if (counter < 0)
goto no_swap; goto no_swap;
counter--;
page_entry++;
if (page_entry >= 1024) { if (page_entry >= 1024) {
page_entry = -1; page_entry = 0;
dir_entry++; dir_entry++;
goto check_dir; goto check_dir;
} }
if (p->swappable && try_to_swap_out(page_entry + (unsigned long *) pg_table)) { if (try_to_swap_out(page_entry + (unsigned long *) pg_table)) {
p->rss--; p->rss--;
dir_entry++;
return 1; return 1;
} }
page_entry++;
counter--;
goto check_table; goto check_table;
no_swap: no_swap:
printk("Out of swap-memory\n\r");
return 0; return 0;
} }
static int try_to_free_page(void)
{
if (shrink_buffers(0))
return 1;
if (swap_out(0))
return 1;
if (shrink_buffers(1))
return 1;
if (swap_out(1))
return 1;
if (shrink_buffers(2))
return 1;
if (swap_out(2))
return 1;
if (shrink_buffers(3))
return 1;
return swap_out(3);
}
/* /*
* Get physical address of first (actually last :-) free page, and mark it * Get physical address of first (actually last :-) free page, and mark it
* used. If no free pages left, return 0. * used. If no free pages left, return 0.
...@@ -250,29 +304,24 @@ unsigned long get_free_page(int priority) ...@@ -250,29 +304,24 @@ unsigned long get_free_page(int priority)
static unsigned long index = 0; static unsigned long index = 0;
repeat: repeat:
__asm__("std ; repne ; scasb\n\t" result = free_page_list;
"jne 1f\n\t"
"movb $1,1(%%edi)\n\t"
"sall $12,%%ecx\n\t"
"addl %2,%%ecx\n\t"
"movl %%ecx,%%edx\n\t"
"movl $1024,%%ecx\n\t"
"leal 4092(%%edx),%%edi\n\t"
"rep ; stosl\n\t"
"movl %%edx,%%eax\n"
"1:\tcld"
:"=a" (result)
:"0" (0),"b" (low_memory),"c" (paging_pages),
"D" (mem_map+paging_pages-1)
:"di","cx","dx");
if (result >= high_memory)
goto repeat;
if ((result && result < low_memory) || (result & 0xfff)) {
printk("weird result: %08x\n",result);
result = 0;
}
if (result) { if (result) {
--nr_free_pages; if ((result & 0xfff) || result < low_memory || result >= high_memory) {
free_page_list = 0;
printk("Result = %08x - memory map destroyed\n");
panic("mm error");
}
free_page_list = *(unsigned long *) result;
nr_free_pages--;
if (mem_map[MAP_NR(result)]) {
printk("Free page %08x has mem_map = %d\n",
result,mem_map[MAP_NR(result)]);
goto repeat;
}
mem_map[MAP_NR(result)] = 1;
__asm__ __volatile__("cld ; rep ; stosl"
::"a" (0),"c" (1024),"D" (result)
:"di","cx");
if (index >= NR_LAST_FREE_PAGES) if (index >= NR_LAST_FREE_PAGES)
index = 0; index = 0;
last_free_pages[index] = result; last_free_pages[index] = result;
...@@ -286,11 +335,7 @@ unsigned long get_free_page(int priority) ...@@ -286,11 +335,7 @@ unsigned long get_free_page(int priority)
} }
if (priority <= GFP_BUFFER) if (priority <= GFP_BUFFER)
return 0; return 0;
if (shrink_buffers()) { if (try_to_free_page()) {
schedule();
goto repeat;
}
if (swap_out()) {
schedule(); schedule();
goto repeat; goto repeat;
} }
......
...@@ -7,17 +7,27 @@ ...@@ -7,17 +7,27 @@
# #
# Note 2! The CFLAGS definition is now in the main makefile... # Note 2! The CFLAGS definition is now in the main makefile...
# only these two lines should need to be changed to remove inet sockets.
# (and the tcp/tcpip.o in net.o)
SUBDIRS =# tcp
SOCK_FLAGS =# -DINET_SOCKETS
.c.o: .c.o:
$(CC) $(CFLAGS) -c $< $(CC) $(CFLAGS) $(SOCK_FLAGS) -c $<
.s.o: .s.o:
$(AS) -o $*.o $< $(AS) -o $*.o $<
.c.s: .c.s:
$(CC) $(CFLAGS) -S $< $(CC) $(CFLAGS) -S $<
OBJS = socket.o unix.o OBJS = socket.o unix.o
net.o: $(OBJS) subdirs
$(LD) -r -o net.o $(OBJS) #tcp/tcpip.o
net.o: $(OBJS)
$(LD) -r -o net.o $(OBJS) subdirs: dummy
for i in $(SUBDIRS); do (cd $$i; echo $$i; $(MAKE)) || exit; done
clean: clean:
rm -f core *.o *.a tmp_make rm -f core *.o *.a tmp_make
...@@ -27,6 +37,9 @@ dep: ...@@ -27,6 +37,9 @@ dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
for i in *.c;do $(CPP) -M $$i;done >> tmp_make for i in *.c;do $(CPP) -M $$i;done >> tmp_make
cp tmp_make Makefile cp tmp_make Makefile
@for i in $(SUBDIRS); do (cd $$i; echo $$i; $(MAKE) dep || exit; done
dummy:
### Dependencies: ### Dependencies:
socket.o : socket.c /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/errno.h \ socket.o : socket.c /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/errno.h \
......
#ifndef _KERN_SOCK_H #ifndef _KERN_SOCK_H
#define _KERN_SOCK_H #define _KERN_SOCK_H
#undef SOCK_DEBUG
#define NSOCKETS 128 /* should be dynamic, later... */ #define NSOCKETS 128 /* should be dynamic, later... */
typedef enum { typedef enum {
...@@ -29,7 +29,7 @@ struct socket { ...@@ -29,7 +29,7 @@ struct socket {
socket_state state; socket_state state;
long flags; long flags;
struct proto_ops *ops; /* protocols do most everything */ struct proto_ops *ops; /* protocols do most everything */
char *data; /* protocol data */ void *data; /* protocol data */
struct socket *conn; /* server socket connected to */ struct socket *conn; /* server socket connected to */
struct socket *iconn; /* incomplete client connections */ struct socket *iconn; /* incomplete client connections */
struct socket *next; struct socket *next;
...@@ -45,15 +45,31 @@ struct proto_ops { ...@@ -45,15 +45,31 @@ struct proto_ops {
int (*bind)(struct socket *sock, struct sockaddr *umyaddr, int (*bind)(struct socket *sock, struct sockaddr *umyaddr,
int sockaddr_len); int sockaddr_len);
int (*connect)(struct socket *sock, struct sockaddr *uservaddr, int (*connect)(struct socket *sock, struct sockaddr *uservaddr,
int sockaddr_len); int sockaddr_len, int flags);
int (*socketpair)(struct socket *sock1, struct socket *sock2); int (*socketpair)(struct socket *sock1, struct socket *sock2);
int (*accept)(struct socket *sock, struct socket *newsock); int (*accept)(struct socket *sock, struct socket *newsock, int flags);
int (*getname)(struct socket *sock, struct sockaddr *uaddr, int (*getname)(struct socket *sock, struct sockaddr *uaddr,
int *usockaddr_len, int peer); int *usockaddr_len, int peer);
int (*read)(struct socket *sock, char *ubuf, int size, int nonblock); int (*read)(struct socket *sock, char *ubuf, int size, int nonblock);
int (*write)(struct socket *sock, char *ubuf, int size, int nonblock); int (*write)(struct socket *sock, char *ubuf, int size, int nonblock);
int (*select)(struct socket *sock, int sel_type, select_table * wait); int (*select)(struct socket *sock, int sel_type, select_table * wait);
int (*ioctl)(struct socket *sock, unsigned int cmd, unsigned long arg); int (*ioctl)(struct socket *sock, unsigned int cmd, unsigned long arg);
int (*listen)(struct socket *sock, int len);
int (*send)(struct socket *sock, void *buff, int len, int nonblock,
unsigned flags);
int (*recv)(struct socket *sock, void *buff, int len, int nonblock,
unsigned flags);
int (*sendto)(struct socket *sock, void *buff, int len, int nonblock,
unsigned flags, struct sockaddr *, int addr_len);
int (*recvfrom)(struct socket *sock, void *buff, int len, int nonblock,
unsigned flags, struct sockaddr *, int *addr_len);
int (*shutdown)(struct socket *sock, int flags);
int (*setsockopt)(struct socket *sock, int level, int optname,
char *optval, int optlen);
int (*getsockopt)(struct socket *sock, int level, int optname,
char *optval, int *optlen);
int (*fcntl) (struct socket *sock, unsigned int cmd,
unsigned long arg);
}; };
extern int sock_awaitconn(struct socket *mysock, struct socket *servsock); extern int sock_awaitconn(struct socket *mysock, struct socket *servsock);
......
/* modified by Ross Biro to help support inet sockets. */
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -16,13 +17,19 @@ ...@@ -16,13 +17,19 @@
extern int sys_close(int fd); extern int sys_close(int fd);
extern struct proto_ops unix_proto_ops; extern struct proto_ops unix_proto_ops;
#ifdef INET_SOCKETS
extern struct proto_ops inet_proto_ops;
#endif
static struct { static struct {
short family; short family;
char *name; char *name;
struct proto_ops *ops; struct proto_ops *ops;
} proto_table[] = { } proto_table[] = {
AF_UNIX, "AF_UNIX", &unix_proto_ops {AF_UNIX, "AF_UNIX", &unix_proto_ops},
#ifdef INET_SOCKETS
{AF_INET, "AF_INET", &inet_proto_ops},
#endif
}; };
#define NPROTO (sizeof(proto_table) / sizeof(proto_table[0])) #define NPROTO (sizeof(proto_table) / sizeof(proto_table[0]))
...@@ -277,16 +284,6 @@ sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -277,16 +284,6 @@ sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
printk("sock_ioctl: can't find socket for inode!\n"); printk("sock_ioctl: can't find socket for inode!\n");
return -EBADF; return -EBADF;
} }
switch (cmd) {
case TIOCINQ:
case TIOCOUTQ:
if (sock->flags & SO_ACCEPTCON)
return -EINVAL;
break;
default:
return -EINVAL;
}
return sock->ops->ioctl(sock, cmd, arg); return sock->ops->ioctl(sock, cmd, arg);
} }
...@@ -302,23 +299,6 @@ sock_select(struct inode *inode, struct file *file, int sel_type, select_table * ...@@ -302,23 +299,6 @@ sock_select(struct inode *inode, struct file *file, int sel_type, select_table *
printk("sock_select: can't find socket for inode!\n"); printk("sock_select: can't find socket for inode!\n");
return 0; return 0;
} }
/*
* handle server sockets specially
*/
if (sock->flags & SO_ACCEPTCON) {
if (sel_type == SEL_IN) {
PRINTK("sock_select: %sconnections pending\n",
sock->iconn ? "" : "no ");
if (sock->iconn)
return 1;
select_wait(&inode->i_wait, wait);
return sock->iconn ? 1 : 0;
}
PRINTK("sock_select: nothing else for server socket\n");
select_wait(&inode->i_wait, wait);
return 0;
}
/* /*
* we can't return errors to select, so its either yes or no. * we can't return errors to select, so its either yes or no.
*/ */
...@@ -555,6 +535,8 @@ sock_listen(int fd, int backlog) ...@@ -555,6 +535,8 @@ sock_listen(int fd, int backlog)
PRINTK("sys_listen: socket already accepting connections!\n"); PRINTK("sys_listen: socket already accepting connections!\n");
return -EINVAL; return -EINVAL;
} }
if (sock->ops && sock->ops->listen)
sock->ops->listen (sock, backlog);
sock->flags |= SO_ACCEPTCON; sock->flags |= SO_ACCEPTCON;
return 0; return 0;
} }
...@@ -567,7 +549,7 @@ static int ...@@ -567,7 +549,7 @@ static int
sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen) sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
{ {
struct file *file; struct file *file;
struct socket *sock, *clientsock, *newsock; struct socket *sock, *newsock;
int i; int i;
PRINTK("sys_accept: fd = %d\n", fd); PRINTK("sys_accept: fd = %d\n", fd);
...@@ -582,20 +564,6 @@ sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen) ...@@ -582,20 +564,6 @@ sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
return -EINVAL; return -EINVAL;
} }
/*
* if there aren't any sockets awaiting connection, then wait for
* one, unless nonblocking
*/
while (!(clientsock = sock->iconn)) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
interruptible_sleep_on(sock->wait);
if (current->signal & ~current->blocked) {
PRINTK("sys_accept: sleep was interrupted\n");
return -ERESTARTSYS;
}
}
if (!(newsock = sock_alloc(0))) { if (!(newsock = sock_alloc(0))) {
printk("sys_accept: no more sockets\n"); printk("sys_accept: no more sockets\n");
return -EINVAL; return -EINVAL;
...@@ -611,24 +579,20 @@ sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen) ...@@ -611,24 +579,20 @@ sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
sock_release(newsock); sock_release(newsock);
return -EINVAL; return -EINVAL;
} }
i = newsock->ops->accept(sock, newsock, file->f_flags);
if ( i < 0)
{
sock_release (newsock);
return (i);
}
PRINTK("sys_accept: connected socket 0x%x via 0x%x\n",
sock, newsock);
/*
* great. finish the connection relative to server and client,
* wake up the client and return the new fd to the server
*/
sock->iconn = clientsock->next;
clientsock->next = NULL;
newsock->conn = clientsock;
clientsock->conn = newsock;
clientsock->state = SS_CONNECTED;
newsock->state = SS_CONNECTED;
newsock->ops->accept(sock, newsock);
PRINTK("sys_accept: connected socket 0x%x via 0x%x to 0x%x\n",
sock, newsock, clientsock);
if (upeer_sockaddr) if (upeer_sockaddr)
newsock->ops->getname(newsock, upeer_sockaddr, newsock->ops->getname(newsock, upeer_sockaddr,
upeer_addrlen, 1); upeer_addrlen, 1);
wake_up(clientsock->wait);
return fd; return fd;
} }
...@@ -640,16 +604,18 @@ static int ...@@ -640,16 +604,18 @@ static int
sock_connect(int fd, struct sockaddr *uservaddr, int addrlen) sock_connect(int fd, struct sockaddr *uservaddr, int addrlen)
{ {
struct socket *sock; struct socket *sock;
struct file *file;
int i; int i;
PRINTK("sys_connect: fd = %d\n", fd); PRINTK("sys_connect: fd = %d\n", fd);
if (!(sock = sockfd_lookup(fd, NULL))) if (!(sock = sockfd_lookup(fd, &file)))
return -EBADF; return -EBADF;
if (sock->state != SS_UNCONNECTED) { if (sock->state != SS_UNCONNECTED) {
PRINTK("sys_connect: socket not unconnected\n"); PRINTK("sys_connect: socket not unconnected\n");
return -EINVAL; return -EINVAL;
} }
if ((i = sock->ops->connect(sock, uservaddr, addrlen)) < 0) { i = sock->ops->connect(sock, uservaddr, addrlen, file->f_flags);
if (i < 0) {
PRINTK("sys_connect: connect failed\n"); PRINTK("sys_connect: connect failed\n");
return i; return i;
} }
...@@ -678,6 +644,168 @@ sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len) ...@@ -678,6 +644,168 @@ sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
return sock->ops->getname(sock, usockaddr, usockaddr_len, 1); return sock->ops->getname(sock, usockaddr, usockaddr_len, 1);
} }
/* send - shutdown added by bir7@leland.stanford.edu */
static int
sys_send( int fd, void * buff, int len, unsigned flags)
{
struct socket *sock;
struct file *file;
PRINTK("sys_send (fd = %d, buff = %X, len = %d, flags = %X)\n",
fd, buff, len, flags);
if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
return (-EBADF);
if (!(sock = sockfd_lookup(fd, NULL)))
return (-ENOTSOCK);
return (sock->ops->send (sock, buff, len, (file->f_flags & O_NONBLOCK),
flags));
}
static int
sys_sendto( int fd, void * buff, int len, unsigned flags,
struct sockaddr *addr, int addr_len)
{
struct socket *sock;
struct file *file;
PRINTK("sys_sendto (fd = %d, buff = %X, len = %d, flags = %X,"
" addr=%X, alen = %d\n", fd, buff, len, flags, addr, addr_len);
if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
return (-EBADF);
if (!(sock = sockfd_lookup(fd, NULL)))
return (-ENOTSOCK);
return (sock->ops->sendto (sock, buff, len,
(file->f_flags & O_NONBLOCK),
flags, addr, addr_len));
}
static int
sys_recv( int fd, void * buff, int len, unsigned flags)
{
struct socket *sock;
struct file *file;
PRINTK("sys_recv (fd = %d, buff = %X, len = %d, flags = %X)\n",
fd, buff, len, flags);
if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
return (-EBADF);
if (!(sock = sockfd_lookup(fd, NULL)))
return (-ENOTSOCK);
return (sock->ops->recv (sock, buff, len,(file->f_flags & O_NONBLOCK),
flags));
}
static int
sys_recvfrom( int fd, void * buff, int len, unsigned flags,
struct sockaddr *addr, int *addr_len)
{
struct socket *sock;
struct file *file;
PRINTK("sys_recvfrom (fd = %d, buff = %X, len = %d, flags = %X,"
" addr=%X, alen=%X\n", fd, buff, len, flags, addr, addr_len);
if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
return (-EBADF);
if (!(sock = sockfd_lookup(fd, NULL)))
return (-ENOTSOCK);
return (sock->ops->recvfrom (sock, buff, len,
(file->f_flags & O_NONBLOCK),
flags, addr, addr_len));
}
static int
sys_setsockopt (int fd, int level, int optname, char *optval, int optlen)
{
struct socket *sock;
struct file *file;
PRINTK ("sys_setsockopt(fd=%d, level=%d, optname=%d,\n",fd, level,
optname);
PRINTK (" optval = %X, optlen = %d)\n", optval, optlen);
if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
return (-EBADF);
if (!(sock = sockfd_lookup(fd, NULL)))
return (-ENOTSOCK);
return (sock->ops->setsockopt (sock, level, optname, optval, optlen));
}
static int
sys_getsockopt (int fd, int level, int optname, char *optval, int *optlen)
{
struct socket *sock;
struct file *file;
PRINTK ("sys_getsockopt(fd=%d, level=%d, optname=%d,\n",fd, level,
optname);
PRINTK (" optval = %X, optlen = %X)\n", optval, optlen);
if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
return (-EBADF);
if (!(sock = sockfd_lookup(fd, NULL)))
return (-ENOTSOCK);
return (0);
return (sock->ops->getsockopt (sock, level, optname, optval, optlen));
}
static int
sys_shutdown( int fd, int how)
{
struct socket *sock;
struct file *file;
PRINTK("sys_shutdown (fd = %d, how = %d)\n",fd, how);
file = current->filp[fd];
if (fd < 0 || fd >= NR_OPEN || file == NULL)
return (-EBADF);
if (!(sock = sockfd_lookup(fd, NULL)))
return (-ENOTSOCK);
return (sock->ops->shutdown (sock, how));
}
int
sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct socket *sock;
sock = socki_lookup (filp->f_inode);
if (sock != NULL && sock->ops != NULL && sock->ops->fcntl != NULL)
return (sock->ops->fcntl (sock, cmd, arg));
return (-EINVAL);
}
/* /*
* system call vectors. since i want to rewrite sockets as streams, we have * system call vectors. since i want to rewrite sockets as streams, we have
* this level of indirection. not a lot of overhead, since more of the work is * this level of indirection. not a lot of overhead, since more of the work is
...@@ -735,6 +863,61 @@ sys_socketcall(int call, unsigned long *args) ...@@ -735,6 +863,61 @@ sys_socketcall(int call, unsigned long *args)
get_fs_long(args+2), get_fs_long(args+2),
(int *)get_fs_long(args+3)); (int *)get_fs_long(args+3));
case SYS_SEND:
verify_area(args, 4 * sizeof (unsigned long));
return ( sys_send (get_fs_long(args+0),
(void *)get_fs_long(args+1),
get_fs_long(args+2),
get_fs_long(args+3)));
case SYS_SENDTO:
verify_area(args, 6 * sizeof (unsigned long));
return ( sys_sendto (get_fs_long(args+0),
(void *)get_fs_long(args+1),
get_fs_long(args+2),
get_fs_long(args+3),
(struct sockaddr *)get_fs_long(args+4),
get_fs_long(args+5)));
case SYS_RECV:
verify_area(args, 4 * sizeof (unsigned long));
return ( sys_recv (get_fs_long(args+0),
(void *)get_fs_long(args+1),
get_fs_long(args+2),
get_fs_long(args+3)));
case SYS_RECVFROM:
verify_area(args, 6 * sizeof (unsigned long));
return ( sys_recvfrom (get_fs_long(args+0),
(void *)get_fs_long(args+1),
get_fs_long(args+2),
get_fs_long(args+3),
(struct sockaddr *)get_fs_long(args+4),
(int *)get_fs_long(args+5)));
case SYS_SHUTDOWN:
verify_area (args, 2* sizeof (unsigned long));
return ( sys_shutdown (get_fs_long (args+0),
get_fs_long (args+1)));
case SYS_SETSOCKOPT:
verify_area (args, 5*sizeof (unsigned long));
return (sys_setsockopt (get_fs_long (args+0),
get_fs_long (args+1),
get_fs_long (args+2),
(char *)get_fs_long (args+3),
get_fs_long (args+4)));
case SYS_GETSOCKOPT:
verify_area (args, 5*sizeof (unsigned long));
return (sys_getsockopt (get_fs_long (args+0),
get_fs_long (args+1),
get_fs_long (args+2),
(char *)get_fs_long (args+3),
(int *)get_fs_long (args+4)));
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -9,5 +9,12 @@ ...@@ -9,5 +9,12 @@
#define SYS_GETSOCKNAME 6 #define SYS_GETSOCKNAME 6
#define SYS_GETPEERNAME 7 #define SYS_GETPEERNAME 7
#define SYS_SOCKETPAIR 8 #define SYS_SOCKETPAIR 8
#define SYS_SEND 9
#define SYS_RECV 10
#define SYS_SENDTO 11
#define SYS_RECVFROM 12
#define SYS_SHUTDOWN 13
#define SYS_SETSOCKOPT 14
#define SYS_GETSOCKOPT 15
#endif _SOCKETCALL_ #endif _SOCKETCALL_
...@@ -46,9 +46,10 @@ static int unix_proto_release(struct socket *sock, struct socket *peer); ...@@ -46,9 +46,10 @@ static int unix_proto_release(struct socket *sock, struct socket *peer);
static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr, static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
int sockaddr_len); int sockaddr_len);
static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr, static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
int sockaddr_len); int sockaddr_len, int flags);
static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2); static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2);
static int unix_proto_accept(struct socket *sock, struct socket *newsock); static int unix_proto_accept(struct socket *sock, struct socket *newsock,
int flags);
static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr, static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
int *usockaddr_len, int peer); int *usockaddr_len, int peer);
static int unix_proto_read(struct socket *sock, char *ubuf, int size, static int unix_proto_read(struct socket *sock, char *ubuf, int size,
...@@ -58,6 +59,24 @@ static int unix_proto_write(struct socket *sock, char *ubuf, int size, ...@@ -58,6 +59,24 @@ static int unix_proto_write(struct socket *sock, char *ubuf, int size,
static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait); static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait);
static int unix_proto_ioctl(struct socket *sock, unsigned int cmd, static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg); unsigned long arg);
static int unix_proto_listen(struct socket *sock, int backlog);
static int unix_proto_send (struct socket *sock, void *buff, int len,
int nonblock, unsigned flags);
static int unix_proto_recv (struct socket *sock, void *buff, int len,
int nonblock, unsigned flags);
static int unix_proto_sendto (struct socket *sock, void *buff, int len,
int nonblock, unsigned flags,
struct sockaddr *addr, int addr_len);
static int unix_proto_recvfrom (struct socket *sock, void *buff, int len,
int nonblock, unsigned flags,
struct sockaddr *addr, int *addr_len);
static int unix_proto_shutdown (struct socket *sock, int how);
static int unix_proto_setsockopt (struct socket *sock, int level, int optname,
char *optval, int optlen);
static int unix_proto_getsockopt (struct socket *sock, int level, int optname,
char *optval, int *optlen);
struct proto_ops unix_proto_ops = { struct proto_ops unix_proto_ops = {
unix_proto_init, unix_proto_init,
...@@ -72,7 +91,16 @@ struct proto_ops unix_proto_ops = { ...@@ -72,7 +91,16 @@ struct proto_ops unix_proto_ops = {
unix_proto_read, unix_proto_read,
unix_proto_write, unix_proto_write,
unix_proto_select, unix_proto_select,
unix_proto_ioctl unix_proto_ioctl,
unix_proto_listen,
unix_proto_send,
unix_proto_recv,
unix_proto_sendto,
unix_proto_recvfrom,
unix_proto_shutdown,
unix_proto_setsockopt,
unix_proto_getsockopt,
NULL /* unix_proto_fcntl. */
}; };
#ifdef SOCK_DEBUG #ifdef SOCK_DEBUG
...@@ -94,6 +122,68 @@ sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len) ...@@ -94,6 +122,68 @@ sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
} }
} }
#endif #endif
/* don't have to do anything. */
static int
unix_proto_listen (struct socket *sock, int backlog)
{
return (0);
}
static int
unix_proto_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen)
{
return (-EOPNOTSUPP);
}
static int
unix_proto_getsockopt(struct socket *sock, int level, int optname,
char *optval, int *optlen)
{
return (-EOPNOTSUPP);
}
static int
unix_proto_sendto(struct socket *sock, void *buff, int len, int nonblock,
unsigned flags, struct sockaddr *addr, int addr_len)
{
return (-EOPNOTSUPP);
}
static int
unix_proto_recvfrom(struct socket *sock, void *buff, int len, int nonblock,
unsigned flags, struct sockaddr *addr, int *addr_len)
{
return (-EOPNOTSUPP);
}
static int
unix_proto_shutdown (struct socket *sock, int how)
{
return (-EOPNOTSUPP);
}
static int
unix_proto_send(struct socket *sock, void *buff, int len, int nonblock,
unsigned flags)
{
/* this error needs to be checked. */
if (flags != 0)
return (-EINVAL);
return (unix_proto_write (sock, buff, len, nonblock));
}
static int
unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
unsigned flags)
{
/* this error needs to be checked. */
if (flags != 0)
return (-EINVAL);
return (unix_proto_read (sock, buff, len, nonblock));
}
static struct unix_proto_data * static struct unix_proto_data *
unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len) unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
...@@ -282,7 +372,7 @@ unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr, ...@@ -282,7 +372,7 @@ unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
*/ */
static int static int
unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr, unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
int sockaddr_len) int sockaddr_len, int flags)
{ {
int i; int i;
struct unix_proto_data *serv_upd; struct unix_proto_data *serv_upd;
...@@ -337,11 +427,39 @@ unix_proto_socketpair(struct socket *sock1, struct socket *sock2) ...@@ -337,11 +427,39 @@ unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
* on accept, we ref the peer's data for safe writes * on accept, we ref the peer's data for safe writes
*/ */
static int static int
unix_proto_accept(struct socket *sock, struct socket *newsock) unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
{ {
struct socket *clientsock;
PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n", PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n",
sock, newsock); sock, newsock);
unix_data_ref(UN_DATA(newsock->conn));
/*
* if there aren't any sockets awaiting connection, then wait for
* one, unless nonblocking
*/
while (!(clientsock = sock->iconn)) {
if (flags & O_NONBLOCK)
return -EAGAIN;
interruptible_sleep_on(sock->wait);
if (current->signal & ~current->blocked) {
PRINTK("sys_accept: sleep was interrupted\n");
return -ERESTARTSYS;
}
}
/*
* great. finish the connection relative to server and client,
* wake up the client and return the new fd to the server
*/
sock->iconn = clientsock->next;
clientsock->next = NULL;
newsock->conn = clientsock;
clientsock->conn = newsock;
clientsock->state = SS_CONNECTED;
newsock->state = SS_CONNECTED;
wake_up(clientsock->wait);
unix_data_ref (UN_DATA(newsock->conn));
UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn); UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn);
return 0; return 0;
} }
...@@ -525,6 +643,23 @@ unix_proto_select(struct socket *sock, int sel_type, select_table * wait) ...@@ -525,6 +643,23 @@ unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
{ {
struct unix_proto_data *upd, *peerupd; struct unix_proto_data *upd, *peerupd;
/*
* handle server sockets specially
*/
if (sock->flags & SO_ACCEPTCON) {
if (sel_type == SEL_IN) {
PRINTK("sock_select: %sconnections pending\n",
sock->iconn ? "" : "no ");
if (sock->iconn)
return 1;
select_wait(sock->wait, wait);
return sock->iconn ? 1 : 0;
}
PRINTK("sock_select: nothing else for server socket\n");
select_wait(sock->wait, wait);
return 0;
}
if (sel_type == SEL_IN) { if (sel_type == SEL_IN) {
upd = UN_DATA(sock); upd = UN_DATA(sock);
PRINTK("unix_proto_select: there is%s data available\n", PRINTK("unix_proto_select: there is%s data available\n",
...@@ -565,7 +700,10 @@ unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -565,7 +700,10 @@ unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL; peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
switch (cmd) { switch (cmd) {
case TIOCINQ: case TIOCINQ:
if (sock->flags & SO_ACCEPTCON)
return -EINVAL;
verify_area((void *)arg, sizeof(unsigned long)); verify_area((void *)arg, sizeof(unsigned long));
if (UN_BUF_AVAIL(upd) || peerupd) if (UN_BUF_AVAIL(upd) || peerupd)
put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg); put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg);
...@@ -574,6 +712,8 @@ unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -574,6 +712,8 @@ unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break; break;
case TIOCOUTQ: case TIOCOUTQ:
if (sock->flags & SO_ACCEPTCON)
return -EINVAL;
verify_area((void *)arg, sizeof(unsigned long)); verify_area((void *)arg, sizeof(unsigned long));
if (peerupd) if (peerupd)
put_fs_long(UN_BUF_SPACE(peerupd), put_fs_long(UN_BUF_SPACE(peerupd),
......
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