NFS: Ensure that we revalidate the cached file length for llseek(SEEK_END) Signed-off-by: Trond Myklebust --- fs/nfs/file.c | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletion(-) Index: linux-2.6.12-rc1/fs/nfs/file.c =================================================================== --- linux-2.6.12-rc1.orig/fs/nfs/file.c +++ linux-2.6.12-rc1/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,19 @@ 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) { + struct inode *inode = file->f_dentry->d_inode; + int retval = nfs_revalidate_inode(NFS_SERVER(inode), inode); + if (retval < 0) + return (loff_t)retval; + } + return remote_llseek(file, offset, origin); +} + /* * Flush all dirty pages, and check for write errors. *