diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/busmouse.c linux-2.3.99pre8+lock/drivers/char/busmouse.c
--- linux-2.3.99pre8-linus/drivers/char/busmouse.c      Mon May 15 07:58:32 2000
+++ linux-2.3.99pre8+lock/drivers/char/busmouse.c       Sat May 20 03:31:12 2000
@@ -109,9 +109,7 @@

       if (changed) {
               wake_up(&mse->wait);
-
-               if (mse->fasyncptr)
-                       kill_fasync(mse->fasyncptr, SIGIO, POLL_IN);
+               tty_send_fasync(&mse->fasyncptr);
       }
}

diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/dn_keyb.c linux-2.3.99pre8+lock/drivers/char/dn_keyb.c
--- linux-2.3.99pre8-linus/drivers/char/dn_keyb.c       Mon Nov  8 14:03:20 1999
+++ linux-2.3.99pre8+lock/drivers/char/dn_keyb.c        Sat May 20 03:33:01 2000
@@ -353,21 +353,20 @@
                       if(mouse_update_allowed) {
                               mouse_ready=1;
                               mouse_buttons=(mouse_packet[0] >> 4) & 0x7;
-                               mouse_dx+=mouse_packet[1] == 0xff ? 0 : (signed char)mouse_packet[1];
-                               mouse_dy+=mouse_packet[2] == 0xff ? 0 : (signed char)mouse_packet[2];
+                               if (mouse_packet[1] != 0xff)
+                                       mouse_dx += (signed char)mouse_packet[1];
+                               if (mouse_packet[2] != 0xff)
+                                       mouse_dy += (signed char)mouse_packet[2];
                               wake_up_interruptible(&mouse_wait);
                               if (mouse_dx < -2048)
-                       mouse_dx = -2048;
-                       else
-                       if (mouse_dx >  2048)
-                       mouse_dx =  2048;
-                       if (mouse_dy < -2048)
-                       mouse_dy = -2048;
-                       else
-                       if (mouse_dy >  2048)
-                       mouse_dy =  2048;
-                               if (mouse_fasyncptr)
-                       kill_fasync(mouse_fasyncptr, SIGIO, POLL_IN);
+                                       mouse_dx = -2048;
+                               else if (mouse_dx >  2048)
+                                       mouse_dx =  2048;
+                               if (mouse_dy < -2048)
+                                       mouse_dy = -2048;
+                               else if (mouse_dy >  2048)
+                                       mouse_dy =  2048;
+                               tty_send_fasync(&mouse_fasyncptr);
                       }
                       mouse_byte_count=0;
/*                     printk("mouse: %d, %d, %x\n",mouse_x,mouse_y,buttons); */
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/drm/fops.c linux-2.3.99pre8+lock/drivers/char/drm/fops.c
--- linux-2.3.99pre8-linus/drivers/char/drm/fops.c      Thu Mar 16 02:05:31 2000
+++ linux-2.3.99pre8+lock/drivers/char/drm/fops.c       Sat May 20 03:33:20 2000
@@ -216,7 +216,7 @@
       if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO);
#else
                               /* Parameter added in 2.3.21 */
-       if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN);
+       tty_send_fasync(&dev->buf_async);
#endif
       DRM_DEBUG("waking\n");
       wake_up_interruptible(&dev->buf_readers);
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/n_hdlc.c linux-2.3.99pre8+lock/drivers/char/n_hdlc.c
--- linux-2.3.99pre8-linus/drivers/char/n_hdlc.c        Mon May 15 07:58:34 2000
+++ linux-2.3.99pre8+lock/drivers/char/n_hdlc.c Sat May 20 03:31:45 2000
@@ -659,12 +659,7 @@

       /* wake up any blocked reads and perform async signalling */
       wake_up_interruptible (&n_hdlc->read_wait);
-       if (n_hdlc->tty->fasync != NULL)
-#if LINUX_VERSION_CODE < VERSION(2,3,0)
-               kill_fasync (n_hdlc->tty->fasync, SIGIO);
-#else
-               kill_fasync (n_hdlc->tty->fasync, SIGIO, POLL_IN);
-#endif
+       tty_send_fasync(&n_hdlc->tty->fasync);
}      /* end of n_hdlc_tty_receive() */

/* n_hdlc_tty_read()
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/n_tty.c linux-2.3.99pre8+lock/drivers/char/n_tty.c
--- linux-2.3.99pre8-linus/drivers/char/n_tty.c Mon May 15 07:58:34 2000
+++ linux-2.3.99pre8+lock/drivers/char/n_tty.c  Sat May 20 03:31:32 2000
@@ -630,8 +630,7 @@
                       put_tty_queue(c, tty);
                       tty->canon_head = tty->read_head;
                       tty->canon_data++;
-                       if (tty->fasync)
-                               kill_fasync(tty->fasync, SIGIO, POLL_IN);
+                       tty_send_fasync(&tty->fasync);
                       if (waitqueue_active(&tty->read_wait))
                               wake_up_interruptible(&tty->read_wait);
                       return;
@@ -735,8 +734,7 @@
       }

       if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
-               if (tty->fasync)
-                       kill_fasync(tty->fasync, SIGIO, POLL_IN);
+               tty_send_fasync(&tty->fasync);
               if (waitqueue_active(&tty->read_wait))
                       wake_up_interruptible(&tty->read_wait);
       }
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/pc110pad.c linux-2.3.99pre8+lock/drivers/char/pc110pad.c
--- linux-2.3.99pre8-linus/drivers/char/pc110pad.c      Mon May 15 07:59:12 2000
+++ linux-2.3.99pre8+lock/drivers/char/pc110pad.c       Sat May 20 03:32:54 2000
@@ -83,8 +83,7 @@
static void wake_readers(void)
{
       wake_up_interruptible(&queue);
-       if(asyncptr)
-               kill_fasync(asyncptr, SIGIO, POLL_IN);
+       tty_send_fasync(&asyncptr);
}


diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/pc_keyb.c linux-2.3.99pre8+lock/drivers/char/pc_keyb.c
--- linux-2.3.99pre8-linus/drivers/char/pc_keyb.c       Mon May 15 07:58:34 2000
+++ linux-2.3.99pre8+lock/drivers/char/pc_keyb.c        Sat May 20 03:32:31 2000
@@ -415,9 +415,8 @@
               head = (head + 1) & (AUX_BUF_SIZE-1);
               if (head != queue->tail) {
                       queue->head = head;
-                       if (queue->fasync)
-                               kill_fasync(queue->fasync, SIGIO, POLL_IN);
                       wake_up_interruptible(&queue->proc_list);
+                       tty_send_fasync(&queue->fasync);
               }
       }
#endif
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/qpmouse.c linux-2.3.99pre8+lock/drivers/char/qpmouse.c
--- linux-2.3.99pre8-linus/drivers/char/qpmouse.c       Sun Feb 20 18:36:53 2000
+++ linux-2.3.99pre8+lock/drivers/char/qpmouse.c        Sat May 20 03:32:41 2000
@@ -133,8 +133,7 @@
               head &= QP_BUF_SIZE-1;
       }
       queue->head = head;
-       if (queue->fasync)
-               kill_fasync(queue->fasync, SIGIO, POLL_IN);
+       tty_send_fasync(&queue->fasync);
       wake_up_interruptible(&queue->proc_list);
}

diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/rtc.c linux-2.3.99pre8+lock/drivers/char/rtc.c
--- linux-2.3.99pre8-linus/drivers/char/rtc.c   Mon May 15 07:59:13 2000
+++ linux-2.3.99pre8+lock/drivers/char/rtc.c    Sat May 20 03:32:17 2000
@@ -178,9 +178,7 @@

       /* Now do the rest of the actions */
       wake_up_interruptible(&rtc_wait);
-
-       if (rtc_async_queue)
-               kill_fasync (rtc_async_queue, SIGIO, POLL_IN);
+       tty_send_fasync(&rtc_async_queue);
}
#endif

@@ -775,9 +773,7 @@

       /* Now we have new data */
       wake_up_interruptible(&rtc_wait);
-
-       if (rtc_async_queue)
-               kill_fasync (rtc_async_queue, SIGIO, POLL_IN);
+       tty_send_fasync(&rtc_async_queue);
}
#endif

diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/char/tty_io.c linux-2.3.99pre8+lock/drivers/char/tty_io.c
--- linux-2.3.99pre8-linus/drivers/char/tty_io.c        Mon May 15 07:59:13 2000
+++ linux-2.3.99pre8+lock/drivers/char/tty_io.c Sat May 20 02:27:42 2000
@@ -1427,49 +1427,6 @@
       return 0;
}

-/*
- * fasync_helper() is used by some character device drivers (mainly mice)
- * to set up the fasync queue. It returns negative on error, 0 if it did
- * no changes and positive if it added/deleted the entry.
- */
-int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
-{
-       struct fasync_struct *fa, **fp;
-       unsigned long flags;
-
-       for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
-               if (fa->fa_file == filp)
-                       break;
-       }
-
-       if (on) {
-               if (fa) {
-                       fa->fa_fd = fd;
-                       return 0;
-               }
-               fa = (struct fasync_struct *)kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
-               if (!fa)
-                       return -ENOMEM;
-               fa->magic = FASYNC_MAGIC;
-               fa->fa_file = filp;
-               fa->fa_fd = fd;
-               save_flags(flags);
-               cli();
-               fa->fa_next = *fapp;
-               *fapp = fa;
-               restore_flags(flags);
-               return 1;
-       }
-       if (!fa)
-               return 0;
-       save_flags(flags);
-       cli();
-       *fp = fa->fa_next;
-       restore_flags(flags);
-       kfree(fa);
-       return 1;
-}
-
static int tty_fasync(int fd, struct file * filp, int on)
{
       struct tty_struct * tty;
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/i2o/i2o_config.c linux-2.3.99pre8+lock/drivers/i2o/i2o_config.c
--- linux-2.3.99pre8-linus/drivers/i2o/i2o_config.c     Mon May 15 07:59:13 2000
+++ linux-2.3.99pre8+lock/drivers/i2o/i2o_config.c      Sat May 20 03:18:38 2000
@@ -161,8 +161,7 @@
//             printk(KERN_INFO "File %p w/id %d has %d events\n",
//                     inf->fp, inf->q_id, inf->q_len);

-               if(inf->fasync)
-                       kill_fasync(inf->fasync, SIGIO, POLL_IN);
+               tty_send_fasync(&inf->fasync);
       }

       return;
Binary files linux-2.3.99pre8-linus/drivers/pci/gen-devlist and linux-2.3.99pre8+lock/drivers/pci/gen-devlist differ
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/sbus/char/pcikbd.c linux-2.3.99pre8+lock/drivers/sbus/char/pcikbd.c
--- linux-2.3.99pre8-linus/drivers/sbus/char/pcikbd.c   Mon May 15 07:59:22 2000
+++ linux-2.3.99pre8+lock/drivers/sbus/char/pcikbd.c    Sat May 20 03:34:05 2000
@@ -737,8 +737,7 @@

       spin_unlock_irqrestore(&pcikbd_lock, flags);

-       if (queue->fasync)
-               kill_fasync(queue->fasync, SIGIO, POLL_IN);
+       tty_send_fasync(&queue->fasync);
       wake_up_interruptible(&queue->proc_list);
}

diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/sbus/char/sunkbd.c linux-2.3.99pre8+lock/drivers/sbus/char/sunkbd.c
--- linux-2.3.99pre8-linus/drivers/sbus/char/sunkbd.c   Mon May 15 07:59:22 2000
+++ linux-2.3.99pre8+lock/drivers/sbus/char/sunkbd.c    Sat May 20 03:33:40 2000
@@ -1310,8 +1310,7 @@
       }
       spin_unlock_irqrestore(&kbd_queue_lock, flags);

-       if (kb_fasync)
-               kill_fasync (kb_fasync, SIGIO, POLL_IN);
+       tty_send_fasync(&kb_fasync);
       wake_up_interruptible (&kbd_wait);
}

diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/sbus/char/sunmouse.c linux-2.3.99pre8+lock/drivers/sbus/char/sunmouse.c
--- linux-2.3.99pre8-linus/drivers/sbus/char/sunmouse.c Mon May 15 07:59:22 2000
+++ linux-2.3.99pre8+lock/drivers/sbus/char/sunmouse.c  Sat May 20 03:35:41 2000
@@ -147,8 +147,7 @@

       spin_unlock_irqrestore(&sunmouse.lock, flags);

-       if (sunmouse.fasync)
-               kill_fasync (sunmouse.fasync, SIGIO, POLL_IN);
+       tty_send_fasync(&sunmouse.fasync);
       wake_up_interruptible (&sunmouse.proc_list);
}

@@ -382,8 +381,7 @@
               /* We just completed a transaction, wake up whoever is awaiting
                * this event.
                */
-               if (sunmouse.fasync)
-                       kill_fasync (sunmouse.fasync, SIGIO, POLL_IN);
+               tty_send_fasync(&sunmouse.fasync);
               wake_up_interruptible(&sunmouse.proc_list);
       }
       return;
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/scsi/sg.c linux-2.3.99pre8+lock/drivers/scsi/sg.c
--- linux-2.3.99pre8-linus/drivers/scsi/sg.c    Tue Apr 25 02:13:23 2000
+++ linux-2.3.99pre8+lock/drivers/scsi/sg.c     Sat May 20 03:07:40 2000
@@ -1052,8 +1052,7 @@
    if (sfp && srp) {
       /* Now wake up any sg_read() that is waiting for this packet. */
       wake_up_interruptible(&sfp->read_wait);
-       if (sfp->async_qp)
-           kill_fasync(sfp->async_qp, SIGPOLL, POLL_IN);
+       kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN);
    }
}

diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/sgi/char/shmiq.c linux-2.3.99pre8+lock/drivers/sgi/char/shmiq.c
--- linux-2.3.99pre8-linus/drivers/sgi/char/shmiq.c     Sun Mar 12 12:03:13 2000
+++ linux-2.3.99pre8+lock/drivers/sgi/char/shmiq.c      Sat May 20 03:34:14 2000
@@ -118,8 +118,7 @@
               e->data.device, e->data.which, e->data.type, e->data.flags);
       s->tail = tail_next;
       shmiqs [device].tail = tail_next;
-       if (shmiqs [device].fasync)
-               kill_fasync (shmiqs [device].fasync, SIGIO, POLL_IN);
+       tty_send_fasync(&shmiqs[device].fasync);
       wake_up_interruptible (&shmiqs [device].proc_list);
}

diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/telephony/ixj.c linux-2.3.99pre8+lock/drivers/telephony/ixj.c
--- linux-2.3.99pre8-linus/drivers/telephony/ixj.c      Thu Mar 16 02:05:36 2000
+++ linux-2.3.99pre8+lock/drivers/telephony/ixj.c       Sat May 20 03:28:40 2000
@@ -446,8 +446,7 @@
                                       {
                                               j->m_hook = 0;
                                               j->ex.bits.hookstate = 1;
-                                               if (j->async_queue)
-                                                       kill_fasync(j->async_queue, SIGIO, POLL_IN);    // Send apps notice of change
+                                               tty_send_fasync(&j->async_queue);       // Send apps notice of change
                                       }
                                       goto timer_end;
                               }
@@ -536,8 +535,7 @@
                                       j->proc_load = j->ssr.high << 8 | j->ssr.low;
                                       if (!j->m_hook) {
                                               j->m_hook = j->ex.bits.hookstate = 1;
-                                               if (j->async_queue)
-                                                       kill_fasync(j->async_queue, SIGIO, POLL_IN);    // Send apps notice of change
+                                               tty_send_fasync(&j->async_queue);       // Send apps notice of change
                                       }
                               } else {
                                       if (j->dsp.low == 0x21 &&
@@ -552,8 +550,7 @@
                                       if (j->m_hook) {
                                               j->m_hook = 0;
                                               j->ex.bits.hookstate = 1;
-                                               if (j->async_queue)
-                                                       kill_fasync(j->async_queue, SIGIO, POLL_IN);    // Send apps notice of change
+                                               tty_send_fasync(&j->async_queue);       // Send apps notice of change
                                       }
                               }
                       }
@@ -642,8 +639,7 @@
                       }
                       if (j->ex.bytes) {
                               wake_up_interruptible(&j->poll_q);      // Wake any blocked selects
-                               if (j->async_queue)
-                                       kill_fasync(j->async_queue, SIGIO, POLL_IN);    // Send apps notice of change
+                               tty_send_fasync(&j->async_queue);       // Send apps notice of change
                       }
               } else {
                       break;
@@ -917,8 +913,7 @@
               j->r_hook = fOffHook;
               if (j->port != PORT_POTS) {
                       j->ex.bits.hookstate = 1;
-                       if (j->async_queue)
-                               kill_fasync(j->async_queue, SIGIO, POLL_IN);    // Send apps notice of change
+                       tty_send_fasync(&j->async_queue);       // Send apps notice of change

               }
       }
@@ -1471,8 +1466,7 @@

                       wake_up_interruptible(&j->poll_q);      // Wake any blocked selects

-                       if (j->async_queue)
-                               kill_fasync(j->async_queue, SIGIO, POLL_IN);    // Send apps notice of frame
+                       tty_send_fasync(&j->async_queue);       // Send apps notice of frame

               }
       }
@@ -1557,8 +1551,7 @@

                       wake_up_interruptible(&j->poll_q);      // Wake any blocked selects

-                       if (j->async_queue)
-                               kill_fasync(j->async_queue, SIGIO, POLL_IN);    // Send apps notice of empty buffer
+                       tty_send_fasync(&j->async_queue);       // Send apps notice of empty buffer
#ifdef PERFMON_STATS
                       ++j->frameswritten;
#endif
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/usb/evdev.c linux-2.3.99pre8+lock/drivers/usb/evdev.c
--- linux-2.3.99pre8-linus/drivers/usb/evdev.c  Mon May 15 07:58:43 2000
+++ linux-2.3.99pre8+lock/drivers/usb/evdev.c   Sat May 20 03:34:26 2000
@@ -72,8 +72,7 @@
               list->buffer[list->head].value = value;
               list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);

-               if (list->fasync)
-                       kill_fasync(list->fasync, SIGIO, POLL_IN);
+               tty_send_fasync(&list->fasync);

               list = list->next;
       }
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/usb/joydev.c linux-2.3.99pre8+lock/drivers/usb/joydev.c
--- linux-2.3.99pre8-linus/drivers/usb/joydev.c Mon May 15 07:58:43 2000
+++ linux-2.3.99pre8+lock/drivers/usb/joydev.c  Sat May 20 03:17:53 2000
@@ -139,8 +139,7 @@
                       if (list->tail == (list->head = (list->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
                               list->startup = 0;

-               if (list->fasync)
-                       kill_fasync(list->fasync, SIGIO, POLL_IN);
+               tty_send_fasync(&list->fasync);

               list = list->next;
       }
diff -urNX ../exclude linux-2.3.99pre8-linus/drivers/usb/mousedev.c linux-2.3.99pre8+lock/drivers/usb/mousedev.c
--- linux-2.3.99pre8-linus/drivers/usb/mousedev.c       Mon May 15 07:59:24 2000
+++ linux-2.3.99pre8+lock/drivers/usb/mousedev.c        Sat May 20 03:36:28 2000
@@ -138,8 +138,7 @@

                       list->ready = 1;

-                       if (list->fasync)
-                               kill_fasync(list->fasync, SIGIO, POLL_IN);
+                       tty_send_fasync(&list->fasync);

                       list = list->next;
               }
@@ -311,8 +310,7 @@
               list->buffer = list->bufsiz;
       }

-       if (list->fasync)
-               kill_fasync(list->fasync, SIGIO, POLL_IN);
+       tty_send_fasync(&list->fasync);

       wake_up_interruptible(&list->mousedev->wait);

diff -urNX ../exclude linux-2.3.99pre8-linus/fs/fcntl.c linux-2.3.99pre8+lock/fs/fcntl.c
--- linux-2.3.99pre8-linus/fs/fcntl.c   Sun Mar 12 12:03:14 2000
+++ linux-2.3.99pre8+lock/fs/fcntl.c    Sat May 20 04:43:39 2000
@@ -4,8 +4,10 @@
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

+#include <linux/init.h>
#include <linux/mm.h>
#include <linux/file.h>
+#include <linux/slab.h>
#include <linux/smp_lock.h>

#include <asm/poll.h>
@@ -326,7 +330,7 @@
       read_unlock(&tasklist_lock);
}

-void kill_fasync(struct fasync_struct *fa, int sig, int band)
+void __kill_fasync(struct fasync_struct *fa, int sig, int band)
{
       while (fa) {
               struct fown_struct * fown;
@@ -343,4 +347,98 @@
                       send_sigio(fown, fa, band);
               fa = fa->fa_next;
       }
+}
+
+static rwlock_t fasync_lock = RW_LOCK_UNLOCKED;
+static kmem_cache_t *fasync_cache;
+
+void kill_fasync(struct fasync_struct **fa, int sig, int band)
+{
+       read_lock(&fasync_lock);
+       __kill_fasync(*fa, sig, band);
+       read_unlock(&fasync_lock);
+}
+
+static int fasync_on(int fd, struct file *filp, struct fasync_struct **prev)
+{
+       struct fasync_struct *fa, *fna = NULL;
+
+       fna = kmem_cache_alloc(fasync_cache, SLAB_KERNEL);
+               /* kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); */
+       if (fna == NULL)
+               return -ENOMEM;
+
+       for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev)
+               if (fa->fa_file == filp)
+                       break;
+
+       if (fa != NULL) {
+               fa->fa_fd = fd;
+               kmem_cache_free(fasync_cache, fna);
+               /* kfree_s(fna,sizeof(struct fasync_struct)); */
+               goto out;
+       } else {
+               fna->fa_file = filp;
+               fna->fa_fd = fd;
+               fna->magic = FASYNC_MAGIC;
+               fna->fa_next = *prev;
+               *prev = fna;
+       }
+
+out:
+       return 0;
+}
+
+static int fasync_off(struct file *filp, struct fasync_struct **prev)
+{
+       struct fasync_struct *fa;
+
+       for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev)
+               if (fa->fa_file == filp)
+                       break;
+
+       if (fa != NULL) {
+               *prev = fa->fa_next;
+               kmem_cache_free(fasync_cache, fa);
+               /* kfree_s(fa, sizeof(struct fasync_struct)); */
+       }
+
+       return 0;
+}
+
+int file_fasync(int fd, struct file *filp, int on)
+{
+       int error;
+       struct fasync_struct **fa;
+
+       write_lock_irq(&fasync_lock);
+       fa = &filp->f_dentry->d_inode->i_fasync;
+       error = on ? fasync_on(fd, filp, fa) : fasync_off(filp, fa);
+       write_unlock_irq(&fasync_lock);
+
+       return error;
+}
+
+/*
+ * fasync_helper() is used by some character device drivers (mainly mice)
+ * to set up the fasync queue. It returns negative on error, 0 if it did
+ * no changes XXX: and positive if it added/deleted the entry.
+ */
+int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fa)
+{
+       int error;
+
+       write_lock_irq(&fasync_lock);
+       error = on ? fasync_on(fd, filp, fa) : fasync_off(filp, fa);
+       write_unlock_irq(&fasync_lock);
+
+       return error;
+}
+
+void __init fasync_init(void)
+{
+       fasync_cache = kmem_cache_create("fasync cache",
+                       sizeof(struct fasync_struct), 0, 0, NULL, NULL);
+       if (!fasync_cache)
+               panic("cannot create fasync slab cache");
}
diff -urNX ../exclude linux-2.3.99pre8-linus/include/linux/fs.h linux-2.3.99pre8+lock/include/linux/fs.h
--- linux-2.3.99pre8-linus/include/linux/fs.h   Mon May 15 07:59:26 2000
+++ linux-2.3.99pre8+lock/include/linux/fs.h    Sat May 20 04:32:48 2000
@@ -187,6 +187,7 @@
extern void buffer_init(unsigned long);
extern void inode_init(unsigned long);
extern void file_table_init(void);
+extern void filelock_init(void);
extern void dcache_init(unsigned long);

/* bh state bits */
@@ -532,20 +533,24 @@
#define OFFSET_MAX     INT_LIMIT(loff_t)
#endif

-extern struct file_lock                        *file_lock_table;
-
#include <linux/fcntl.h>

extern int fcntl_getlk(unsigned int, struct flock *);
extern int fcntl_setlk(unsigned int, unsigned int, struct flock *);

/* fs/locks.c */
+extern struct semaphore file_lock_sem;
+extern struct list_head file_lock_list;
+
extern void locks_remove_posix(struct file *, fl_owner_t);
extern void locks_remove_flock(struct file *);
extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
extern int posix_lock_file(struct file *, struct file_lock *, unsigned int);
extern void posix_block_lock(struct file_lock *, struct file_lock *);
extern void posix_unblock_lock(struct file_lock *);
+extern int __get_lease(struct inode *inode, unsigned int flags);
+
+#define FASYNC_MAGIC 0x4601

struct fasync_struct {
       int     magic;
@@ -554,6 +559,16 @@
       struct  file            *fa_file;
};

+extern void __kill_fasync(struct fasync_struct *, int, int);
+extern void kill_fasync(struct fasync_struct **, int, int);
+extern int file_fasync(int, struct file *, int);
+#define inode_send_fasync(inode) \
+       kill_fasync(&inode->i_fasync, SIGIO, POLL_MSG)
+#define tty_send_fasync(fa) \
+       kill_fasync(fa, SIGIO, POLL_IN)
+
+extern int fasync_helper(int, struct file *, int, struct fasync_struct **);
+
struct nameidata {
       struct dentry *dentry;
       struct vfsmount *mnt;
@@ -562,10 +577,6 @@
       int last_type;
};

-#define FASYNC_MAGIC 0x4601
-
-extern int fasync_helper(int, struct file *, int, struct fasync_struct **);
-
#define DQUOT_USR_ENABLED      0x01            /* User diskquotas enabled */
#define DQUOT_GRP_ENABLED      0x02            /* Group diskquotas enabled */

@@ -863,7 +880,6 @@
#define putname(name)  free_page((unsigned long)(name))

enum {BDEV_FILE, BDEV_SWAP, BDEV_FS, BDEV_RAW};
-extern void kill_fasync(struct fasync_struct *, int, int);
extern int register_blkdev(unsigned int, const char *, struct block_device_operations *);
extern int unregister_blkdev(unsigned int, const char *);
extern struct block_device *bdget(dev_t);
diff -urNX ../exclude linux-2.3.99pre8-linus/init/main.c linux-2.3.99pre8+lock/init/main.c
--- linux-2.3.99pre8-linus/init/main.c  Mon May 15 07:59:39 2000
+++ linux-2.3.99pre8+lock/init/main.c   Sat May 20 00:56:08 2000
@@ -93,6 +93,7 @@
extern void ppc_init(void);
extern void sysctl_init(void);
extern void filescache_init(void);
+extern void fasync_init(void);
extern void signals_init(void);
extern void bdev_init(void);
extern int init_pcmcia_ds(void);
@@ -577,6 +578,8 @@
       bdev_init();
       inode_init(mempages);
       file_table_init();
+       filelock_init();
+       fasync_init();
#if defined(CONFIG_SYSVIPC)
       ipc_init();
#endif