2005-04-05 02:38:00

by NeilBrown

[permalink] [raw]
Subject: Re: corruption over NFS with 2.6 client, locking, truncating and appending...

On Monday April 4, [email protected] wrote:
> ty den 05.04.2005 Klokka 10:51 (+1000) skreiv Neil Brown:
>
> > switch(*action) {
> > case 'a': /* append */
> > off = lseek(fd, 0, SEEK_END);
> > sprintf(buf, "%09lu\n", off);
> > write(fd, buf, 10);
> > fsync(fd);
> > break;
>
> Argh... OK, I see the problem here.
>
> When you call lseek(SEEK_END), the kernel really needs to be calling
> nfs_revalidate_inode() in order to update the cached attribute info.
> Currently that is not the case, since we just default to the VFS
> generic_file_llseek().
>
> I'll code something up in the morning.

Thanks.

Your explanation would explain that value of 'off' being wrong as I
found with the lockf locking in 2.4.
However as the file was open for O_APPEND, there would be an implicit
seek to the end on every write. Is this implicit seek expected to do
the right thing or would it need fixing too?

NeilBrown


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs


2005-04-05 02:13:53

by Trond Myklebust

[permalink] [raw]
Subject: Re: corruption over NFS with 2.6 client, locking, truncating and appending...

NFS: Ensure that we revalidate the cached file length for llseek(SEEK_END)

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/file.c | 15 ++++++++++++++-
1 files changed, 14 insertions(+), 1 deletion(-)

Index: linux-2.6.12-rc2/fs/nfs/file.c
===================================================================
--- linux-2.6.12-rc2.orig/fs/nfs/file.c
+++ linux-2.6.12-rc2/fs/nfs/file.c
@@ -37,6 +37,7 @@

static int nfs_file_open(struct inode *, struct file *);
static int nfs_file_release(struct inode *, struct file *);
+static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
static int nfs_file_mmap(struct file *, struct vm_area_struct *);
static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
@@ -48,7 +49,7 @@ static int nfs_lock(struct file *filp, i
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);

struct file_operations nfs_file_operations = {
- .llseek = remote_llseek,
+ .llseek = nfs_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = nfs_file_read,
@@ -126,6 +127,18 @@ nfs_file_release(struct inode *inode, st
return NFS_PROTO(inode)->file_release(inode, filp);
}

+static loff_t
+nfs_file_llseek(struct file *file, loff_t offset, int origin)
+{
+ /* origin == SEEK_END => we must revalidate the cached file length */
+ if (origin == 2) {
+ int retval = nfs_revalidate_inode(file->f_dentry->d_inode);
+ if (retval < 0)
+ return (loff_t)retval;
+ }
+ return remote_llseek(file, offset, origin);
+}
+
/*
* Flush all dirty pages, and check for write errors.
*


Attachments:
linux-2.6.12-37-file_add_lseek.dif (1.67 kB)