Commit ca572727 authored by jan Blunck's avatar jan Blunck Committed by Linus Torvalds

fs/: do not fallback to default_llseek() when readdir() uses BKL

Do not use the fallback default_llseek() if the readdir operation of the
filesystem still uses the big kernel lock.

Since llseek() modifies
file->f_pos of the directory directly it may need locking to not confuse
readdir which usually uses file->f_pos directly as well

Since the special characteristics of the BKL (unlocked on schedule) are
not necessary in this case, the inode mutex can be used for locking as
provided by generic_file_llseek().  This is only possible since all
filesystems, except reiserfs, either use a directory as a flat file or
with disk address offsets.  Reiserfs on the other hand uses a 32bit hash
off the filename as the offset so generic_file_llseek() can get used as
well since the hash is always smaller than sb->s_maxbytes (= (512 << 32) -
blocksize).
Signed-off-by: default avatarJan Blunck <jblunck@suse.de>
Acked-by: default avatarJan Kara <jack@suse.cz>
Acked-by: default avatarAnders Larsen <al@alarsen.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b4d878e2
...@@ -28,6 +28,7 @@ static int autofs_root_mkdir(struct inode *,struct dentry *,int); ...@@ -28,6 +28,7 @@ static int autofs_root_mkdir(struct inode *,struct dentry *,int);
static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
const struct file_operations autofs_root_operations = { const struct file_operations autofs_root_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = autofs_root_readdir, .readdir = autofs_root_readdir,
.ioctl = autofs_root_ioctl, .ioctl = autofs_root_ioctl,
......
...@@ -57,6 +57,8 @@ const struct inode_operations vxfs_dir_inode_ops = { ...@@ -57,6 +57,8 @@ const struct inode_operations vxfs_dir_inode_ops = {
}; };
const struct file_operations vxfs_dir_operations = { const struct file_operations vxfs_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = vxfs_readdir, .readdir = vxfs_readdir,
}; };
......
...@@ -272,6 +272,7 @@ static int isofs_readdir(struct file *filp, ...@@ -272,6 +272,7 @@ static int isofs_readdir(struct file *filp,
const struct file_operations isofs_dir_operations = const struct file_operations isofs_dir_operations =
{ {
.llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = isofs_readdir, .readdir = isofs_readdir,
}; };
......
...@@ -49,6 +49,7 @@ extern int ncp_symlink(struct inode *, struct dentry *, const char *); ...@@ -49,6 +49,7 @@ extern int ncp_symlink(struct inode *, struct dentry *, const char *);
const struct file_operations ncp_dir_operations = const struct file_operations ncp_dir_operations =
{ {
.llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = ncp_readdir, .readdir = ncp_readdir,
.unlocked_ioctl = ncp_ioctl, .unlocked_ioctl = ncp_ioctl,
......
...@@ -77,6 +77,7 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -77,6 +77,7 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
const struct file_operations qnx4_dir_operations = const struct file_operations qnx4_dir_operations =
{ {
.llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = qnx4_readdir, .readdir = qnx4_readdir,
.fsync = simple_fsync, .fsync = simple_fsync,
......
...@@ -18,6 +18,7 @@ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, ...@@ -18,6 +18,7 @@ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
int datasync); int datasync);
const struct file_operations reiserfs_dir_operations = { const struct file_operations reiserfs_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = reiserfs_readdir, .readdir = reiserfs_readdir,
.fsync = reiserfs_dir_fsync, .fsync = reiserfs_dir_fsync,
......
...@@ -37,6 +37,7 @@ static int smb_link(struct dentry *, struct inode *, struct dentry *); ...@@ -37,6 +37,7 @@ static int smb_link(struct dentry *, struct inode *, struct dentry *);
const struct file_operations smb_dir_operations = const struct file_operations smb_dir_operations =
{ {
.llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = smb_readdir, .readdir = smb_readdir,
.unlocked_ioctl = smb_ioctl, .unlocked_ioctl = smb_ioctl,
......
...@@ -207,6 +207,7 @@ static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -207,6 +207,7 @@ static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* readdir and lookup functions */ /* readdir and lookup functions */
const struct file_operations udf_dir_operations = { const struct file_operations udf_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = udf_readdir, .readdir = udf_readdir,
.unlocked_ioctl = udf_ioctl, .unlocked_ioctl = udf_ioctl,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment