Commit 6feb9891 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French

CIFS: Simplify invalidate part (try #5)

Simplify many places when we call cifs_revalidate/invalidate to make
it do what it exactly needs.
Reviewed-by: default avatarJeff Layton <jlayton@samba.org>
Signed-off-by: default avatarPavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 0b81c1c4
...@@ -618,16 +618,29 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) ...@@ -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 */ /* origin == SEEK_END => we must revalidate the cached file length */
if (origin == SEEK_END) { if (origin == SEEK_END) {
int retval; int rc;
struct inode *inode = file->f_path.dentry->d_inode;
/* 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 */ * We need to be sure that all dirty pages are written and the
CIFS_I(file->f_path.dentry->d_inode)->time = 0; * server has the newest file length.
*/
retval = cifs_revalidate_file(file); if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
if (retval < 0) inode->i_mapping->nrpages != 0) {
return (loff_t)retval; 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); return generic_file_llseek_unlocked(file, offset, origin);
} }
......
...@@ -59,9 +59,11 @@ extern int cifs_mkdir(struct inode *, struct dentry *, int); ...@@ -59,9 +59,11 @@ extern int cifs_mkdir(struct inode *, struct dentry *, int);
extern int cifs_rmdir(struct inode *, struct dentry *); extern int cifs_rmdir(struct inode *, struct dentry *);
extern int cifs_rename(struct inode *, struct dentry *, struct inode *, extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
struct dentry *); struct dentry *);
extern int cifs_revalidate_file_attr(struct file *filp);
extern int cifs_revalidate_dentry_attr(struct dentry *);
extern int cifs_revalidate_file(struct file *filp); extern int cifs_revalidate_file(struct file *filp);
extern int cifs_revalidate_dentry(struct dentry *); extern int cifs_revalidate_dentry(struct dentry *);
extern void cifs_invalidate_mapping(struct inode *inode); extern int cifs_invalidate_mapping(struct inode *inode);
extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int cifs_setattr(struct dentry *, struct iattr *); extern int cifs_setattr(struct dentry *, struct iattr *);
......
...@@ -1445,8 +1445,13 @@ int cifs_strict_fsync(struct file *file, int datasync) ...@@ -1445,8 +1445,13 @@ int cifs_strict_fsync(struct file *file, int datasync)
cFYI(1, "Sync file - name: %s datasync: 0x%x", cFYI(1, "Sync file - name: %s datasync: 0x%x",
file->f_path.dentry->d_name.name, datasync); file->f_path.dentry->d_name.name, datasync);
if (!CIFS_I(inode)->clientCanCacheRead) if (!CIFS_I(inode)->clientCanCacheRead) {
cifs_invalidate_mapping(inode); rc = cifs_invalidate_mapping(inode);
if (rc) {
cFYI(1, "rc: %d during invalidate phase", rc);
rc = 0; /* don't care about it in fsync */
}
}
tcon = tlink_tcon(smbfile->tlink); tcon = tlink_tcon(smbfile->tlink);
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
...@@ -1903,8 +1908,11 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1903,8 +1908,11 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
xid = GetXid(); xid = GetXid();
if (!CIFS_I(inode)->clientCanCacheRead) if (!CIFS_I(inode)->clientCanCacheRead) {
cifs_invalidate_mapping(inode); rc = cifs_invalidate_mapping(inode);
if (rc)
return rc;
}
rc = generic_file_mmap(file, vma); rc = generic_file_mmap(file, vma);
if (rc == 0) if (rc == 0)
......
...@@ -1683,18 +1683,15 @@ cifs_inode_needs_reval(struct inode *inode) ...@@ -1683,18 +1683,15 @@ cifs_inode_needs_reval(struct inode *inode)
/* /*
* Zap the cache. Called when invalid_mapping flag is set. * Zap the cache. Called when invalid_mapping flag is set.
*/ */
void int
cifs_invalidate_mapping(struct inode *inode) cifs_invalidate_mapping(struct inode *inode)
{ {
int rc; int rc = 0;
struct cifsInodeInfo *cifs_i = CIFS_I(inode); struct cifsInodeInfo *cifs_i = CIFS_I(inode);
cifs_i->invalid_mapping = false; cifs_i->invalid_mapping = false;
if (inode->i_mapping && inode->i_mapping->nrpages != 0) { if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
/* write back any cached data */
rc = filemap_write_and_wait(inode->i_mapping);
mapping_set_error(inode->i_mapping, rc);
rc = invalidate_inode_pages2(inode->i_mapping); rc = invalidate_inode_pages2(inode->i_mapping);
if (rc) { if (rc) {
cERROR(1, "%s: could not invalidate inode %p", __func__, cERROR(1, "%s: could not invalidate inode %p", __func__,
...@@ -1704,56 +1701,52 @@ cifs_invalidate_mapping(struct inode *inode) ...@@ -1704,56 +1701,52 @@ cifs_invalidate_mapping(struct inode *inode)
} }
cifs_fscache_reset_inode_cookie(inode); cifs_fscache_reset_inode_cookie(inode);
return rc;
} }
int cifs_revalidate_file(struct file *filp) int cifs_revalidate_file_attr(struct file *filp)
{ {
int rc = 0; int rc = 0;
struct inode *inode = filp->f_path.dentry->d_inode; struct inode *inode = filp->f_path.dentry->d_inode;
struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
if (!cifs_inode_needs_reval(inode)) if (!cifs_inode_needs_reval(inode))
goto check_inval; return rc;
if (tlink_tcon(cfile->tlink)->unix_ext) if (tlink_tcon(cfile->tlink)->unix_ext)
rc = cifs_get_file_info_unix(filp); rc = cifs_get_file_info_unix(filp);
else else
rc = cifs_get_file_info(filp); rc = cifs_get_file_info(filp);
check_inval:
if (CIFS_I(inode)->invalid_mapping)
cifs_invalidate_mapping(inode);
return rc; return rc;
} }
/* revalidate a dentry's inode attributes */ int cifs_revalidate_dentry_attr(struct dentry *dentry)
int cifs_revalidate_dentry(struct dentry *dentry)
{ {
int xid; int xid;
int rc = 0; int rc = 0;
char *full_path = NULL;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct super_block *sb = dentry->d_sb; struct super_block *sb = dentry->d_sb;
char *full_path = NULL;
if (inode == NULL) if (inode == NULL)
return -ENOENT; return -ENOENT;
xid = GetXid();
if (!cifs_inode_needs_reval(inode)) if (!cifs_inode_needs_reval(inode))
goto check_inval; return rc;
xid = GetXid();
/* can not safely grab the rename sem here if rename calls revalidate /* can not safely grab the rename sem here if rename calls revalidate
since that would deadlock */ since that would deadlock */
full_path = build_path_from_dentry(dentry); full_path = build_path_from_dentry(dentry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto check_inval; goto out;
} }
cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time "
"jiffies %ld", full_path, inode, inode->i_count.counter, "%ld jiffies %ld", full_path, inode, inode->i_count.counter,
dentry, dentry->d_time, jiffies); dentry, dentry->d_time, jiffies);
if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
...@@ -1762,41 +1755,81 @@ int cifs_revalidate_dentry(struct dentry *dentry) ...@@ -1762,41 +1755,81 @@ int cifs_revalidate_dentry(struct dentry *dentry)
rc = cifs_get_inode_info(&inode, full_path, NULL, sb, rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
xid, NULL); xid, NULL);
check_inval: out:
if (CIFS_I(inode)->invalid_mapping)
cifs_invalidate_mapping(inode);
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
int cifs_revalidate_file(struct file *filp)
{
int rc;
struct inode *inode = filp->f_path.dentry->d_inode;
rc = cifs_revalidate_file_attr(filp);
if (rc)
return rc;
if (CIFS_I(inode)->invalid_mapping)
rc = cifs_invalidate_mapping(inode);
return rc;
}
/* revalidate a dentry's inode attributes */
int cifs_revalidate_dentry(struct dentry *dentry)
{
int rc;
struct inode *inode = dentry->d_inode;
rc = cifs_revalidate_dentry_attr(dentry);
if (rc)
return rc;
if (CIFS_I(inode)->invalid_mapping)
rc = cifs_invalidate_mapping(inode);
return rc;
}
int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat) struct kstat *stat)
{ {
struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
int err = cifs_revalidate_dentry(dentry); struct inode *inode = dentry->d_inode;
int rc;
if (!err) { /*
generic_fillattr(dentry->d_inode, stat); * We need to be sure that all dirty pages are written and the server
stat->blksize = CIFS_MAX_MSGSIZE; * has actual ctime, mtime and file length.
stat->ino = CIFS_I(dentry->d_inode)->uniqueid; */
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;
}
/* rc = cifs_revalidate_dentry_attr(dentry);
* If on a multiuser mount without unix extensions, and the if (rc)
* admin hasn't overridden them, set the ownership to the return rc;
* fsuid/fsgid of the current process.
*/ generic_fillattr(inode, stat);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && stat->blksize = CIFS_MAX_MSGSIZE;
!tcon->unix_ext) { stat->ino = CIFS_I(inode)->uniqueid;
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
stat->uid = current_fsuid(); /*
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) * If on a multiuser mount without unix extensions, and the admin hasn't
stat->gid = current_fsgid(); * overridden them, set the ownership to the fsuid/fsgid of the current
} * process.
*/
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
!tcon->unix_ext) {
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
stat->uid = current_fsuid();
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
stat->gid = current_fsgid();
} }
return err; return rc;
} }
static int cifs_truncate_page(struct address_space *mapping, loff_t from) static int cifs_truncate_page(struct address_space *mapping, loff_t from)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment