2011/4/12 Jeff Layton <[email protected]>:
> On Fri, 8 Apr 2011 11:56:48 +0400
> Pavel Shilovsky <[email protected]> wrote:
>
>> Simplify many places when we call cifs_revalidate/invalidate to make
>> it does what it exactly needs.
>>
>> Signed-off-by: Pavel Shilovsky <[email protected]>
>> ---
>> fs/cifs/cifsfs.c | 2 +-
>> fs/cifs/cifsfs.h | 4 +-
>> fs/cifs/file.c | 16 ++++++--
>> fs/cifs/inode.c | 114
>> ++++++++++++++++++++++++++++++++++--------------------
>> 4 files changed, 88 insertions(+), 48 deletions(-)
>>
>> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
>> index fb6a2ad..7b29274 100644
>> --- a/fs/cifs/cifsfs.c
>> +++ b/fs/cifs/cifsfs.c
>> @@ -630,7 +630,7 @@ static loff_t cifs_llseek(struct file *file, loff_t
>> offset, int origin)
>> setting the revalidate time to zero */
>> CIFS_I(file->f_path.dentry->d_inode)->time = 0;
>>
>> - retval = cifs_revalidate_file(file);
>> + retval = cifs_revalidate_file_attr(file);
>> if (retval < 0)
>> return (loff_t)retval;
>> }
>
> This looks good overall, I think. I'll note though that on getattr,
> you're writing back data, presumably to make sure that you get a
> correct file size from the server.
>
> Here though in llseek, you're not. Isn't an updated file size important
> for the llseek case? If not, then why bother refreshing the attributes
> at all?
It's my bug - you are right. I think we definitely need to flush all
dirty pages before - I will fix it and resend the patch.
>
>> diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
>> index bb64313..d304584 100644
>> --- a/fs/cifs/cifsfs.h
>> +++ b/fs/cifs/cifsfs.h
>> @@ -59,9 +59,11 @@ extern int cifs_mkdir(struct inode *, struct dentry *,
>> int);
>> extern int cifs_rmdir(struct inode *, struct dentry *);
>> extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
>> 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_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_setattr(struct dentry *, struct iattr *);
>>
>> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
>> index 20a95bb..b1ab963 100644
>> --- a/fs/cifs/file.c
>> +++ b/fs/cifs/file.c
>> @@ -1442,8 +1442,13 @@ int cifs_strict_fsync(struct file *file, int datasync)
>> cFYI(1, "Sync file - name: %s datasync: 0x%x",
>> file->f_path.dentry->d_name.name, datasync);
>>
>> - if (!CIFS_I(inode)->clientCanCacheRead)
>> - cifs_invalidate_mapping(inode);
>> + if (!CIFS_I(inode)->clientCanCacheRead) {
>> + 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);
>> if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
>> @@ -1928,8 +1933,11 @@ int cifs_file_strict_mmap(struct file *file, struct
>> vm_area_struct *vma)
>>
>> xid = GetXid();
>>
>> - if (!CIFS_I(inode)->clientCanCacheRead)
>> - cifs_invalidate_mapping(inode);
>> + if (!CIFS_I(inode)->clientCanCacheRead) {
>> + rc = cifs_invalidate_mapping(inode);
>> + if (rc)
>> + return rc;
>> + }
>>
>> rc = generic_file_mmap(file, vma);
>> if (rc == 0)
>> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
>> index adb6324..5f71e11 100644
>> --- a/fs/cifs/inode.c
>> +++ b/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.
>> */
>> -void
>> +int
>> cifs_invalidate_mapping(struct inode *inode)
>> {
>> - int rc;
>> + int rc = 0;
>> struct cifsInodeInfo *cifs_i = CIFS_I(inode);
>>
>> cifs_i->invalid_mapping = false;
>>
>> 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);
>> if (rc) {
>> 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);
>> + return rc;
>> }
>>
>> -int cifs_revalidate_file(struct file *filp)
>> +int cifs_revalidate_file_attr(struct file *filp)
>> {
>> int rc = 0;
>> struct inode *inode = filp->f_path.dentry->d_inode;
>> struct cifsFileInfo *cfile = (struct cifsFileInfo *)
>> filp->private_data;
>>
>> if (!cifs_inode_needs_reval(inode))
>> - goto check_inval;
>> + return rc;
>>
>> if (tlink_tcon(cfile->tlink)->unix_ext)
>> rc = cifs_get_file_info_unix(filp);
>> else
>> rc = cifs_get_file_info(filp);
>>
>> -check_inval:
>> - if (CIFS_I(inode)->invalid_mapping)
>> - cifs_invalidate_mapping(inode);
>> -
>> return rc;
>> }
>>
>> -/* revalidate a dentry's inode attributes */
>> -int cifs_revalidate_dentry(struct dentry *dentry)
>> +int cifs_revalidate_dentry_attr(struct dentry *dentry)
>> {
>> int xid;
>> int rc = 0;
>> - char *full_path = NULL;
>> struct inode *inode = dentry->d_inode;
>> struct super_block *sb = dentry->d_sb;
>> + char *full_path = NULL;
>>
>> if (inode == NULL)
>> return -ENOENT;
>>
>> - xid = GetXid();
>> -
>> 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
>> since that would deadlock */
>> full_path = build_path_from_dentry(dentry);
>> if (full_path == NULL) {
>> rc = -ENOMEM;
>> - goto check_inval;
>> + goto out;
>> }
>>
>> - cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
>> - "jiffies %ld", full_path, inode, inode->i_count.counter,
>> + cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time
>> "
>> + "%ld jiffies %ld", full_path, inode, inode->i_count.counter,
>> dentry, dentry->d_time, jiffies);
>>
>> if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
>> @@ -1762,41 +1755,78 @@ int cifs_revalidate_dentry(struct dentry *dentry)
>> rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
>> xid, NULL);
>>
>> -check_inval:
>> - if (CIFS_I(inode)->invalid_mapping)
>> - cifs_invalidate_mapping(inode);
>> -
>> +out:
>> kfree(full_path);
>> FreeXid(xid);
>> 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,
>> struct kstat *stat)
>> {
>> struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
>> struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
>> - int err = cifs_revalidate_dentry(dentry);
>> -
>> - if (!err) {
>> - generic_fillattr(dentry->d_inode, stat);
>> - stat->blksize = CIFS_MAX_MSGSIZE;
>> - stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
>> + struct inode *inode = dentry->d_inode;
>> + int rc;
>>
>> - /*
>> - * 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) &&
>> - !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();
>> + if (inode && inode->i_mapping && inode->i_mapping->nrpages != 0) {
>> + rc = filemap_write_and_wait(inode->i_mapping);
>> + if (rc) {
>> + mapping_set_error(inode->i_mapping, rc);
>> + return rc;
>> }
>> }
>> - return err;
>> +
>> + rc = cifs_revalidate_dentry_attr(dentry);
>> + if (rc)
>> + return rc;
>> +
>> + 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 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) &&
>> + !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 rc;
>> }
>>
>> static int cifs_truncate_page(struct address_space *mapping, loff_t from)
>
>
> --
> Jeff Layton <[email protected]>
>
--
Best regards,
Pavel Shilovsky.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html