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
