Re: [patch 3/5] fuse: fix race in llseek

Miklos Szeredi
2008-04-28T15:12:57Z

> > From: Miklos Szeredi <mszeredi@suse.cz>
> >
> > Fuse doesn't use i_mutex to protect setting i_size, and so
> > generic_file_llseek() can be racy: it doesn't use i_size_read().
> >
> > So do a fuse specific llseek method, which does use i_size_read().
> >
>
> Is there any specific reason why we don't use i_size_read() in
> generic_file_llseek()?

Just to save some cycles on 32bit archs. Considering that
lseek(SEEK_END) isn't a very performance sensitive operation...

> If no, why don't you fix it instead?

...we could do that. Does anybody object?

Miklos
----

Some filesystems (e.g. fuse) don't use i_mutex to protect setting
i_size, and so generic_file_llseek() can be racy.

Since lseek(SEEK_END) isn't a very performance sensitive operation, do
this in generic_file_llseek(), instead of requiring such filesystems
to duplicate this function.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
fs/read_write.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

Index: linux/fs/read_write.c
===================================================================
--- linux.orig/fs/read_write.c 2008-04-17 04:49:44.000000000 +0200
+++ linux/fs/read_write.c 2008-04-28 17:08:25.000000000 +0200
@@ -39,7 +39,11 @@ loff_t generic_file_llseek(struct file *
mutex_lock(&inode->i_mutex);
switch (origin) {
case SEEK_END:
- offset += inode->i_size;
+ /*
+ * Some filesystems use a different lock as i_mutex
+ * to protect writing i_size
+ */
+ offset += i_size_read(inode);
break;
case SEEK_CUR:
offset += file->f_pos;