aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Benedict Torvalds <torvalds@klaava.Helsinki.FI>1992-08-06 10:47:32 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:06 -0400
commitfe07d2d9e764decdab478241a2ad5a157392af86 (patch)
treed404d08d9546e77f296b0c1d678f6dcb68b3d829
parent36c51b40b2a02f608b7214efd71cb1e0bbd17788 (diff)
downloadarchive-fe07d2d9e764decdab478241a2ad5a157392af86.tar.gz
0.97 patch1 available on nicv0.97-pl1
It seems all connections to Finland are down (or at least some server is acting up), so patch1 is available only on nic.funet.fi: pub/OS/Linux/testing/Linus/linux-0.97.patch1.Z I'll upload it to the other sites when I get a working ftp-connection. 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
-rw-r--r--Makefile9
-rw-r--r--fs/buffer.c16
-rw-r--r--fs/ext/Makefile2
-rw-r--r--fs/ext/dir.c6
-rw-r--r--fs/ext/freelists.c139
-rw-r--r--fs/ext/inode.c115
-rw-r--r--fs/ext/namei.c23
-rw-r--r--fs/ext/truncate.c2
-rw-r--r--fs/fcntl.c8
-rw-r--r--fs/minix/bitmap.c38
-rw-r--r--fs/open.c123
-rw-r--r--include/linux/config.dist.h4
-rw-r--r--include/linux/config.h4
-rw-r--r--include/linux/config.site.h4
-rw-r--r--include/linux/ctype.h4
-rw-r--r--include/linux/ext_fs.h22
-rw-r--r--include/linux/ext_fs_sb.h12
-rw-r--r--include/linux/fcntl.h7
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/genhd.h4
-rw-r--r--include/linux/limits.h4
-rw-r--r--include/linux/minix_fs.h4
-rw-r--r--include/linux/mm.h5
-rw-r--r--include/linux/msdos_fs.h4
-rw-r--r--include/linux/param.h18
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/linux/signal.h16
-rw-r--r--include/linux/socket.h27
-rw-r--r--include/linux/stat.h4
-rw-r--r--include/linux/sys.h4
-rw-r--r--include/linux/timer.h3
-rw-r--r--include/linux/times.h8
-rw-r--r--include/linux/tty.h4
-rw-r--r--include/linux/types.h5
-rw-r--r--include/linux/un.h4
-rw-r--r--include/linux/unistd.h2
-rw-r--r--init/main.c21
-rw-r--r--kernel/blk_drv/hd.c3
-rw-r--r--kernel/blk_drv/ll_rw_blk.c4
-rw-r--r--kernel/blk_drv/ramdisk.c2
-rw-r--r--kernel/chr_drv/console.c128
-rw-r--r--kernel/chr_drv/mouse.c12
-rw-r--r--kernel/chr_drv/tty_io.c73
-rw-r--r--kernel/chr_drv/tty_ioctl.c41
-rw-r--r--kernel/exit.c24
-rw-r--r--kernel/sched.c23
-rw-r--r--kernel/sys_call.S41
-rw-r--r--mm/memory.c57
-rw-r--r--mm/swap.c121
-rw-r--r--net/Makefile21
-rw-r--r--net/kern_sock.h24
-rw-r--r--net/socket.c301
-rw-r--r--net/socketcall.h7
-rw-r--r--net/unix.c152
54 files changed, 1181 insertions, 531 deletions
diff --git a/Makefile b/Makefile
index 39e87db..d143eac 100644
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,13 @@
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:
#
# The value of KBDFLAGS should be or'ed together from the following
@@ -71,7 +78,7 @@ LD86 =ld86 -0
AS =as
LD =ld
HOSTCC =gcc -static
-CC =gcc -nostdinc -I$(KERNELHDRS)
+CC =gcc -nostdinc -I$(KERNELHDRS) $(PROFILING)
MAKE =make
CPP =$(CC) -E
AR =ar
diff --git a/fs/buffer.c b/fs/buffer.c
index f8efd1f..b8604be 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -557,16 +557,24 @@ static int try_to_free(struct buffer_head * bh)
/*
* 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;
int i;
+ if (priority > 2) {
+ priority = 3;
+ sync_buffers(0);
+ }
bh = free_list;
- for (i = nr_buffers*2 ; i-- > 0 ; bh = bh->b_next_free) {
- wait_on_buffer(bh);
- if (bh->b_count || !bh->b_this_page)
+ i = nr_buffers >> (3-priority);
+ for ( ; i-- > 0 ; bh = bh->b_next_free) {
+ if (bh->b_lock || bh->b_count || !bh->b_this_page)
continue;
if (bh->b_dirt) {
ll_rw_block(WRITEA,bh);
diff --git a/fs/ext/Makefile b/fs/ext/Makefile
index 43fc4e1..d5e994f 100644
--- a/fs/ext/Makefile
+++ b/fs/ext/Makefile
@@ -14,7 +14,7 @@
.s.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
ext.o: $(OBJS)
diff --git a/fs/ext/dir.c b/fs/ext/dir.c
index 54bc7ad..48cefa2 100644
--- a/fs/ext/dir.c
+++ b/fs/ext/dir.c
@@ -62,8 +62,6 @@ static int ext_readdir(struct inode * inode, struct file * filp,
if (!inode || !S_ISDIR(inode->i_mode))
return -EBADF;
-/* if (filp->f_pos & (sizeof (struct ext_dir_entry) - 1))
- return -EBADF; */
while (filp->f_pos < inode->i_size) {
offset = filp->f_pos & 1023;
block = ext_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
@@ -89,8 +87,8 @@ static int ext_readdir(struct inode * inode, struct file * filp,
return i;
}
}
-/* de++; */
- de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
+ de = (struct ext_dir_entry *) ((char *) de
+ + de->rec_len);
}
brelse(bh);
}
diff --git a/fs/ext/freelists.c b/fs/ext/freelists.c
index e39f442..454796c 100644
--- a/fs/ext/freelists.c
+++ b/fs/ext/freelists.c
@@ -15,21 +15,18 @@
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
- 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]
- 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.
+ in s->u.ext_sb.s_firstfreeblocknumber and the block header is stored in
+ s->u.ext_sb.s_firstfreeblock. u.ext_sb.s_freeblockscount contains the count
+ of free blocks.
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
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
- of the block containing the inode is stored in s->u.ext_sb.s_imap[1]. u.ext_sb.s_imap[2] contains
- the count of free inodes.
+ The number of the first free inode is stored in
+ s->u.ext_sb.s_firstfreeinodenumber and the header of the block containing
+ 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 @@
#include <linux/kernel.h>
#include <linux/string.h>
-#ifdef EXTFS_FREELIST
-
#define clear_block(addr) \
__asm__("cld\n\t" \
"rep\n\t" \
@@ -55,7 +50,8 @@ int ext_free_block(int dev, int block)
if (!(sb = get_super(dev)))
panic("trying to free block on nonexistent device");
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");
bh = get_hash_table(dev, block, sb->s_blocksize);
if (bh) {
@@ -69,26 +65,27 @@ int ext_free_block(int dev, int block)
if (bh->b_count)
brelse(bh);
}
- if (sb->u.ext_sb.s_zmap[1])
- efb = (struct ext_free_block *) sb->u.ext_sb.s_zmap[1]->b_data;
- if (!sb->u.ext_sb.s_zmap[1] || efb->count == 254) {
+ if (sb->u.ext_sb.s_firstfreeblock)
+ efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
+ if (!sb->u.ext_sb.s_firstfreeblock || efb->count == 254) {
#ifdef EXTFS_DEBUG
printk("ext_free_block: block full, skipping to %d\n", block);
#endif
- if (sb->u.ext_sb.s_zmap[1])
- brelse (sb->u.ext_sb.s_zmap[1]);
- if (!(sb->u.ext_sb.s_zmap[1] = bread (dev, block, sb->s_blocksize)))
+ if (sb->u.ext_sb.s_firstfreeblock)
+ brelse (sb->u.ext_sb.s_firstfreeblock);
+ if (!(sb->u.ext_sb.s_firstfreeblock = bread (dev,
+ block, sb->s_blocksize)))
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->next = (unsigned long) sb->u.ext_sb.s_zmap[0];
+ efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
+ efb->next = sb->u.ext_sb.s_firstfreeblocknumber;
efb->count = 0;
- sb->u.ext_sb.s_zmap[0] = (struct buffer_head *) block;
+ sb->u.ext_sb.s_firstfreeblocknumber = block;
} else {
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->u.ext_sb.s_zmap[1]->b_dirt = 1;
+ sb->u.ext_sb.s_firstfreeblock->b_dirt = 1;
free_super (sb);
return 1;
}
@@ -98,28 +95,30 @@ int ext_new_block(int dev)
struct buffer_head * bh;
struct super_block * sb;
struct ext_free_block * efb;
- int /* i, */ j;
+ int j;
if (!(sb = get_super(dev)))
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;
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) {
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 {
#ifdef EXTFS_DEBUG
printk("ext_new_block: block empty, skipping to %d\n", efb->next);
#endif
- j = (unsigned long) sb->u.ext_sb.s_zmap[0];
- sb->u.ext_sb.s_zmap[0] = (struct buffer_head *) efb->next;
- brelse (sb->u.ext_sb.s_zmap[1]);
- if (!sb->u.ext_sb.s_zmap[0]) {
- sb->u.ext_sb.s_zmap[1] = NULL;
+ j = sb->u.ext_sb.s_firstfreeblocknumber;
+ sb->u.ext_sb.s_firstfreeblocknumber = efb->next;
+ brelse (sb->u.ext_sb.s_firstfreeblock);
+ if (!sb->u.ext_sb.s_firstfreeblocknumber) {
+ sb->u.ext_sb.s_firstfreeblock = NULL;
} 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");
}
}
@@ -127,7 +126,7 @@ printk("ext_new_block: block empty, skipping to %d\n", efb->next);
printk ("ext_new_block: blk = %d\n", j);
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;
if (!(bh=getblk(dev, j, sb->s_blocksize)))
@@ -153,10 +152,10 @@ unsigned long ext_count_free_blocks(struct super_block *sb)
unsigned long count, block;
lock_super (sb);
- if (!sb->u.ext_sb.s_zmap[1])
+ if (!sb->u.ext_sb.s_firstfreeblock)
count = 0;
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;
block = efb->next;
while (block) {
@@ -172,11 +171,11 @@ unsigned long ext_count_free_blocks(struct super_block *sb)
}
}
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);
return count;
#else
- return (unsigned long) sb->u.ext_sb.s_zmap[2];
+ return sb->u.ext_sb.s_freeblockscount;
#endif
}
@@ -210,30 +209,30 @@ void ext_free_inode(struct inode * inode)
free_super (inode->i_sb);
return;
}
- if (inode->i_sb->u.ext_sb.s_imap[1])
- efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_imap[1]->b_data) +
- (((unsigned long) inode->i_sb->u.ext_sb.s_imap[0])-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 = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
+ (inode->i_sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
+ if (!inode->i_sb->u.ext_sb.s_firstfreeinodeblock || efi->count == 14) {
#ifdef EXTFS_DEBUG
printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
#endif
- if (inode->i_sb->u.ext_sb.s_imap[1])
- brelse (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_firstfreeinodeblock);
block = 2 + (inode->i_ino - 1) / EXT_INODES_PER_BLOCK;
if (!(bh = bread(inode->i_dev, block, inode->i_sb->s_blocksize)))
panic("ext_free_inode: unable to read inode block\n");
efi = ((struct ext_free_inode *) bh->b_data) +
(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;
- inode->i_sb->u.ext_sb.s_imap[0] = (struct buffer_head *) inode->i_ino;
- inode->i_sb->u.ext_sb.s_imap[1] = bh;
+ inode->i_sb->u.ext_sb.s_firstfreeinodenumber = inode->i_ino;
+ inode->i_sb->u.ext_sb.s_firstfreeinodeblock = bh;
} else {
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->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);
memset(inode,0,sizeof(*inode));
}
@@ -243,7 +242,7 @@ struct inode * ext_new_inode(int dev)
struct inode * inode;
struct ext_free_inode * efi;
unsigned long block;
- int /* i, */ j;
+ int j;
if (!(inode=get_empty_inode()))
return NULL;
@@ -253,34 +252,34 @@ struct inode * ext_new_inode(int dev)
return NULL;
}
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;
lock_super (inode->i_sb);
- efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_imap[1]->b_data) +
- (((unsigned long) inode->i_sb->u.ext_sb.s_imap[0])-1)%EXT_INODES_PER_BLOCK;
+ efi = ((struct ext_free_inode *) inode->i_sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
+ (inode->i_sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
if (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 {
#ifdef EXTFS_DEBUG
printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
#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) {
printk ("efi->next = %d\n", efi->next);
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;
- brelse (inode->i_sb->u.ext_sb.s_imap[1]);
- if (!inode->i_sb->u.ext_sb.s_imap[0]) {
- inode->i_sb->u.ext_sb.s_imap[1] = NULL;
+ brelse (inode->i_sb->u.ext_sb.s_firstfreeinodeblock);
+ if (!inode->i_sb->u.ext_sb.s_firstfreeinodenumber) {
+ inode->i_sb->u.ext_sb.s_firstfreeinodeblock = NULL;
} 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");
}
}
- 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_count = 1;
inode->i_nlink = 1;
@@ -306,17 +305,17 @@ unsigned long ext_count_free_inodes(struct super_block *sb)
unsigned long count, block, ino;
lock_super (sb);
- if (!sb->u.ext_sb.s_imap[1])
+ if (!sb->u.ext_sb.s_firstfreeinodeblock)
count = 0;
else {
- efi = ((struct ext_free_inode *) sb->u.ext_sb.s_imap[1]->b_data) +
- ((((unsigned long) sb->u.ext_sb.s_imap[0])-1)%EXT_INODES_PER_BLOCK);
+ efi = ((struct ext_free_inode *) sb->u.ext_sb.s_firstfreeinodeblock->b_data) +
+ ((sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK);
count = efi->count + 1;
ino = efi->next;
while (ino) {
if (ino < 1 || ino > sb->u.ext_sb.s_ninodes) {
- printk ("u.ext_sb.s_imap[0] = %d, ino = %d\n",
- (int) sb->u.ext_sb.s_imap[0],ino);
+ printk ("u.ext_sb.s_firstfreeinodenumber = %d, ino = %d\n",
+ (int) sb->u.ext_sb.s_firstfreeinodenumber,ino);
panic ("ext_count_fre_inodes: bad inode number in free list\n");
}
block = 2 + ((ino - 1) / EXT_INODES_PER_BLOCK);
@@ -333,12 +332,10 @@ unsigned long ext_count_free_inodes(struct super_block *sb)
}
}
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);
return count;
#else
- return (unsigned long) sb->u.ext_sb.s_imap[2];
+ return sb->u.ext_sb.s_freeinodescount;
#endif
}
-
-#endif
diff --git a/fs/ext/inode.c b/fs/ext/inode.c
index dae86ae..67ed523 100644
--- a/fs/ext/inode.c
+++ b/fs/ext/inode.c
@@ -31,24 +31,13 @@ void ext_put_inode(struct inode *inode)
void ext_put_super(struct super_block *sb)
{
-#ifdef EXTFS_BITMAP
- int i;
-#endif
lock_super(sb);
sb->s_dev = 0;
-#ifdef EXTFS_BITMAP
- for(i = 0 ; i < EXT_I_MAP_SLOTS ; i++)
- brelse(sb->u.ext_sb.s_imap[i]);
- for(i = 0 ; i < EXT_Z_MAP_SLOTS ; i++)
- 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
+ if (sb->u.ext_sb.s_firstfreeinodeblock)
+ brelse (sb->u.ext_sb.s_firstfreeinodeblock);
+ if (sb->u.ext_sb.s_firstfreeblock)
+ brelse (sb->u.ext_sb.s_firstfreeblock);
free_super(sb);
return;
}
@@ -67,9 +56,6 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
struct buffer_head *bh;
struct ext_super_block *es;
int dev = s->s_dev,block;
-#ifdef EXTFS_BITMAP
- int i;
-#endif
lock_super(s);
if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
@@ -78,26 +64,18 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
printk("bread failed\n");
return NULL;
}
-/* *((struct ext_super_block *) s) =
- *((struct ext_super_block *) bh->b_data); */
es = (struct ext_super_block *) bh->b_data;
s->s_blocksize = 1024;
s->u.ext_sb.s_ninodes = es->s_ninodes;
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_log_zone_size = es->s_log_zone_size;
s->u.ext_sb.s_max_size = es->s_max_size;
s->s_magic = es->s_magic;
-#ifdef EXTFS_FREELIST
- s->u.ext_sb.s_zmap[0] = (struct buffer_head *) es->s_firstfreeblock;
- s->u.ext_sb.s_zmap[2] = (struct buffer_head *) es->s_freeblockscount;
- s->u.ext_sb.s_imap[0] = (struct buffer_head *) es->s_firstfreeinode;
- s->u.ext_sb.s_imap[2] = (struct buffer_head *) es->s_freeinodescount;
-#endif
+ s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock;
+ s->u.ext_sb.s_freeblockscount = es->s_freeblockscount;
+ s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode;
+ s->u.ext_sb.s_freeinodescount = es->s_freeinodescount;
brelse(bh);
if (s->s_magic != EXT_SUPER_MAGIC) {
s->s_dev = 0;
@@ -105,59 +83,28 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
printk("magic match failed\n");
return NULL;
}
-#ifdef EXTFS_BITMAP
- for (i=0;i < EXT_I_MAP_SLOTS;i++)
- 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;
+ if (!s->u.ext_sb.s_firstfreeblocknumber)
+ s->u.ext_sb.s_firstfreeblock = NULL;
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");
s->s_dev = 0;
free_super(s);
return NULL;
}
- if (!s->u.ext_sb.s_imap[0])
- s->u.ext_sb.s_imap[1] = NULL;
+ if (!s->u.ext_sb.s_firstfreeinodenumber)
+ s->u.ext_sb.s_firstfreeinodeblock = NULL;
else {
- block = 2 + (((unsigned long) s->u.ext_sb.s_imap[0]) - 1) / EXT_INODES_PER_BLOCK;
- if (!(s->u.ext_sb.s_imap[1] = bread(dev, block, BLOCK_SIZE))) {
+ block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK;
+ if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) {
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;
free_super (s);
return NULL;
}
}
-#endif
-
free_super(s);
/* set up enough so that it can read an inode */
s->s_dev = dev;
@@ -172,26 +119,21 @@ struct super_block *ext_read_super(struct super_block *s,void *data)
void ext_write_super (struct super_block *sb)
{
-#ifdef EXTFS_FREELIST
struct buffer_head * bh;
struct ext_super_block * es;
-#ifdef EXTFS_DEBUG
- printk ("ext_write_super called\n");
-#endif
if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) {
printk ("ext_write_super: bread failed\n");
return;
}
es = (struct ext_super_block *) bh->b_data;
- es->s_firstfreeblock = (unsigned long) sb->u.ext_sb.s_zmap[0];
- es->s_freeblockscount = (unsigned long) sb->u.ext_sb.s_zmap[2];
- es->s_firstfreeinode = (unsigned long) sb->u.ext_sb.s_imap[0];
- es->s_freeinodescount = (unsigned long) sb->u.ext_sb.s_imap[2];
+ es->s_firstfreeblock = sb->u.ext_sb.s_firstfreeblocknumber;
+ es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
+ es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
+ es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
bh->b_dirt = 1;
brelse (bh);
sb->s_dirt = 0;
-#endif
}
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(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);
put_fs_long(tmp, &buf->f_bfree);
put_fs_long(tmp, &buf->f_bavail);
@@ -341,13 +284,7 @@ void ext_read_inode(struct inode * inode)
struct ext_inode * raw_inode;
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;
-#endif
if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
panic("unable to read i-node block");
raw_inode = ((struct ext_inode *) bh->b_data) +
@@ -389,13 +326,7 @@ void ext_write_inode(struct inode * inode)
struct ext_inode * raw_inode;
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;
-#endif
if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
panic("unable to read i-node block");
raw_inode = ((struct ext_inode *)bh->b_data) +
diff --git a/fs/ext/namei.c b/fs/ext/namei.c
index bea8dc0..9ddf729 100644
--- a/fs/ext/namei.c
+++ b/fs/ext/namei.c
@@ -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 */
if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
return 1;
-/* if (len < EXT_NAME_LEN && de->name[len])
- return 0; */
if (len < EXT_NAME_LEN && len != de->name_len)
return 0;
__asm__("cld\n\t"
@@ -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,
struct ext_dir_entry ** prev_dir, struct ext_dir_entry ** next_dir)
{
-/* int entries; */
- int block /* ,i */;
+ int block;
long offset;
struct buffer_head * bh;
struct ext_dir_entry * de;
@@ -108,7 +105,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
if (namelen > EXT_NAME_LEN)
namelen = EXT_NAME_LEN;
#endif
-/* entries = dir->i_size / (sizeof (struct ext_dir_entry)); */
if (!(block = dir->i_data[0]))
return NULL;
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
@@ -117,7 +113,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
*prev_dir = NULL;
if (next_dir)
*next_dir = NULL;
-/* i = 0; */
offset = 0;
de = (struct ext_dir_entry *) bh->b_data;
while (offset < dir->i_size) {
@@ -126,8 +121,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
bh = NULL;
if (!(block = ext_bmap(dir,offset>>BLOCK_SIZE_BITS)) ||
!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
-/* i += EXT_DIR_ENTRIES_PER_BLOCK; */
-/* offset += BLOCK_SIZE; */
continue;
}
de = (struct ext_dir_entry *) bh->b_data;
@@ -148,7 +141,6 @@ static struct buffer_head * ext_find_entry(struct inode * dir,
if (prev_dir)
*prev_dir = de;
de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
-/* i++; */
}
brelse(bh);
return NULL;
@@ -218,7 +210,6 @@ static struct buffer_head * ext_add_entry(struct inode * dir,
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE)))
return NULL;
rec_len = ((8 + namelen + EXT_DIR_PAD - 1) / EXT_DIR_PAD) * EXT_DIR_PAD;
-/* i = 0; */
offset = 0;
de = (struct ext_dir_entry *) bh->b_data;
while (1) {
@@ -232,7 +223,6 @@ printk ("ext_add_entry: skipping to next block\n");
if (!block)
return NULL;
if (!(bh = bread(dir->i_dev, block, BLOCK_SIZE))) {
-/* i += EXT_DIR_ENTRIES_PER_BLOCK; */
offset += BLOCK_SIZE;
continue;
}
@@ -271,7 +261,6 @@ printk ("ext_add_entry : creating next block\n");
/* Allocate the entry */
de->inode=0;
de->rec_len = rec_len;
-/* dir->i_size = (i+1)*sizeof(struct ext_dir_entry); */
dir->i_size += de->rec_len;
dir->i_dirt = 1;
dir->i_ctime = CURRENT_TIME;
@@ -292,7 +281,7 @@ printk ("ext_add_entry : creating next block\n");
dir->i_mtime = CURRENT_TIME;
de->name_len = namelen;
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;
*res_dir = de;
return bh;
@@ -441,7 +430,6 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
de->rec_len=16;
de->name_len=1;
strcpy(de->name,".");
-/* de++; */
de = (struct ext_dir_entry *) ((char *) de + de->rec_len);
de->inode = dir->i_ino;
de->rec_len=16;
@@ -474,13 +462,11 @@ int ext_mkdir(struct inode * dir, const char * name, int len, int mode)
*/
static int empty_dir(struct inode * inode)
{
- int /* nr, */ block;
-/* int len; */
+ int block;
unsigned long offset;
struct buffer_head * bh;
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] ||
!(bh=bread(inode->i_dev, inode->i_data[0], BLOCK_SIZE))) {
printk("warning - bad directory on dev %04x\n",inode->i_dev);
@@ -493,7 +479,6 @@ static int empty_dir(struct inode * inode)
printk("warning - bad directory on dev %04x\n",inode->i_dev);
return 0;
}
-/* nr = 2; */
offset = de->rec_len + de1->rec_len;
de = (struct ext_dir_entry *) ((char *) de1 + de1->rec_len);
while (offset < inode->i_size ) {
@@ -749,12 +734,10 @@ static int subdir(struct inode * new, struct inode * old)
#define PARENT_INO(buffer) \
((struct ext_dir_entry *) ((char *) buffer + \
((struct ext_dir_entry *) buffer)->rec_len))->inode
-/* (((struct ext_dir_entry *) (buffer))[1].inode) */
#define PARENT_NAME(buffer) \
((struct ext_dir_entry *) ((char *) buffer + \
((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.
diff --git a/fs/ext/truncate.c b/fs/ext/truncate.c
index 3e647e8..c32a091 100644
--- a/fs/ext/truncate.c
+++ b/fs/ext/truncate.c
@@ -166,8 +166,6 @@ void ext_truncate(struct inode * inode)
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
-/* if (inode->i_data[7] & 0xffff0000)
- printk("BAD! ext inode has 16 high bits set\n"); */
while (1) {
flag = trunc_direct(inode);
flag |= trunc_indirect(inode,9,(unsigned long *)&inode->i_data[9]);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 7e61dd9..ed2decf 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -51,7 +51,8 @@ int sys_dup(unsigned int fildes)
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
-
+ extern int sock_fcntl (struct file *, unsigned int cmd,
+ unsigned long arg);
if (fd >= NR_OPEN || !(filp = current->filp[fd]))
return -EBADF;
switch (cmd) {
@@ -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:
return -ENOSYS;
default:
+ /* sockets need a few special fcntls. */
+ if (S_ISSOCK (filp->f_inode->i_mode))
+ {
+ return (sock_fcntl (filp, cmd, arg));
+ }
return -EINVAL;
}
}
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 57bed4b..ddf74f6 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -79,10 +79,15 @@ int minix_free_block(int dev, int block)
struct buffer_head * bh;
unsigned int bit,zone;
- if (!(sb = get_super(dev)))
- panic("trying to free block on nonexistent device");
- if (block < sb->u.minix_sb.s_firstdatazone || block >= sb->u.minix_sb.s_nzones)
- panic("trying to free block not in datazone");
+ if (!(sb = get_super(dev))) {
+ printk("trying to free block on nonexistent device\n");
+ return 1;
+ }
+ 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);
if (bh) {
if (bh->b_count > 1) {
@@ -110,8 +115,11 @@ int minix_new_block(int dev)
struct super_block * sb;
int i,j;
- if (!(sb = get_super(dev)))
- panic("trying to get new block from nonexistant device");
+ if (!(sb = get_super(dev))) {
+ printk("trying to get new block from nonexistant device\n");
+ return 0;
+ }
+repeat:
j = 8192;
for (i=0 ; i<8 ; i++)
if (bh=sb->u.minix_sb.s_zmap[i])
@@ -119,16 +127,22 @@ int minix_new_block(int dev)
break;
if (i>=8 || !bh || j>=8192)
return 0;
- if (set_bit(j,bh->b_data))
- panic("new_block: bit already set");
+ if (set_bit(j,bh->b_data)) {
+ printk("new_block: bit already set");
+ goto repeat;
+ }
bh->b_dirt = 1;
j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
if (j >= sb->u.minix_sb.s_nzones)
return 0;
- if (!(bh=getblk(dev,j,BLOCK_SIZE)))
- panic("new_block: cannot get block");
- if (bh->b_count != 1)
- panic("new block: count is != 1");
+ if (!(bh=getblk(dev,j,BLOCK_SIZE))) {
+ printk("new_block: cannot get block");
+ return 0;
+ }
+ if (bh->b_count != 1) {
+ printk("new block: count is != 1");
+ return 0;
+ }
clear_block(bh->b_data);
bh->b_uptodate = 1;
bh->b_dirt = 1;
diff --git a/fs/open.c b/fs/open.c
index 538f7ae..183b10c 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -14,7 +14,7 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/signal.h>
-
+#include <linux/tty.h>
#include <asm/segment.h>
struct file_operations * chrdev_fops[MAX_CHRDEV] = {
@@ -338,35 +338,132 @@ int sys_creat(const char * pathname, int mode)
return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
}
-int sys_close(unsigned int fd)
-{
- struct file * filp;
- struct inode * inode;
+static int
+close_fp (struct file *filp)
+{
+ 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) {
printk("Close: file count is 0\n");
return 0;
}
+
if (filp->f_count > 1) {
filp->f_count--;
return 0;
}
+
inode = filp->f_inode;
if (filp->f_op && filp->f_op->release)
filp->f_op->release(inode,filp);
+
filp->f_count--;
filp->f_inode = NULL;
iput(inode);
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);
}
+
diff --git a/include/linux/config.dist.h b/include/linux/config.dist.h
index 15b6e4b..816c8fc 100644
--- a/include/linux/config.dist.h
+++ b/include/linux/config.dist.h
@@ -1,5 +1,5 @@
-#ifndef _CONFIG_DIST_H
-#define _CONFIG_DIST_H
+#ifndef _LINUX_CONFIG_DIST_H
+#define _LINUX_CONFIG_DIST_H
#ifdef CONFIG_DISTRIBUTION
#undef CONFG_SCSI
diff --git a/include/linux/config.h b/include/linux/config.h
index ef79c38..7e95d8e 100644
--- a/include/linux/config.h
+++ b/include/linux/config.h
@@ -1,5 +1,5 @@
-#ifndef _CONFIG_H
-#define _CONFIG_H
+#ifndef _LINUX_CONFIG_H
+#define _LINUX_CONFIG_H
#define CONFIG_DISTRIBUTION
diff --git a/include/linux/config.site.h b/include/linux/config.site.h
index 49b731b..e478a03 100644
--- a/include/linux/config.site.h
+++ b/include/linux/config.site.h
@@ -1,5 +1,5 @@
-#ifndef _CONFIG_SITE_H
-#define _CONFIG_SITE_H
+#ifndef _LINUX_CONFIG_SITE_H
+#define _LINUX_CONFIG_SITE_H
/*
This configuration file contains site specific things, things
diff --git a/include/linux/ctype.h b/include/linux/ctype.h
index 7acf55d..838ef93 100644
--- a/include/linux/ctype.h
+++ b/include/linux/ctype.h
@@ -1,5 +1,5 @@
-#ifndef _CTYPE_H
-#define _CTYPE_H
+#ifndef _LINUX_CTYPE_H
+#define _LINUX_CTYPE_H
#define _U 0x01 /* upper */
#define _L 0x02 /* lower */
diff --git a/include/linux/ext_fs.h b/include/linux/ext_fs.h
index c4b3cf4..cfb3d10 100644
--- a/include/linux/ext_fs.h
+++ b/include/linux/ext_fs.h
@@ -1,28 +1,16 @@
-#ifndef _EXT_FS_H
-#define _EXT_FS_H
+#ifndef _LINUX_EXT_FS_H
+#define _LINUX_EXT_FS_H
/*
* 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_ROOT_INO 1
-#define EXT_I_MAP_SLOTS 8
-#define EXT_Z_MAP_SLOTS 8
#define EXT_SUPER_MAGIC 0x137D
#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 {
unsigned short i_mode;
@@ -49,16 +37,10 @@ struct ext_free_block {
struct ext_super_block {
unsigned long s_ninodes;
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_freeblockscount;
unsigned long s_firstfreeinode;
unsigned long s_freeinodescount;
-#endif
unsigned long s_firstdatazone;
unsigned long s_log_zone_size;
unsigned long s_max_size;
diff --git a/include/linux/ext_fs_sb.h b/include/linux/ext_fs_sb.h
index 8aff1ff..19004d8 100644
--- a/include/linux/ext_fs_sb.h
+++ b/include/linux/ext_fs_sb.h
@@ -2,18 +2,20 @@
#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 {
unsigned long s_ninodes;
unsigned long s_nzones;
- unsigned long s_imap_blocks;
- unsigned long s_zmap_blocks;
unsigned long s_firstdatazone;
unsigned long s_log_zone_size;
unsigned long s_max_size;
- struct buffer_head * s_imap[8];
- struct buffer_head * s_zmap[8];
+ unsigned long s_firstfreeblocknumber;
+ unsigned long s_freeblockscount;
+ struct buffer_head * s_firstfreeblock;
+ unsigned long s_firstfreeinodenumber;
+ unsigned long s_freeinodescount;
+ struct buffer_head * s_firstfreeinodeblock;
};
#endif
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index e477370..99361ed 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -1,5 +1,5 @@
-#ifndef _FCNTL_H
-#define _FCNTL_H
+#ifndef _LINUX_FCNTL_H
+#define _LINUX_FCNTL_H
/* open/fcntl - O_SYNC isn't implemented yet */
#define O_ACCMODE 0003
@@ -28,6 +28,9 @@
#define F_SETLK 6
#define F_SETLKW 7
+#define F_SETOWN 8 /* for sockets. */
+#define F_GETOWN 9 /* for sockets. */
+
/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 86cb92a..2c64bd4 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -225,7 +225,7 @@ extern struct file file_table[NR_FILE];
extern struct super_block super_block[NR_SUPER];
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_buffer_heads;
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index c1d1b4e..bacc130 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -1,5 +1,5 @@
-#ifndef _GENHD_H
-#define _GENHD_H
+#ifndef _LINUX_GENHD_H
+#define _LINUX_GENHD_H
/*
* genhd.h Copyright (C) 1992 Drew Eckhardt
diff --git a/include/linux/limits.h b/include/linux/limits.h
index 9b04df7..1de0388 100644
--- a/include/linux/limits.h
+++ b/include/linux/limits.h
@@ -7,14 +7,14 @@
#define NR_INODE 128
#define NR_FILE 128
#define NR_SUPER 8
-#define NR_HASH 307
+#define NR_HASH 997
#define BLOCK_SIZE 1024
#define BLOCK_SIZE_BITS 10
#define MAX_CHRDEV 16
#define MAX_BLKDEV 16
#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 OPEN_MAX 32 /* # open files a process may have */
#define LINK_MAX 127 /* # links a file may have */
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index 1205d6e..9ed0ebf 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -1,5 +1,5 @@
-#ifndef _MINIX_FS_H
-#define _MINIX_FS_H
+#ifndef _LINUX_MINIX_FS_H
+#define _LINUX_MINIX_FS_H
/*
* The minix filesystem constants/structures
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 256f032..a7b6af2 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1,11 +1,10 @@
-#ifndef _MM_H
-#define _MM_H
+#ifndef _LINUX_MM_H
+#define _LINUX_MM_H
#define PAGE_SIZE 4096
#include <linux/fs.h>
#include <linux/kernel.h>
-#include <linux/signal.h>
/*
* BAD_PAGE is the page that is used for page faults when linux
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 0eebbf4..c106f6f 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -1,5 +1,5 @@
-#ifndef _MSDOS_FS_H
-#define _MSDOS_FS_H
+#ifndef _LINUX_MSDOS_FS_H
+#define _LINUX_MSDOS_FS_H
/*
* The MS-DOS filesystem constants/structures
diff --git a/include/linux/param.h b/include/linux/param.h
index c864701..ec03686 100644
--- a/include/linux/param.h
+++ b/include/linux/param.h
@@ -1,12 +1,20 @@
-#ifndef _SYS_PARAM_H
-#define _SYS_PARAM_H
+#ifndef _LINUX_PARAM_H
+#define _LINUX_PARAM_H
+#ifndef HZ
#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
+#endif
-#define MAXHOSTNAMELEN 8
+#define MAXHOSTNAMELEN 64 /* max length of hostname */
#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 5de4d65..21a3fbb 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -221,6 +221,7 @@ extern struct task_struct *current;
extern unsigned long volatile jiffies;
extern unsigned long startup_time;
extern int jiffies_offset;
+extern int need_resched;
#define CURRENT_TIME (startup_time+(jiffies+jiffies_offset)/HZ)
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 24f098f..2886cd5 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -35,12 +35,13 @@ typedef unsigned int sigset_t; /* 32 bits */
* so they are commented out.
*/
-/*
+
#define SIGIO 23
#define SIGPOLL SIGIO
+#define SIGURG SIGIO
#define SIGXCPU 24
#define SIGXFSZ 25
-*/
+
#define SIGVTALRM 26
#define SIGPROF 27
@@ -60,12 +61,15 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIG_UNBLOCK 1 /* for unblocking signals */
#define SIG_SETMASK 2 /* for setting the signal mask */
-#define SIG_DFL ((void (*)(int))0) /* default signal handling */
-#define SIG_IGN ((void (*)(int))1) /* ignore signal */
-#define SIG_ERR ((void (*)(int))-1) /* error return from signal */
+/* Type of a signal handler. */
+typedef void (*__sighandler_t)(int);
+
+#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 {
- void (*sa_handler)(int);
+ __sighandler_t sa_handler;
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
diff --git a/include/linux/socket.h b/include/linux/socket.h
index e07703e..a0d3781 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -2,7 +2,7 @@
#define _LINUX_SOCKET_H
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 */
};
@@ -11,8 +11,9 @@ struct sockaddr {
*/
#define SOCK_STREAM 1 /* stream (connection) socket */
#define SOCK_DGRAM 2 /* datagram (connectionless) socket */
-#define SOCK_SEQPACKET 3 /* sequential packet socket */
-#define SOCK_RAW 4 /* raw socket */
+#define SOCK_RAW 3 /* raw socket */
+#define SOCK_RDM 4 /* reliably-delivered message */
+#define SOCK_SEQPACKET 5 /* sequential packet socket */
/*
* supported address families
@@ -27,4 +28,22 @@ struct sockaddr {
#define PF_UNIX AF_UNIX
#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 */
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 2e11b1c..3d8b4a9 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -1,6 +1,8 @@
#ifndef _LINUX_STAT_H
#define _LINUX_STAT_H
+#ifndef __NOT_KERNEL
+
struct old_stat {
unsigned short st_dev;
unsigned short st_ino;
@@ -38,6 +40,8 @@ struct new_stat {
unsigned long __unused5;
};
+#endif
+
#define S_IFMT 00170000
#define S_IFSOCK 0140000
#define S_IFLNK 0120000
diff --git a/include/linux/sys.h b/include/linux/sys.h
index deae36f..a479faa 100644
--- a/include/linux/sys.h
+++ b/include/linux/sys.h
@@ -114,6 +114,7 @@ extern int sys_newfstat();
extern int sys_newuname();
extern int sys_iopl();
extern int sys_vhangup();
+extern int sys_idle();
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,
@@ -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_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm,
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.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 84d6aa8..55d5bdd 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -22,6 +22,8 @@
* FLOPPY_TIMER floppy disk timer (not used right now)
*
* SCSI_TIMER scsi.c timeout timer
+ *
+ * NET_TIMER tcp/ip timeout timer
*/
#define BLANK_TIMER 0
@@ -40,6 +42,7 @@
#define HD_TIMER 16
#define FLOPPY_TIMER 17
#define SCSI_TIMER 18
+#define NET_TIMER 19
struct timer_struct {
unsigned long expires;
diff --git a/include/linux/times.h b/include/linux/times.h
index e7ae2fa..569349e 100644
--- a/include/linux/times.h
+++ b/include/linux/times.h
@@ -2,10 +2,10 @@
#define _LINUX_TIMES_H
struct tms {
- time_t tms_utime;
- time_t tms_stime;
- time_t tms_cutime;
- time_t tms_cstime;
+ clock_t tms_utime;
+ clock_t tms_stime;
+ clock_t tms_cutime;
+ clock_t tms_cstime;
};
#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index d6c1f6e..d06179e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -146,7 +146,9 @@ struct tty_struct {
struct termios termios;
int pgrp;
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 count;
struct winsize winsize;
diff --git a/include/linux/types.h b/include/linux/types.h
index 53088a2..a8c992a 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -23,7 +23,7 @@ typedef long clock_t;
#ifndef _PTRDIFF_T
#define _PTRDIFF_T
-typedef long ptrdiff_t;
+typedef int ptrdiff_t;
#endif
#ifndef NULL
@@ -65,9 +65,6 @@ typedef unsigned long tcflag_t;
typedef unsigned long fd_set;
-typedef struct { int quot,rem; } div_t;
-typedef struct { long quot,rem; } ldiv_t;
-
struct ustat {
daddr_t f_tfree;
ino_t f_tinode;
diff --git a/include/linux/un.h b/include/linux/un.h
index 5c41503..d04a907 100644
--- a/include/linux/un.h
+++ b/include/linux/un.h
@@ -2,8 +2,8 @@
#define _LINUX_UN_H
struct sockaddr_un {
- u_short sun_family; /* AF_UNIX */
+ unsigned short sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */
};
-#endif /* _UN_H */
+#endif /* _LINUX_UN_H */
diff --git a/include/linux/unistd.h b/include/linux/unistd.h
index 4675fbc..569c552 100644
--- a/include/linux/unistd.h
+++ b/include/linux/unistd.h
@@ -117,6 +117,8 @@
#define __NR_fstat 108
#define __NR_uname 109
#define __NR_iopl 110
+#define __NR_vhangup 111
+#define __NR_idle 112
extern int errno;
diff --git a/init/main.c b/init/main.c
index aec7bb7..704bd1e 100644
--- a/init/main.c
+++ b/init/main.c
@@ -18,6 +18,10 @@
#include <linux/head.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
* in NO COPY ON WRITE (!!!), until an execve is executed. This
@@ -30,6 +34,7 @@
* won't be any messing with the stack from main(), but we define
* some others too.
*/
+static inline _syscall0(int,idle)
static inline _syscall0(int,fork)
static inline _syscall0(int,pause)
static inline _syscall1(int,setup,void *,BIOS)
@@ -54,7 +59,6 @@ extern void init(void);
extern void init_IRQ(void);
extern long blk_dev_init(long,long);
extern long chr_dev_init(long,long);
-extern void hd_init(void);
extern void floppy_init(void);
extern void sock_init(void);
extern long rd_init(long mem_start, int length);
@@ -157,23 +161,28 @@ void start_kernel(void)
trap_init();
init_IRQ();
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 = blk_dev_init(memory_start,memory_end);
memory_start = mem_init(memory_start,memory_end);
buffer_init();
time_init();
printk("Linux version " UTS_RELEASE " " __DATE__ " " __TIME__ "\n");
- hd_init();
floppy_init();
sock_init();
sti();
#ifdef CONFIG_SCSI
scsi_dev_init();
#endif
+ sti();
move_to_user_mode();
- if (!fork()) { /* we count on this going ok */
+ if (!fork()) /* we count on this going ok */
init();
- }
/*
* 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
@@ -181,10 +190,10 @@ void start_kernel(void)
* anything that can be useful, but shouldn't take time from the real
* processes.
*
- * Right now task[0] just does a infinite loop in user mode.
+ * Right now task[0] just does a infinite idle loop.
*/
for(;;)
- /* nothing */ ;
+ idle();
}
static int printf(const char *fmt, ...)
diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c
index b1620d2..f8d7d21 100644
--- a/kernel/blk_drv/hd.c
+++ b/kernel/blk_drv/hd.c
@@ -593,7 +593,7 @@ static struct sigaction hd_sigaction = {
NULL
};
-void hd_init(void)
+unsigned long hd_init(unsigned long mem_start)
{
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
blkdev_fops[MAJOR_NR] = &hd_fops;
@@ -602,6 +602,7 @@ void hd_init(void)
if (irqaction(HD_IRQ,&hd_sigaction))
printk("Unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
timer_table[HD_TIMER].fn = hd_times_out;
+ return mem_start;
}
#endif
diff --git a/kernel/blk_drv/ll_rw_blk.c b/kernel/blk_drv/ll_rw_blk.c
index 0a7005b..1a5f640 100644
--- a/kernel/blk_drv/ll_rw_blk.c
+++ b/kernel/blk_drv/ll_rw_blk.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/config.h>
#include <asm/system.h>
@@ -299,6 +300,9 @@ long blk_dev_init(long mem_start, long mem_end)
request[i].next = NULL;
}
memset(ro_bits,0,sizeof(ro_bits));
+#ifdef CONFIG_BLK_DEV_HD
+ mem_start = hd_init(mem_start,mem_end);
+#endif
#ifdef RAMDISK
mem_start += rd_init(mem_start, RAMDISK*1024);
#endif
diff --git a/kernel/blk_drv/ramdisk.c b/kernel/blk_drv/ramdisk.c
index 195146d..8194b44 100644
--- a/kernel/blk_drv/ramdisk.c
+++ b/kernel/blk_drv/ramdisk.c
@@ -7,11 +7,11 @@
#include <linux/config.h>
#ifdef RAMDISK
-#include <linux/string.h>
#include <linux/sched.h>
#include <linux/minix_fs.h>
#include <linux/fs.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/memory.h>
diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c
index cff8124..4880d35 100644
--- a/kernel/chr_drv/console.c
+++ b/kernel/chr_drv/console.c
@@ -929,13 +929,13 @@ void con_write(struct tty_struct * tty)
* Control characters can be used in the _middle_
* of an escape sequence.
*/
- if (c < 32 || c == 127) switch(c) {
+ switch (c) {
case 7:
sysbeep();
- break;
+ continue;
case 8:
bs(currcons);
- break;
+ continue;
case 9:
pos -= (x << 1);
while (x < video_num_columns - 1) {
@@ -944,80 +944,84 @@ void con_write(struct tty_struct * tty)
break;
}
pos += (x << 1);
- break;
+ continue;
case 10: case 11: case 12:
lf(currcons);
if (!lfnlmode)
- break;
+ continue;
case 13:
cr(currcons);
- break;
+ continue;
case 14:
charset = 1;
translate = G1_charset;
- break;
+ continue;
case 15:
charset = 0;
translate = G0_charset;
- break;
+ continue;
case 24: case 26:
state = ESnormal;
- break;
+ continue;
case 27:
state = ESesc;
- break;
+ continue;
case 127:
del(currcons);
- break;
- } else switch(state) {
+ continue;
+ case 128+27:
+ state = ESsquare;
+ continue;
+ }
+ switch(state) {
case ESesc:
state = ESnormal;
switch (c) {
case '[':
state = ESsquare;
- break;
+ continue;
case 'E':
cr(currcons);
lf(currcons);
- break;
+ continue;
case 'M':
ri(currcons);
- break;
+ continue;
case 'D':
lf(currcons);
- break;
+ continue;
case 'H':
tab_stop[x >> 5] |= (1 << (x & 31));
- break;
+ continue;
case 'Z':
respond_ID(currcons,tty);
- break;
+ continue;
case '7':
save_cur(currcons);
- break;
+ continue;
case '8':
restore_cur(currcons);
- break;
+ continue;
case '(':
state = ESsetG0;
- break;
+ continue;
case ')':
state = ESsetG1;
- break;
+ continue;
case '#':
state = EShash;
- break;
+ continue;
case 'c':
reset_terminal(currcons,1);
- break;
+ continue;
case '>': /* Numeric keypad */
SET(kbdapplic,kapplic,0);
- break;
+ continue;
case '=': /* Appl. keypad */
SET(kbdapplic,kapplic,1);
- break;
+ continue;
}
- break;
+ continue;
case ESsquare:
for(npar = 0 ; npar < NPAR ; npar++)
par[npar] = 0;
@@ -1025,97 +1029,97 @@ void con_write(struct tty_struct * tty)
state = ESgetpars;
if (c == '[') { /* Function key */
state=ESfunckey;
- break;
+ continue;
}
if (ques=(c=='?'))
- break;
+ continue;
case ESgetpars:
if (c==';' && npar<NPAR-1) {
npar++;
- break;
+ continue;
} else if (c>='0' && c<='9') {
par[npar] *= 10;
par[npar] += c-'0';
- break;
+ continue;
} else state=ESgotpars;
case ESgotpars:
state = ESnormal;
switch(c) {
case 'h':
set_mode(currcons,1);
- break;
+ continue;
case 'l':
set_mode(currcons,0);
- break;
+ continue;
case 'n':
if (!ques)
if (par[0] == 5)
status_report(currcons,tty);
else if (par[0] == 6)
cursor_report(currcons,tty);
- break;
+ continue;
}
if (ques) {
ques = 0;
- break;
+ continue;
}
switch(c) {
case 'G': case '`':
if (par[0]) par[0]--;
gotoxy(currcons,par[0],y);
- break;
+ continue;
case 'A':
if (!par[0]) par[0]++;
gotoxy(currcons,x,y-par[0]);
- break;
+ continue;
case 'B': case 'e':
if (!par[0]) par[0]++;
gotoxy(currcons,x,y+par[0]);
- break;
+ continue;
case 'C': case 'a':
if (!par[0]) par[0]++;
gotoxy(currcons,x+par[0],y);
- break;
+ continue;
case 'D':
if (!par[0]) par[0]++;
gotoxy(currcons,x-par[0],y);
- break;
+ continue;
case 'E':
if (!par[0]) par[0]++;
gotoxy(currcons,0,y+par[0]);
- break;
+ continue;
case 'F':
if (!par[0]) par[0]++;
gotoxy(currcons,0,y-par[0]);
- break;
+ continue;
case 'd':
if (par[0]) par[0]--;
gotoxy(currcons,x,par[0]);
- break;
+ continue;
case 'H': case 'f':
if (par[0]) par[0]--;
if (par[1]) par[1]--;
gotoxy(currcons,par[1],par[0]);
- break;
+ continue;
case 'J':
csi_J(currcons,par[0]);
- break;
+ continue;
case 'K':
csi_K(currcons,par[0]);
- break;
+ continue;
case 'L':
csi_L(currcons,par[0]);
- break;
+ continue;
case 'M':
csi_M(currcons,par[0]);
- break;
+ continue;
case 'P':
csi_P(currcons,par[0]);
- break;
+ continue;
case 'c':
if (!par[0])
respond_ID(currcons,tty);
- break;
+ continue;
case 'g':
if (!par[0])
tab_stop[x >> 5] &= ~(1 << (x & 31));
@@ -1126,10 +1130,10 @@ void con_write(struct tty_struct * tty)
tab_stop[3] =
tab_stop[4] = 0;
}
- break;
+ continue;
case 'm':
csi_m(currcons);
- break;
+ continue;
case 'r':
if (!par[0])
par[0]++;
@@ -1142,24 +1146,24 @@ void con_write(struct tty_struct * tty)
bottom=par[1];
gotoxy(currcons,0,0);
}
- break;
+ continue;
case 's':
save_cur(currcons);
- break;
+ continue;
case 'u':
restore_cur(currcons);
- break;
+ continue;
case '@':
csi_at(currcons,par[0]);
- break;
+ continue;
case ']': /* setterm functions */
setterm_command(currcons);
- break;
+ continue;
}
- break;
+ continue;
case ESfunckey:
state = ESnormal;
- break;
+ continue;
case EShash:
state = ESnormal;
if (c == '8') {
@@ -1170,7 +1174,7 @@ void con_write(struct tty_struct * tty)
video_erase_char =
(video_erase_char & 0xff00) | ' ';
}
- break;
+ continue;
case ESsetG0:
if (c == '0')
G0_charset = GRAF_TRANS;
@@ -1181,7 +1185,7 @@ void con_write(struct tty_struct * tty)
if (charset == 0)
translate = G0_charset;
state = ESnormal;
- break;
+ continue;
case ESsetG1:
if (c == '0')
G1_charset = GRAF_TRANS;
@@ -1192,7 +1196,7 @@ void con_write(struct tty_struct * tty)
if (charset == 1)
translate = G1_charset;
state = ESnormal;
- break;
+ continue;
default:
state = ESnormal;
}
diff --git a/kernel/chr_drv/mouse.c b/kernel/chr_drv/mouse.c
index 396e6c2..f042be6 100644
--- a/kernel/chr_drv/mouse.c
+++ b/kernel/chr_drv/mouse.c
@@ -83,14 +83,12 @@ static int open_mouse(struct inode * inode, struct file * file)
mouse.dx = 0;
mouse.dy = 0;
mouse.buttons = mouse.latch_buttons = 0x80;
- MSE_INT_ON();
if (request_irq(MOUSE_IRQ, mouse_interrupt)) {
- MSE_INT_OFF();
- mouse.active = 0;
- mouse.ready = 0;
- mouse.inode = NULL;
- return -EBUSY;
- }
+ /* once we get to here mouse is unused, IRQ is busy */
+ mouse.active = 0; /* it's not active, fix it */
+ return -EBUSY; /* IRQ is busy, so we're BUSY */
+ } /* if we can't get the IRQ and mouse not active */
+ MSE_INT_ON();
return 0;
}
diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c
index 67d4153..7b65584 100644
--- a/kernel/chr_drv/tty_io.c
+++ b/kernel/chr_drv/tty_io.c
@@ -201,11 +201,15 @@ void copy_to_cooked(struct tty_struct * tty)
if (I_IXON(tty)) {
if ((STOP_CHAR(tty) != __DISABLED_CHAR) &&
(c==STOP_CHAR(tty))) {
+ tty->status_changed = 1;
+ tty->ctrl_status |= TIOCPKT_STOP;
tty->stopped=1;
continue;
}
if ((START_CHAR(tty) != __DISABLED_CHAR) &&
(c==START_CHAR(tty))) {
+ tty->status_changed = 1;
+ tty->ctrl_status |= TIOCPKT_START;
tty->stopped=0;
continue;
}
@@ -338,10 +342,32 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n
}
if (file->f_flags & O_NONBLOCK)
time = current->timeout = 0;
- else if (L_CANON(tty))
+ else if (L_CANON(tty)) {
wait_for_canon_input(tty);
+ if (current->signal & ~current->blocked)
+ return -ERESTARTSYS;
+ }
if (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) {
TTY_READ_FLUSH(tty);
if (tty->link)
@@ -379,8 +405,20 @@ static int read_chan(unsigned int channel, struct file * file, char * buf, int n
if (tty->link && tty->link->write)
TTY_WRITE_FLUSH(tty->link);
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)
return -ERESTARTSYS;
if (file->f_flags & O_NONBLOCK)
@@ -523,9 +561,20 @@ static int tty_open(struct inode * inode, struct file * filp)
return -EAGAIN;
if (tty->link)
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++;
retval = 0;
+
+ /* clean up the packet stuff. */
+ tty->status_changed = 0;
+ tty->ctrl_status = 0;
+ tty->packet = 0;
+
if (!(filp->f_flags & O_NOCTTY) &&
current->leader &&
current->tty<0 &&
@@ -598,6 +647,12 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se
return 1;
if (tty->link && !tty->link->count)
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);
return 0;
case SEL_OUT:
@@ -639,7 +694,7 @@ long tty_init(long kmem_start)
for (i=0 ; i<256 ; i++) {
tty_table[i] = (struct tty_struct) {
{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
};
}
@@ -655,6 +710,10 @@ long tty_init(long kmem_start)
-1, /* initial pgrp */
0, /* initial session */
0, /* initial stopped */
+ 0, /* initial status_changed */
+ 0, /* initial packet */
+ 0, /* initial ctrl_status */
+ 0, /* initial unused */
0, /* initial flags */
0, /* initial count */
{video_num_lines,video_num_columns,0,0},
@@ -673,7 +732,7 @@ long tty_init(long kmem_start)
INIT_C_CC},
-1,
0,
- 0,
+ 0, 0, 0, 0, 0,
0,
0,
{25,80,0,0},
@@ -692,7 +751,7 @@ long tty_init(long kmem_start)
INIT_C_CC},
-1,
0,
- 0,
+ 0, 0, 0, 0, 0,
0,
0,
{25,80,0,0},
@@ -709,7 +768,7 @@ long tty_init(long kmem_start)
INIT_C_CC},
-1,
0,
- 0,
+ 0, 0, 0, 0, 0,
0,
0,
{25,80,0,0},
diff --git a/kernel/chr_drv/tty_ioctl.c b/kernel/chr_drv/tty_ioctl.c
index eb213ac..5212b50 100644
--- a/kernel/chr_drv/tty_ioctl.c
+++ b/kernel/chr_drv/tty_ioctl.c
@@ -33,6 +33,8 @@ static void flush(struct tty_queue * queue)
void flush_input(struct tty_struct * tty)
{
+ tty->status_changed = 1;
+ tty->ctrl_status |= TIOCPKT_FLUSHREAD;
if (tty->read_q) {
flush(tty->read_q);
wake_up(&tty->read_q->proc_list);
@@ -49,6 +51,8 @@ void flush_input(struct tty_struct * tty)
void flush_output(struct tty_struct * tty)
{
+ tty->status_changed = 1;
+ tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
if (tty->write_q) {
flush(tty->write_q);
wake_up(&tty->write_q->proc_list);
@@ -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);
if (IS_A_SERIAL(channel) && tty->termios.c_cflag != old_cflag)
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;
}
@@ -179,6 +189,22 @@ static int set_termio(struct tty_struct * tty, struct termio * termio,
}
for (i=0 ; i< (sizeof (*termio)) ; i++)
((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_oflag = tmp_termio.c_oflag;
*(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
@@ -408,6 +434,21 @@ int tty_ioctl(struct inode * inode, struct file * file,
tty->session = 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:
return vt_ioctl(tty, dev, cmd, arg);
}
diff --git a/kernel/exit.c b/kernel/exit.c
index b31e90e..8cc5451 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -203,6 +203,30 @@ int kill_pg(int pgrp, int sig, int priv)
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)
{
struct task_struct **p;
diff --git a/kernel/sched.c b/kernel/sched.c
index 208aefb..1e8a710 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -29,6 +29,9 @@
int need_resched = 0;
+unsigned long * prof_buffer = NULL;
+unsigned long prof_len = 0;
+
#define _S(nr) (1<<((nr)-1))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
@@ -157,12 +160,14 @@ void schedule(void)
if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
c = (*p)->counter, next = i;
}
- if (c) break;
+ if (c)
+ break;
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p)
(*p)->counter = ((*p)->counter >> 1) +
(*p)->priority;
}
+ sti();
switch_to(next);
}
@@ -396,21 +401,29 @@ static void do_timer(int regs)
static int avg_cnt = 0;
jiffies++;
- if (3 & ((struct pt_regs *) regs)->cs)
+ if (3 & ((struct pt_regs *) regs)->cs) {
current->utime++;
- else {
- current->stime++;
/* Update ITIMER_VIRT for current task if not in a system call */
if (current->it_virt_value && !(--current->it_virt_value)) {
current->it_virt_value = current->it_virt_incr;
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) {
avg_cnt = 500;
update_avg();
}
- if ((--current->counter)<=0) {
+ if (current == task[0] || (--current->counter)<=0) {
current->counter=0;
need_resched = 1;
}
diff --git a/kernel/sys_call.S b/kernel/sys_call.S
index 735a795..44c0723 100644
--- a/kernel/sys_call.S
+++ b/kernel/sys_call.S
@@ -12,6 +12,9 @@
* NOTE: This code handles signal-recognition, which happens every time
* 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':
* ptrace needs to have all regs on the stack.
* if the order here is changed, it needs to be
@@ -75,10 +78,6 @@ sa_restorer = 12
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 _device_not_available, _coprocessor_error
.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
@@ -107,11 +106,11 @@ ENOSYS = 38
movl $0x17,%edx; \
mov %dx,%fs
-.align 2
+.align 4
reschedule:
pushl $ret_from_sys_call
jmp _schedule
-.align 2
+.align 4
_system_call:
pushl %eax # save orig_eax
SAVE_ALL
@@ -120,6 +119,7 @@ _system_call:
jae ret_from_sys_call
call _sys_call_table(,%eax,4)
movl %eax,EAX(%esp) # save the return value
+ .align 4,0x90
ret_from_sys_call:
cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
jne 2f
@@ -128,14 +128,12 @@ ret_from_sys_call:
1: cmpl $0,_need_resched
jne reschedule
movl _current,%eax
+ cmpl _task,%eax # task[0] cannot have signals
+ je 2f
cmpl $0,state(%eax) # state
jne reschedule
cmpl $0,counter(%eax) # counter
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 blocked(%eax),%ecx
notl %ecx
@@ -167,7 +165,7 @@ ret_from_sys_call:
addl $4,%esp # skip the orig_eax
iret
-.align 2
+.align 4
_sys_execve:
lea (EIP+4)(%esp),%eax # don't forget about the return address.
pushl %eax
@@ -175,9 +173,11 @@ _sys_execve:
addl $4,%esp
ret
+.align 4
_divide_error:
pushl $0 # no error code
pushl $_do_divide_error
+.align 4,0x90
error_code:
push %fs
push %es
@@ -207,13 +207,13 @@ error_code:
addl $8,%esp
jmp ret_from_sys_call
-.align 2
+.align 4
_coprocessor_error:
pushl $0
pushl $_do_coprocessor_error
jmp error_code
-.align 2
+.align 4
_device_not_available:
pushl $-1 # mark this as an int
SAVE_ALL
@@ -227,70 +227,85 @@ _device_not_available:
addl $4,%esp
ret
+.align 4
_debug:
pushl $0
pushl $_do_debug
jmp error_code
+.align 4
_nmi:
pushl $0
pushl $_do_nmi
jmp error_code
+.align 4
_int3:
pushl $0
pushl $_do_int3
jmp error_code
+.align 4
_overflow:
pushl $0
pushl $_do_overflow
jmp error_code
+.align 4
_bounds:
pushl $0
pushl $_do_bounds
jmp error_code
+.align 4
_invalid_op:
pushl $0
pushl $_do_invalid_op
jmp error_code
+.align 4
_coprocessor_segment_overrun:
pushl $0
pushl $_do_coprocessor_segment_overrun
jmp error_code
+.align 4
_reserved:
pushl $0
pushl $_do_reserved
jmp error_code
+.align 4
_double_fault:
pushl $_do_double_fault
jmp error_code
+.align 4
_invalid_TSS:
pushl $_do_invalid_TSS
jmp error_code
+.align 4
_segment_not_present:
pushl $_do_segment_not_present
jmp error_code
+.align 4
_stack_segment:
pushl $_do_stack_segment
jmp error_code
+.align 4
_general_protection:
pushl $_do_general_protection
jmp error_code
+.align 4
_alignment_check:
pushl $_do_alignment_check
jmp error_code
+.align 4
_page_fault:
pushl $_do_page_fault
jmp error_code
diff --git a/mm/memory.c b/mm/memory.c
index 209641e..1595b4f 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -41,7 +41,7 @@ current->start_code + current->end_code)
unsigned long low_memory = 0;
unsigned long high_memory = 0;
-unsigned long paging_pages = 0;
+unsigned long free_page_list = 0;
#define copy_page(from,to) \
__asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")
@@ -71,14 +71,16 @@ void free_page(unsigned long addr)
if (addr < low_memory)
return;
- if (addr < high_memory) {
- i = addr - low_memory;
- i >>= 12;
- if (mem_map[i] == 1)
- ++nr_free_pages;
- if (mem_map[i]--)
+ i = addr - low_memory;
+ i >>= 12;
+ if (addr < high_memory && mem_map[i]) {
+ if (--mem_map[i])
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);
}
@@ -170,7 +172,7 @@ int copy_page_tables(unsigned long from,unsigned long to,long size)
from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
if (!(to_page_table = (unsigned long *) get_free_page(GFP_KERNEL)))
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;
for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
repeat:
@@ -187,7 +189,7 @@ repeat:
goto repeat;
}
*to_page_table = this_page;
- *from_page_table = new_page | (PAGE_DIRTY | 7);
+ *from_page_table = new_page | (PAGE_DIRTY | PAGE_ACCESSED | 7);
continue;
}
this_page &= ~2;
@@ -294,7 +296,7 @@ int remap_page_range(unsigned long from, unsigned long to, unsigned long size,
invalidate();
return -1;
}
- *dir++ = ((unsigned long) page_table) | 7;
+ *dir++ = ((unsigned long) page_table) | PAGE_ACCESSED | 7;
}
else
page_table = (unsigned long *)(0xfffff000 & *dir++);
@@ -384,7 +386,7 @@ static unsigned long put_page(unsigned long page,unsigned long address)
oom(current);
tmp = BAD_PAGETABLE;
}
- *page_table = tmp | 7;
+ *page_table = tmp | PAGE_ACCESSED | 7;
return 0;
}
page_table += (address>>12) & 0x3ff;
@@ -393,7 +395,7 @@ static unsigned long put_page(unsigned long page,unsigned long address)
*page_table = 0;
invalidate();
}
- *page_table = page | 7;
+ *page_table = page | PAGE_ACCESSED | 7;
/* no need for invalidate */
return page;
}
@@ -429,7 +431,7 @@ unsigned long put_dirty_page(unsigned long page, unsigned long address)
*page_table = 0;
invalidate();
}
- *page_table = page | (PAGE_DIRTY | 7);
+ *page_table = page | (PAGE_DIRTY | PAGE_ACCESSED | 7);
/* no need for invalidate */
return page;
}
@@ -472,7 +474,7 @@ repeat:
new_page = BAD_PAGE;
send_sig(SIGSEGV,task,1);
}
- *table_entry = new_page | dirty | 7;
+ *table_entry = new_page | dirty | PAGE_ACCESSED | 7;
free_page(old_page);
invalidate();
}
@@ -580,7 +582,7 @@ static int try_to_share(unsigned long address, struct task_struct * p)
to = get_free_page(GFP_KERNEL);
if (!to)
return 0;
- *(unsigned long *) to_page = to | 7;
+ *(unsigned long *) to_page = to | PAGE_ACCESSED | 7;
}
to &= 0xfffff000;
to_page = to + ((address>>10) & 0xffc);
@@ -650,7 +652,7 @@ repeat:
*p = 0;
}
if (page) {
- *p = page | 7;
+ *p = page | PAGE_ACCESSED | 7;
return *p;
}
if (page = get_free_page(GFP_KERNEL))
@@ -764,7 +766,8 @@ void show_mem(void)
printk("Free pages: %6d\n",nr_free_pages);
printk("Buffer heads: %6d\n",nr_buffer_heads);
printk("Buffer blocks: %6d\n",nr_buffers);
- for (i = 0 ; i < paging_pages ; i++) {
+ i = (high_memory - low_memory) >> 12;
+ while (i-- > 0) {
total++;
if (!mem_map[i])
free++;
@@ -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 tmp;
+
end_mem &= 0xfffff000;
high_memory = end_mem;
mem_map = (char *) start_mem;
- paging_pages = (end_mem - start_mem) >> 12;
- start_mem += paging_pages;
+ tmp = (end_mem - start_mem) >> 12;
+ start_mem += tmp;
start_mem += 0xfff;
start_mem &= 0xfffff000;
low_memory = start_mem;
- paging_pages = (high_memory - low_memory) >> 12;
+ tmp = (high_memory - low_memory) >> 12;
swap_device = 0;
swap_file = NULL;
- memset(mem_map,0,paging_pages);
- nr_free_pages = paging_pages;
+ memset(mem_map,0,tmp);
+ 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;
}
diff --git a/mm/swap.c b/mm/swap.c
index b582eb4..cc95a72 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -20,6 +20,8 @@
static int lowest_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...
*/
@@ -150,6 +152,9 @@ int try_to_swap_out(unsigned long * table_ptr)
page = *table_ptr;
if (!(PAGE_PRESENT & page))
return 0;
+ *table_ptr &= ~PAGE_ACCESSED;
+ if (PAGE_ACCESSED & page)
+ return 0;
if (page < low_memory || page >= high_memory)
return 0;
for (i = 0; i < NR_LAST_FREE_PAGES; i++)
@@ -182,6 +187,40 @@ int try_to_swap_out(unsigned long * table_ptr)
#define LAST_VM_PAGE (1024*1024)
#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
* we can swap out.
@@ -190,11 +229,9 @@ int try_to_swap_out(unsigned long * table_ptr)
* is un-swappable), allowing high-priority processes which cannot be
* 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;
- static int page_entry = -1;
- int counter = VM_PAGES;
+ int counter = VM_PAGES / 2;
int pg_table;
struct task_struct * p;
@@ -203,7 +240,7 @@ check_dir:
goto no_swap;
if (dir_entry >= 1024)
dir_entry = FIRST_VM_PAGE>>10;
- if (!(p = task[dir_entry >> 4])) {
+ if (!(p = task[dir_entry >> 4]) || !p->swappable) {
counter -= 1024;
dir_entry++;
goto check_dir;
@@ -222,24 +259,41 @@ check_dir:
check_table:
if (counter < 0)
goto no_swap;
- counter--;
- page_entry++;
if (page_entry >= 1024) {
- page_entry = -1;
+ page_entry = 0;
dir_entry++;
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--;
- dir_entry++;
return 1;
}
+ page_entry++;
+ counter--;
goto check_table;
no_swap:
- printk("Out of swap-memory\n\r");
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
* used. If no free pages left, return 0.
@@ -250,29 +304,24 @@ unsigned long get_free_page(int priority)
static unsigned long index = 0;
repeat:
- __asm__("std ; repne ; scasb\n\t"
- "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;
- }
+ result = free_page_list;
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)
index = 0;
last_free_pages[index] = result;
@@ -286,11 +335,7 @@ repeat:
}
if (priority <= GFP_BUFFER)
return 0;
- if (shrink_buffers()) {
- schedule();
- goto repeat;
- }
- if (swap_out()) {
+ if (try_to_free_page()) {
schedule();
goto repeat;
}
diff --git a/net/Makefile b/net/Makefile
index daada70..72a28e1 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -7,17 +7,27 @@
#
# 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:
- $(CC) $(CFLAGS) -c $<
+ $(CC) $(CFLAGS) $(SOCK_FLAGS) -c $<
.s.o:
$(AS) -o $*.o $<
.c.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:
rm -f core *.o *.a tmp_make
@@ -27,6 +37,9 @@ dep:
sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
for i in *.c;do $(CPP) -M $$i;done >> tmp_make
cp tmp_make Makefile
+ @for i in $(SUBDIRS); do (cd $$i; echo $$i; $(MAKE) dep || exit; done
+
+dummy:
### Dependencies:
socket.o : socket.c /usr/src/linux/include/linux/signal.h /usr/src/linux/include/linux/errno.h \
diff --git a/net/kern_sock.h b/net/kern_sock.h
index ccbd5e4..ac6f433 100644
--- a/net/kern_sock.h
+++ b/net/kern_sock.h
@@ -1,6 +1,6 @@
#ifndef _KERN_SOCK_H
#define _KERN_SOCK_H
-
+#undef SOCK_DEBUG
#define NSOCKETS 128 /* should be dynamic, later... */
typedef enum {
@@ -29,7 +29,7 @@ struct socket {
socket_state state;
long flags;
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 *iconn; /* incomplete client connections */
struct socket *next;
@@ -45,15 +45,31 @@ struct proto_ops {
int (*bind)(struct socket *sock, struct sockaddr *umyaddr,
int sockaddr_len);
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 (*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 *usockaddr_len, int peer);
int (*read)(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 (*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);
diff --git a/net/socket.c b/net/socket.c
index ffea8a2..3652226 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1,3 +1,4 @@
+/* modified by Ross Biro to help support inet sockets. */
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/sched.h>
@@ -16,13 +17,19 @@
extern int sys_close(int fd);
extern struct proto_ops unix_proto_ops;
+#ifdef INET_SOCKETS
+extern struct proto_ops inet_proto_ops;
+#endif
static struct {
short family;
char *name;
struct proto_ops *ops;
} 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]))
@@ -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");
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);
}
@@ -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");
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.
*/
@@ -555,6 +535,8 @@ sock_listen(int fd, int backlog)
PRINTK("sys_listen: socket already accepting connections!\n");
return -EINVAL;
}
+ if (sock->ops && sock->ops->listen)
+ sock->ops->listen (sock, backlog);
sock->flags |= SO_ACCEPTCON;
return 0;
}
@@ -567,7 +549,7 @@ static int
sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
{
struct file *file;
- struct socket *sock, *clientsock, *newsock;
+ struct socket *sock, *newsock;
int i;
PRINTK("sys_accept: fd = %d\n", fd);
@@ -582,20 +564,6 @@ sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
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))) {
printk("sys_accept: no more sockets\n");
return -EINVAL;
@@ -611,24 +579,20 @@ sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
sock_release(newsock);
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)
newsock->ops->getname(newsock, upeer_sockaddr,
upeer_addrlen, 1);
- wake_up(clientsock->wait);
return fd;
}
@@ -640,16 +604,18 @@ static int
sock_connect(int fd, struct sockaddr *uservaddr, int addrlen)
{
struct socket *sock;
+ struct file *file;
int i;
PRINTK("sys_connect: fd = %d\n", fd);
- if (!(sock = sockfd_lookup(fd, NULL)))
+ if (!(sock = sockfd_lookup(fd, &file)))
return -EBADF;
if (sock->state != SS_UNCONNECTED) {
PRINTK("sys_connect: socket not unconnected\n");
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");
return i;
}
@@ -678,6 +644,168 @@ sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
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
* 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)
get_fs_long(args+2),
(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:
return -EINVAL;
}
diff --git a/net/socketcall.h b/net/socketcall.h
index 4b48562..29fd1ae 100644
--- a/net/socketcall.h
+++ b/net/socketcall.h
@@ -9,5 +9,12 @@
#define SYS_GETSOCKNAME 6
#define SYS_GETPEERNAME 7
#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_
diff --git a/net/unix.c b/net/unix.c
index 8e956b5..b0a2f10 100644
--- a/net/unix.c
+++ b/net/unix.c
@@ -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,
int sockaddr_len);
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_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,
int *usockaddr_len, int peer);
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,
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,
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 = {
unix_proto_init,
@@ -72,7 +91,16 @@ struct proto_ops unix_proto_ops = {
unix_proto_read,
unix_proto_write,
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
@@ -94,6 +122,68 @@ sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
}
}
#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 *
unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
@@ -282,7 +372,7 @@ unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
*/
static int
unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
- int sockaddr_len)
+ int sockaddr_len, int flags)
{
int i;
struct unix_proto_data *serv_upd;
@@ -337,11 +427,39 @@ unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
* on accept, we ref the peer's data for safe writes
*/
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",
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);
return 0;
}
@@ -525,6 +643,23 @@ unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
{
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) {
upd = UN_DATA(sock);
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)
peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
switch (cmd) {
+
case TIOCINQ:
+ if (sock->flags & SO_ACCEPTCON)
+ return -EINVAL;
verify_area((void *)arg, sizeof(unsigned long));
if (UN_BUF_AVAIL(upd) || peerupd)
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)
break;
case TIOCOUTQ:
+ if (sock->flags & SO_ACCEPTCON)
+ return -EINVAL;
verify_area((void *)arg, sizeof(unsigned long));
if (peerupd)
put_fs_long(UN_BUF_SPACE(peerupd),