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: Jeff Layton <jlayton@samba.org> Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
0b81c1c405
commit
6feb9891da
@ -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
|
* We need to be sure that all dirty pages are written and the
|
||||||
setting the revalidate time to zero */
|
* server has the newest file length.
|
||||||
CIFS_I(file->f_path.dentry->d_inode)->time = 0;
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
retval = cifs_revalidate_file(file);
|
rc = cifs_revalidate_file_attr(file);
|
||||||
if (retval < 0)
|
if (rc < 0)
|
||||||
return (loff_t)retval;
|
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);
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
||||||
|
103
fs/cifs/inode.c
103
fs/cifs/inode.c
@ -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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,31 +1755,72 @@ 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);
|
|
||||||
stat->blksize = CIFS_MAX_MSGSIZE;
|
|
||||||
stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If on a multiuser mount without unix extensions, and the
|
* We need to be sure that all dirty pages are written and the server
|
||||||
* admin hasn't overridden them, set the ownership to the
|
* has actual ctime, mtime and file length.
|
||||||
* fsuid/fsgid of the current process.
|
*/
|
||||||
|
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 (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
generic_fillattr(inode, stat);
|
||||||
|
stat->blksize = CIFS_MAX_MSGSIZE;
|
||||||
|
stat->ino = CIFS_I(inode)->uniqueid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If on a multiuser mount without unix extensions, and the admin hasn't
|
||||||
|
* overridden them, set the ownership to the fsuid/fsgid of the current
|
||||||
|
* process.
|
||||||
*/
|
*/
|
||||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
|
||||||
!tcon->unix_ext) {
|
!tcon->unix_ext) {
|
||||||
@ -1795,8 +1829,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
|||||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
|
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
|
||||||
stat->gid = current_fsgid();
|
stat->gid = current_fsgid();
|
||||||
}
|
}
|
||||||
}
|
return rc;
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cifs_truncate_page(struct address_space *mapping, loff_t from)
|
static int cifs_truncate_page(struct address_space *mapping, loff_t from)
|
||||||
|
Loading…
Reference in New Issue
Block a user