Filesystems which are using generic_file_llseek() do not need lock_kernel() in their readir implementations. All operations (including llseek) are serialised by the directory's i_sem. Just fix ext2 and ext3 for now. Others may need locking between readdir and who-knows-what. fs/ext2/dir.c | 4 +--- fs/ext2/file.c | 0 fs/ext3/dir.c | 18 +++++++++--------- 3 files changed, 10 insertions(+), 12 deletions(-) diff -puN fs/ext2/dir.c~lseek-ext2_readdir fs/ext2/dir.c --- 25/fs/ext2/dir.c~lseek-ext2_readdir 2003-03-15 03:20:22.000000000 -0800 +++ 25-akpm/fs/ext2/dir.c 2003-03-15 12:21:56.000000000 -0800 @@ -259,8 +259,6 @@ ext2_readdir (struct file * filp, void * int need_revalidate = (filp->f_version != inode->i_version); int ret = 0; - lock_kernel(); - if (pos > inode->i_size - EXT2_DIR_REC_LEN(1)) goto done; @@ -313,7 +311,6 @@ done: filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; filp->f_version = inode->i_version; UPDATE_ATIME(inode); - unlock_kernel(); return 0; } @@ -660,6 +657,7 @@ not_empty: } struct file_operations ext2_dir_operations = { + .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = ext2_readdir, .ioctl = ext2_ioctl, diff -puN fs/ext3/dir.c~lseek-ext2_readdir fs/ext3/dir.c --- 25/fs/ext3/dir.c~lseek-ext2_readdir 2003-03-15 03:20:22.000000000 -0800 +++ 25-akpm/fs/ext3/dir.c 2003-03-15 12:22:14.000000000 -0800 @@ -37,10 +37,11 @@ static int ext3_release_dir (struct inod struct file * filp); struct file_operations ext3_dir_operations = { + .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = ext3_readdir, /* we take BKL. needed?*/ .ioctl = ext3_ioctl, /* BKL held */ - .fsync = ext3_sync_file, /* BKL held */ + .fsync = ext3_sync_file, /* BKL held */ #ifdef CONFIG_EXT3_INDEX .release = ext3_release_dir, #endif @@ -98,8 +99,7 @@ static int ext3_readdir(struct file * fi struct super_block * sb; int err; struct inode *inode = filp->f_dentry->d_inode; - - lock_kernel(); + int ret = 0; sb = inode->i_sb; @@ -110,8 +110,8 @@ static int ext3_readdir(struct file * fi ((inode->i_size >> sb->s_blocksize_bits) == 1))) { err = ext3_dx_readdir(filp, dirent, filldir); if (err != ERR_BAD_DX_DIR) { - unlock_kernel(); - return err; + ret = err; + goto out; } /* * We don't set the inode dirty flag since it's not @@ -191,8 +191,8 @@ revalidate: filp->f_pos = (filp->f_pos | (sb->s_blocksize - 1)) + 1; brelse (bh); - unlock_kernel(); - return stored; + ret = stored; + goto out; } offset += le16_to_cpu(de->rec_len); if (le32_to_cpu(de->inode)) { @@ -222,8 +222,8 @@ revalidate: brelse (bh); } UPDATE_ATIME(inode); - unlock_kernel(); - return 0; +out: + return ret; } #ifdef CONFIG_EXT3_INDEX diff -puN fs/ext2/file.c~lseek-ext2_readdir fs/ext2/file.c _