]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Linux-0.97.1 (August 6, 1992) 0.97.1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:04 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:04 +0000 (15:09 -0500)
Make the page allocator use a free page list instead of a silly
linear search.

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

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

[Original announcement below]

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

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

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

                Linus

54 files changed:
Makefile
fs/buffer.c
fs/ext/Makefile
fs/ext/dir.c
fs/ext/freelists.c
fs/ext/inode.c
fs/ext/namei.c
fs/ext/truncate.c
fs/fcntl.c
fs/minix/bitmap.c
fs/open.c
include/linux/config.dist.h
include/linux/config.h
include/linux/config.site.h
include/linux/ctype.h
include/linux/ext_fs.h
include/linux/ext_fs_sb.h
include/linux/fcntl.h
include/linux/fs.h
include/linux/genhd.h
include/linux/limits.h
include/linux/minix_fs.h
include/linux/mm.h
include/linux/msdos_fs.h
include/linux/param.h
include/linux/sched.h
include/linux/signal.h
include/linux/socket.h
include/linux/stat.h
include/linux/sys.h
include/linux/timer.h
include/linux/times.h
include/linux/tty.h
include/linux/types.h
include/linux/un.h
include/linux/unistd.h
init/main.c
kernel/blk_drv/hd.c
kernel/blk_drv/ll_rw_blk.c
kernel/blk_drv/ramdisk.c
kernel/chr_drv/console.c
kernel/chr_drv/mouse.c
kernel/chr_drv/tty_io.c
kernel/chr_drv/tty_ioctl.c
kernel/exit.c
kernel/sched.c
kernel/sys_call.S
mm/memory.c
mm/swap.c
net/Makefile
net/kern_sock.h
net/socket.c
net/socketcall.h
net/unix.c

index 39e87db0cbb3ec4dd53e560292698249f1dc1525..d143eacc53319bb8ca611ac30038f9048d29065a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,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:
 #
@@ -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
index f8efd1f1740cf593c7345e3930a25f6bdd5b302f..b8604bebc3a9a382521d3b821b05a6764e81d933 100644 (file)
@@ -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);
index 43fc4e12bd46868227c4e2d4bb806f2a59646a53..d5e994f50d5be6ae1ddccad00c456094d40f987b 100644 (file)
@@ -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)
index 54bc7ad0e2b2b472c597b8696a6113106a657655..48cefa2845b47a53c09ddd0349a67f7da04112d8 100644 (file)
@@ -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);
        }
index e39f442711c4199ad7afb6afd77951ed7d984b0e..454796ca982bc01c08b6748341b4f290b465a60d 100644 (file)
    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
index dae86aeeee28637866f26e9bdfc2f2685596d5e9..67ed5233a12f3a169ab33dc08cfc474be7d4142a 100644 (file)
@@ -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) +
index bea8dc0f0b01c9e2e75657242bd2922b77e28210..9ddf729c3b5f6aae7479cc9c91ab4b7cdb5058ac 100644 (file)
@@ -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.
index 3e647e8adfbf417e31c67b7940b2d0d2a1a92d3a..c32a0912b36ba7105f82eb499642c600fcaa3279 100644 (file)
@@ -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]);
index 7e61dd94b2bcc7fbcae67224254d264611ef72f2..ed2decff70c074d5511a75711f15ffc2ef39a083 100644 (file)
@@ -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;
        }
 }
index 57bed4ba9438f7bc5ee8f21905fcb7a660665f48..ddf74f616528b498d4f7dcf3745d8f28c34249ea 100644 (file)
@@ -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;
index 538f7ae11bfb8dc015d5e8d68dc3a9f81a52e305..183b10cbe74f122c5188e7117750e35235bb03e3 100644 (file)
--- 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);
 }
+
index 15b6e4be4167b70be1c2fb35e12f0f97cf8209d2..816c8fc28648908af709145d8a22eac24672bd18 100644 (file)
@@ -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
index ef79c388ae939833667e7a5773976bf93084dd14..7e95d8e2c5240c2c571ad950d3d30507738a1065 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _CONFIG_H
-#define _CONFIG_H
+#ifndef _LINUX_CONFIG_H
+#define _LINUX_CONFIG_H
 
 #define CONFIG_DISTRIBUTION
 
index 49b731bb0499920d9ba125aa26d55b09fa282568..e478a0305392b557200a6512e180424c8e32a828 100644 (file)
@@ -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 
index 7acf55d10e427ce64361a93c0f7660fa7d5a8ff5..838ef933d16c574caa4c7e931df7e6cce1bc7e83 100644 (file)
@@ -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 */
index c4b3cf435d360b8ec4c7c3b9e3ea973da161f681..cfb3d1077c4e0992dedb798d7f46c80d1d05e49f 100644 (file)
@@ -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;
index 8aff1ff8e364ed5616cab99c1a6ae2a9055a2e19..19004d80f15ed5a6cf75dabeb368c6d7b4fb0cb4 100644 (file)
@@ -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
index e4773700047aed70a1a1146f92b55e2a93b00d41..99361ed778d7ed2366b20fd1c13791ece22b3d65 100644 (file)
@@ -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 */
 
index 86cb92ab6d71af4359f96fda99c9444ad124a5a2..2c64bd4b02ad8ce21cc00ff49254c5e16422e4b5 100644 (file)
@@ -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;
index c1d1b4ed3f918e4fb64a1dabb9eba96047cf0a56..bacc130589aea95cd7957cb398ca73dfc9e4e73e 100644 (file)
@@ -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
index 9b04df71454d590bdea91281fb2e44eef7f328f7..1de038822b999b40d0458fdaab83abe6ca238c0d 100644 (file)
@@ -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 */
index 1205d6e2a61e47b775773a421132a95057d6fefb..9ed0ebfdd96622978f2a878bba0793cd9dbf7ae5 100644 (file)
@@ -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
index 256f032f674b741cc272a4ce5bd756c08d7154d1..a7b6af23b65afad40ef8a6bfc2875fe8c0a0a100 100644 (file)
@@ -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
index 0eebbf4d0bc9aefcfd435ec35370c096c9604343..c106f6f4e28bd74b9281cd25f1ae1db63f74e36d 100644 (file)
@@ -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
index c8647019067d42c431ffa03c6f9b31546b936a82..ec036865355860fdf966db8ba0de4aad873cacc5 100644 (file)
@@ -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
index 5de4d654bb94eb18896d97e297b2aad144bfec87..21a3fbbe460632a3ab634aa41308c46260717a74 100644 (file)
@@ -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)
 
index 24f098f02895fc2b2ca1d5f50dc5edf4250bc38d..2886cd595077908a8b30226b44a18566118179ff 100644 (file)
@@ -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);
index e07703ef6f5ea5bee0893406b953ab70f1cc5f6a..a0d378125f9f88c59b3ae2e9950603a7ef52ff6c 100644 (file)
@@ -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 */
index 2e11b1ce849464d4f5a372f4e480c9c6cbdbde36..3d8b4a933466b4daabbae4e7c634e9a5913c781c 100644 (file)
@@ -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
index deae36f422fb1ecbe65d7481f52ff9fcd4e07e25..a479faa9b05a0e2c4ef9f0048a987e1927593c76 100644 (file)
@@ -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);
index 84d6aa8d58f0af4459dfce4381a2666368d563b6..55d5bddc240446b9a8dd499accb5e9f35a151c27 100644 (file)
@@ -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;
index e7ae2fa87c20dfc28588dc966936dd02c34ed912..569349ef461efaf53ad8d1bbf5faf40a05c35fbc 100644 (file)
@@ -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
index d6c1f6e72d40f842c06286f0a8b9b05adc2c980a..d06179e690cafc538ad7de1a462d564c6d0c64d1 100644 (file)
@@ -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;
index 53088a28cff2c7f0a299ea8944c4a5a0f12daa20..a8c992a1b388b1857609c529a2387d1fdf9abf58 100644 (file)
@@ -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;
index 5c4150346fac069ae482a8392fb841edc191c51d..d04a9075311c40b95e0106d05d3beb0885f4afd5 100644 (file)
@@ -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 */
index 4675fbce0cffdaccfdc26f82bcc1636894d2505b..569c552922f8b883bcabe3409fe1ea968616a048 100644 (file)
 #define __NR_fstat             108
 #define __NR_uname             109
 #define __NR_iopl              110
+#define __NR_vhangup           111
+#define __NR_idle              112
 
 extern int errno;
 
index aec7bb7ff6804816d4bcd26282bec6daf54cf96f..704bd1ebd0b3128810354ef2fa9e5c7aad495efa 100644 (file)
 #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, ...)
index b1620d2c1feb9af7e16da6d89b5c87cf9b1aab17..f8d7d2102d28cff7e09ba0afda7082c906753c3a 100644 (file)
@@ -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
index 0a7005b7d6d9434ca86c57268d56dae00df087ea..1a5f6404c0a92a8f1cc45a8f1201c67204977165 100644 (file)
@@ -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
index 195146d5f00d50239d0a2b79d5c8ba83dd84aaa8..8194b44c30506d9edb906168afe5fafe5dc11cb0 100644 (file)
@@ -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>
index cff8124554a17b943f12036bbf60586fb7e7c615..4880d35df967e55b408a78589441542dade69ccd 100644 (file)
@@ -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;
                }
index 396e6c243219fb5840fb2af2ebc93b54c0c6e080..f042be69b6604e6f867150cd659f12fc0014b2e8 100644 (file)
@@ -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;
 }
 
index 67d4153cd0591d5f43f9105b2a306d31d9e7e501..7b65584c780ddee04b69fb3dfc31f8bc477e177c 100644 (file)
@@ -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},
index eb213ac2e3966a3893f87676ebccf5202a2ef8da..5212b50f1c5849c70c902723525957ffed0ad794 100644 (file)
@@ -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);
        }
index b31e90e3c9771a7aebf5aa21c2fe322699fd688c..8cc5451a52efb7f8bc7e93fba66c74ed396e2ebe 100644 (file)
@@ -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;
index 208aefb3e0d7700c827b8b7471d61729332d8b9d..1e8a710a8663524c546494026cfec2460283ba85 100644 (file)
@@ -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;
        }
index 735a795d95101c939a664cd6b8d5bb900c7d5986..44c072326c55e23381cebd23b38989f8b98fc554 100644 (file)
@@ -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
index 209641e422a63b42a1c223e9d4f500bb9d20611d..1595b4f1d949f968f6cdbd24a47c501ae244fd02 100644 (file)
@@ -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;
 }
index b582eb4cb6fe0e2e4b172f2e519942504ac41c92..cc95a72125fdb9c2a5539236476ed09a1b4f43c2 100644 (file)
--- 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;
        }
index daada7072d9cf10d3efcafa2a05c4b583e7304c9..72a28e1a3dca7685e105f55f671cc4ee45233ce1 100644 (file)
@@ -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 \
index ccbd5e49f87bcf2a693e9e5ecba487e4c5507fdb..ac6f43324ecc47ac2f5ba8fc92e66edfb8846e52 100644 (file)
@@ -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);
index ffea8a2f408536f6079a7243978c220390919970..365222680f65d4d7d446b97d89b8fd7b64df68e3 100644 (file)
@@ -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>
 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;
        }
index 4b48562de73abb42acb68cf6394c9ccc34163fc7..29fd1ae20e4ab9dc8c86a0375d48661892ac043e 100644 (file)
@@ -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_
index 8e956b55313fa0fc43f87aa6a126a319514dc0f3..b0a2f10a7eea8d44c4e9d4b650296111df60a164 100644 (file)
@@ -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),