aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <andi@firstfloor.org>2008-06-27 05:05:24 -0400
committerJonathan Corbet <corbet@lwn.net>2008-07-02 17:06:27 -0400
commit9465efc9e96135a2cec8154c0c766fa59984a298 (patch)
tree079b94123ab65ff80c4869bcf25192c8596b049c
parent9c20616c385ebeaa30257ef5d35e8f346db4ee32 (diff)
Remove BKL from remote_llseek v2
- Replace remote_llseek with generic_file_llseek_unlocked (to force compilation failures in all users) - Change all users to either use generic_file_llseek_unlocked directly or take the BKL around. I changed the file systems who don't use the BKL for anything (CIFS, GFS) to call it directly. NCPFS and SMBFS and NFS take the BKL, but explicitely in their own source now. I moved them all over in a single patch to avoid unbisectable sections. Open problem: 32bit kernels can corrupt fpos because its modification is not atomic, but they can do that anyways because there's other paths who modify it without BKL. Do we need a special lock for the pos/f_version = 0 checks? Trond says the NFS BKL is likely not needed, but keep it for now until his full audit. v2: Use generic_file_llseek_unlocked instead of remote_llseek_unlocked and factor duplicated code (suggested by hch) Cc: Trond.Myklebust@netapp.com Cc: swhiteho@redhat.com Cc: sfrench@samba.org Cc: vandrove@vc.cvut.cz Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Jonathan Corbet <corbet@lwn.net>
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/gfs2/ops_file.c4
-rw-r--r--fs/ncpfs/file.c12
-rw-r--r--fs/nfs/file.c6
-rw-r--r--fs/read_write.c38
-rw-r--r--fs/smbfs/file.c11
-rw-r--r--include/linux/fs.h3
7 files changed, 42 insertions, 34 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 427a7c69589..aeff0fe5b6b 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -581,7 +581,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
581 if (retval < 0) 581 if (retval < 0)
582 return (loff_t)retval; 582 return (loff_t)retval;
583 } 583 }
584 return remote_llseek(file, offset, origin); 584 return generic_file_llseek_unlocked(file, offset, origin);
585} 585}
586 586
587struct file_system_type cifs_fs_type = { 587struct file_system_type cifs_fs_type = {
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index e1b7d525a06..24dd5945008 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -62,11 +62,11 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin)
62 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, 62 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
63 &i_gh); 63 &i_gh);
64 if (!error) { 64 if (!error) {
65 error = remote_llseek(file, offset, origin); 65 error = generic_file_llseek_unlocked(file, offset, origin);
66 gfs2_glock_dq_uninit(&i_gh); 66 gfs2_glock_dq_uninit(&i_gh);
67 } 67 }
68 } else 68 } else
69 error = remote_llseek(file, offset, origin); 69 error = generic_file_llseek_unlocked(file, offset, origin);
70 70
71 return error; 71 return error;
72} 72}
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 2b145de45b3..6a7d901f193 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -18,6 +18,7 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/vmalloc.h> 19#include <linux/vmalloc.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/smp_lock.h>
21 22
22#include <linux/ncp_fs.h> 23#include <linux/ncp_fs.h>
23#include "ncplib_kernel.h" 24#include "ncplib_kernel.h"
@@ -281,9 +282,18 @@ static int ncp_release(struct inode *inode, struct file *file) {
281 return 0; 282 return 0;
282} 283}
283 284
285static loff_t ncp_remote_llseek(struct file *file, loff_t offset, int origin)
286{
287 loff_t ret;
288 lock_kernel();
289 ret = generic_file_llseek_unlocked(file, offset, origin);
290 unlock_kernel();
291 return ret;
292}
293
284const struct file_operations ncp_file_operations = 294const struct file_operations ncp_file_operations =
285{ 295{
286 .llseek = remote_llseek, 296 .llseek = ncp_remote_llseek,
287 .read = ncp_file_read, 297 .read = ncp_file_read,
288 .write = ncp_file_write, 298 .write = ncp_file_write,
289 .ioctl = ncp_ioctl, 299 .ioctl = ncp_ioctl,
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 3536b01164f..a34eb78989f 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -170,6 +170,7 @@ force_reval:
170 170
171static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) 171static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
172{ 172{
173 loff_t loff;
173 /* origin == SEEK_END => we must revalidate the cached file length */ 174 /* origin == SEEK_END => we must revalidate the cached file length */
174 if (origin == SEEK_END) { 175 if (origin == SEEK_END) {
175 struct inode *inode = filp->f_mapping->host; 176 struct inode *inode = filp->f_mapping->host;
@@ -177,7 +178,10 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
177 if (retval < 0) 178 if (retval < 0)
178 return (loff_t)retval; 179 return (loff_t)retval;
179 } 180 }
180 return remote_llseek(filp, offset, origin); 181 lock_kernel(); /* BKL needed? */
182 loff = generic_file_llseek_unlocked(filp, offset, origin);
183 unlock_kernel();
184 return loff;
181} 185}
182 186
183/* 187/*
diff --git a/fs/read_write.c b/fs/read_write.c
index f0d1240a5c6..9ba495d5a29 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -31,12 +31,12 @@ const struct file_operations generic_ro_fops = {
31 31
32EXPORT_SYMBOL(generic_ro_fops); 32EXPORT_SYMBOL(generic_ro_fops);
33 33
34loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) 34loff_t
35generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin)
35{ 36{
36 loff_t retval; 37 loff_t retval;
37 struct inode *inode = file->f_mapping->host; 38 struct inode *inode = file->f_mapping->host;
38 39
39 mutex_lock(&inode->i_mutex);
40 switch (origin) { 40 switch (origin) {
41 case SEEK_END: 41 case SEEK_END:
42 offset += inode->i_size; 42 offset += inode->i_size;
@@ -46,42 +46,26 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
46 } 46 }
47 retval = -EINVAL; 47 retval = -EINVAL;
48 if (offset>=0 && offset<=inode->i_sb->s_maxbytes) { 48 if (offset>=0 && offset<=inode->i_sb->s_maxbytes) {
49 /* Special lock needed here? */
49 if (offset != file->f_pos) { 50 if (offset != file->f_pos) {
50 file->f_pos = offset; 51 file->f_pos = offset;
51 file->f_version = 0; 52 file->f_version = 0;
52 } 53 }
53 retval = offset; 54 retval = offset;
54 } 55 }
55 mutex_unlock(&inode->i_mutex);
56 return retval; 56 return retval;
57} 57}
58EXPORT_SYMBOL(generic_file_llseek_unlocked);
58 59
59EXPORT_SYMBOL(generic_file_llseek); 60loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
60
61loff_t remote_llseek(struct file *file, loff_t offset, int origin)
62{ 61{
63 loff_t retval; 62 loff_t n;
64 63 mutex_lock(&file->f_dentry->d_inode->i_mutex);
65 lock_kernel(); 64 n = generic_file_llseek_unlocked(file, offset, origin);
66 switch (origin) { 65 mutex_unlock(&file->f_dentry->d_inode->i_mutex);
67 case SEEK_END: 66 return n;
68 offset += i_size_read(file->f_path.dentry->d_inode);
69 break;
70 case SEEK_CUR:
71 offset += file->f_pos;
72 }
73 retval = -EINVAL;
74 if (offset>=0 && offset<=file->f_path.dentry->d_inode->i_sb->s_maxbytes) {
75 if (offset != file->f_pos) {
76 file->f_pos = offset;
77 file->f_version = 0;
78 }
79 retval = offset;
80 }
81 unlock_kernel();
82 return retval;
83} 67}
84EXPORT_SYMBOL(remote_llseek); 68EXPORT_SYMBOL(generic_file_llseek);
85 69
86loff_t no_llseek(struct file *file, loff_t offset, int origin) 70loff_t no_llseek(struct file *file, loff_t offset, int origin)
87{ 71{
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index efbe29af3d7..2294783320c 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -422,9 +422,18 @@ smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
422 return error; 422 return error;
423} 423}
424 424
425static loff_t smb_remote_llseek(struct file *file, loff_t offset, int origin)
426{
427 loff_t ret;
428 lock_kernel();
429 ret = generic_file_llseek_unlocked(file, offset, origin);
430 unlock_kernel();
431 return ret;
432}
433
425const struct file_operations smb_file_operations = 434const struct file_operations smb_file_operations =
426{ 435{
427 .llseek = remote_llseek, 436 .llseek = smb_remote_llseek,
428 .read = do_sync_read, 437 .read = do_sync_read,
429 .aio_read = smb_file_aio_read, 438 .aio_read = smb_file_aio_read,
430 .write = do_sync_write, 439 .write = do_sync_write,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f413085f748..b158e5161bc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1871,7 +1871,8 @@ extern void
1871file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); 1871file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
1872extern loff_t no_llseek(struct file *file, loff_t offset, int origin); 1872extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
1873extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); 1873extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
1874extern loff_t remote_llseek(struct file *file, loff_t offset, int origin); 1874extern loff_t generic_file_llseek_unlocked(struct file *file, loff_t offset,
1875 int origin);
1875extern int generic_file_open(struct inode * inode, struct file * filp); 1876extern int generic_file_open(struct inode * inode, struct file * filp);
1876extern int nonseekable_open(struct inode * inode, struct file * filp); 1877extern int nonseekable_open(struct inode * inode, struct file * filp);
1877 1878