diff -urN linux-2.5.3-pre6/Documentation/filesystems/Locking linux/Documentation/filesystems/Locking
--- linux-2.5.3-pre6/Documentation/filesystems/Locking	Tue Feb  5 17:15:08 2002
+++ linux/Documentation/filesystems/Locking	Tue Feb  5 17:19:44 2002
@@ -219,7 +219,7 @@
 locking rules:
 	All except ->poll() may block.
 		BKL
-llseek:		yes
+llseek:		yes	(see below)
 read:		no
 write:		no
 readdir:	yes	(see below)
@@ -235,6 +235,12 @@
 readv:		no
 writev:		no
 
+->llseek() locking has moved from llseek to the individual llseek
+implementations.  If you are not using generic_file_llseek, you
+need to acquire and release the appropriate lock in your ->llseek().
+This may or may not be the BKL.  Many methods may be safe acquiring
+only the inode semaphore.
+
 ->open() locking is in-transit: big lock partially moved into the methods.
 The only exception is ->open() in the instances of file_operations that never
 end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices
diff -urN linux-2.5.3-pre6/fs/block_dev.c linux/fs/block_dev.c
--- linux-2.5.3-pre6/fs/block_dev.c	Tue Feb  5 17:14:52 2002
+++ linux/fs/block_dev.c	Tue Feb  5 17:20:16 2002
@@ -170,6 +170,7 @@
 	loff_t size = file->f_dentry->d_inode->i_bdev->bd_inode->i_size;
 	loff_t retval;
 
+	lock_kernel();
 	switch (origin) {
 		case 2:
 			offset += size;
@@ -186,6 +187,7 @@
 		}
 		retval = offset;
 	}
+	unlock_kernel();
 	return retval;
 }
 	
diff -urN linux-2.5.3-pre6/fs/hfs/file_cap.c linux/fs/hfs/file_cap.c
--- linux-2.5.3-pre6/fs/hfs/file_cap.c	Tue Feb  5 17:14:52 2002
+++ linux/fs/hfs/file_cap.c	Tue Feb  5 17:28:03 2002
@@ -24,6 +24,7 @@
 #include <linux/hfs_fs_sb.h>
 #include <linux/hfs_fs_i.h>
 #include <linux/hfs_fs.h>
+#include <linux/smp_lock.h>
 
 /*================ Forward declarations ================*/
 static loff_t      cap_info_llseek(struct file *, loff_t,
@@ -91,6 +92,7 @@
 {
 	long long retval;
 
+	lock_kernel();
 	switch (origin) {
 		case 2:
 			offset += file->f_dentry->d_inode->i_size;
@@ -106,6 +108,7 @@
 		}
 		retval = offset;
 	}
+	unlock_kernel();
 	return retval;
 }
 
diff -urN linux-2.5.3-pre6/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c
--- linux-2.5.3-pre6/fs/hfs/file_hdr.c	Tue Feb  5 17:14:52 2002
+++ linux/fs/hfs/file_hdr.c	Tue Feb  5 17:28:15 2002
@@ -29,6 +29,7 @@
 #include <linux/hfs_fs_sb.h>
 #include <linux/hfs_fs_i.h>
 #include <linux/hfs_fs.h>
+#include <linux/smp_lock.h>
 
 /* prodos types */
 #define PRODOSI_FTYPE_DIR   0x0F
@@ -347,6 +348,7 @@
 {
 	long long retval;
 
+	lock_kernel();
 	switch (origin) {
 		case 2:
 			offset += file->f_dentry->d_inode->i_size;
@@ -362,6 +364,7 @@
 		}
 		retval = offset;
 	}
+	unlock_kernel();
 	return retval;
 }
 
diff -urN linux-2.5.3-pre6/fs/hpfs/dir.c linux/fs/hpfs/dir.c
--- linux-2.5.3-pre6/fs/hpfs/dir.c	Tue Feb  5 17:14:52 2002
+++ linux/fs/hpfs/dir.c	Tue Feb  5 17:22:17 2002
@@ -30,6 +30,7 @@
 	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
 	struct super_block *s = i->i_sb;
 	/*printk("dir lseek\n");*/
+	lock_kernel();
 	if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;
 	hpfs_lock_inode(i);
 	pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1;
@@ -40,10 +41,12 @@
 	}
 	hpfs_unlock_inode(i);
 	ok:
+	unlock_kernel();
 	return filp->f_pos = new_off;
 	fail:
 	hpfs_unlock_inode(i);
 	/*printk("illegal lseek: %016llx\n", new_off);*/
+	unlock_kernel();
 	return -ESPIPE;
 }
 
diff -urN linux-2.5.3-pre6/fs/ncpfs/file.c linux/fs/ncpfs/file.c
--- linux-2.5.3-pre6/fs/ncpfs/file.c	Tue Feb  5 17:14:52 2002
+++ linux/fs/ncpfs/file.c	Tue Feb  5 17:28:33 2002
@@ -18,6 +18,7 @@
 #include <linux/locks.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/smp_lock.h>
 
 #include <linux/ncp_fs.h>
 #include "ncplib_kernel.h"
diff -urN linux-2.5.3-pre6/fs/proc/generic.c linux/fs/proc/generic.c
--- linux-2.5.3-pre6/fs/proc/generic.c	Tue Feb  5 17:14:52 2002
+++ linux/fs/proc/generic.c	Tue Feb  5 17:24:10 2002
@@ -16,6 +16,7 @@
 #include <linux/stat.h>
 #define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/smp_lock.h>
 #include <asm/bitops.h>
 
 static ssize_t proc_file_read(struct file * file, char * buf,
@@ -140,22 +141,26 @@
 static loff_t
 proc_file_lseek(struct file * file, loff_t offset, int orig)
 {
+    lock_kernel();
+
     switch (orig) {
     case 0:
 	if (offset < 0)
-	    return -EINVAL;    
+	    goto out;
 	file->f_pos = offset;
-	return(file->f_pos);
+	goto out;
     case 1:
 	if (offset + file->f_pos < 0)
-	    return -EINVAL;    
+	    goto out;
 	file->f_pos += offset;
-	return(file->f_pos);
+	goto out;
     case 2:
-	return(-EINVAL);
     default:
-	return(-EINVAL);
     }
+
+out:
+    unlock_kernel();
+    return -EINVAL;
 }
 
 /*
diff -urN linux-2.5.3-pre6/fs/read_write.c linux/fs/read_write.c
--- linux-2.5.3-pre6/fs/read_write.c	Tue Feb  5 17:14:52 2002
+++ linux/fs/read_write.c	Tue Feb  5 17:41:23 2002
@@ -28,23 +28,29 @@
 loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
 {
 	long long retval;
+	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+
+	down(&inode->i_sem);
 
 	switch (origin) {
 		case 2:
-			offset += file->f_dentry->d_inode->i_size;
+			offset += inode->i_size;
 			break;
 		case 1:
 			offset += file->f_pos;
 	}
 	retval = -EINVAL;
 	if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
-		if (offset != file->f_pos) {
+		if (offset>=0 && offset<=inode->i_sb->s_maxbytes) {
 			file->f_pos = offset;
 			file->f_reada = 0;
 			file->f_version = ++event;
 		}
 		retval = offset;
 	}
+
+	up(&inode->i_sem);
+
 	return retval;
 }
 
@@ -57,6 +63,7 @@
 {
 	long long retval;
 
+	lock_kernel();
 	switch (origin) {
 		case 2:
 			offset += file->f_dentry->d_inode->i_size;
@@ -73,21 +80,18 @@
 		}
 		retval = offset;
 	}
+	unlock_kernel();
 	return retval;
 }
 
 static inline loff_t llseek(struct file *file, loff_t offset, int origin)
 {
 	loff_t (*fn)(struct file *, loff_t, int);
-	loff_t retval;
 
 	fn = default_llseek;
 	if (file->f_op && file->f_op->llseek)
 		fn = file->f_op->llseek;
-	lock_kernel();
-	retval = fn(file, offset, origin);
-	unlock_kernel();
-	return retval;
+	return fn(file, offset, origin);
 }
 
 asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
diff -urN linux-2.5.3-pre6/fs/ufs/file.c linux/fs/ufs/file.c
--- linux-2.5.3-pre6/fs/ufs/file.c	Tue Feb  5 17:14:52 2002
+++ linux/fs/ufs/file.c	Tue Feb  5 17:28:47 2002
@@ -35,6 +35,7 @@
 #include <linux/locks.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
+#include <linux/smp_lock.h>
 
 /*
  * Make sure the offset never goes beyond the 32-bit mark..
@@ -47,6 +48,7 @@
 	long long retval;
 	struct inode *inode = file->f_dentry->d_inode;
 
+	lock_kernel();
 	switch (origin) {
 		case 2:
 			offset += inode->i_size;
@@ -64,6 +66,7 @@
 		}
 		retval = offset;
 	}
+	unlock_kernel();
 	return retval;
 }
 
