diff options
Diffstat (limited to 'fs/cifs/cifsfs.c')
-rw-r--r-- | fs/cifs/cifsfs.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index f736d8a2e771..0f6a54f14eff 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -618,16 +618,29 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) { /* origin == SEEK_END => we must revalidate the cached file length */ if (origin == SEEK_END) { - int retval; - - /* some applications poll for the file length in this strange - way so we must seek to end on non-oplocked files by - setting the revalidate time to zero */ - CIFS_I(file->f_path.dentry->d_inode)->time = 0; - - retval = cifs_revalidate_file(file); - if (retval < 0) - return (loff_t)retval; + int rc; + struct inode *inode = file->f_path.dentry->d_inode; + + /* + * We need to be sure that all dirty pages are written and the + * server has the newest file length. + */ + if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && + inode->i_mapping->nrpages != 0) { + rc = filemap_fdatawait(inode->i_mapping); + mapping_set_error(inode->i_mapping, rc); + return rc; + } + /* + * Some applications poll for the file length in this strange + * way so we must seek to end on non-oplocked files by + * setting the revalidate time to zero. + */ + CIFS_I(inode)->time = 0; + + rc = cifs_revalidate_file_attr(file); + if (rc < 0) + return (loff_t)rc; } return generic_file_llseek_unlocked(file, offset, origin); } |