diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-02-12 07:44:18 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-03-09 20:22:53 +0000 |
commit | abab095d1fd25986b910d3c46289d8fa3582cdc5 (patch) | |
tree | 2b70291e5159f9a8332cbeb17b21999962eadad0 /fs/cifs/inode.c | |
parent | c8634fd3115497ac311f57be9c12f993437745cf (diff) |
cifs: add cifs_revalidate_file
...to allow updating inode attributes on an existing inode by
filehandle. Change mmap and llseek codepaths to use that
instead of cifs_revalidate_dentry since they have a filehandle
readily available.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index f050dba920c..0d034a84bb8 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -268,6 +268,31 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; } +int cifs_get_file_info_unix(struct file *filp) +{ + int rc; + int xid; + FILE_UNIX_BASIC_INFO find_data; + struct cifs_fattr fattr; + struct inode *inode = filp->f_path.dentry->d_inode; + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct cifsTconInfo *tcon = cifs_sb->tcon; + struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; + + xid = GetXid(); + rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); + if (!rc) { + cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); + } else if (rc == -EREMOTE) { + cifs_create_dfs_fattr(&fattr, inode->i_sb); + rc = 0; + } + + cifs_fattr_to_inode(inode, &fattr); + FreeXid(xid); + return rc; +} + int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *full_path, struct super_block *sb, int xid) @@ -469,6 +494,47 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, fattr->cf_gid = cifs_sb->mnt_gid; } +int cifs_get_file_info(struct file *filp) +{ + int rc; + int xid; + FILE_ALL_INFO find_data; + struct cifs_fattr fattr; + struct inode *inode = filp->f_path.dentry->d_inode; + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct cifsTconInfo *tcon = cifs_sb->tcon; + struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; + + xid = GetXid(); + rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); + if (rc == -EOPNOTSUPP || rc == -EINVAL) { + /* + * FIXME: legacy server -- fall back to path-based call? + * for now, just skip revalidating and mark inode for + * immediate reval. + */ + rc = 0; + CIFS_I(inode)->time = 0; + goto cgfi_exit; + } else if (rc == -EREMOTE) { + cifs_create_dfs_fattr(&fattr, inode->i_sb); + rc = 0; + } else if (rc) + goto cgfi_exit; + + /* + * don't bother with SFU junk here -- just mark inode as needing + * revalidation. + */ + cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false); + fattr.cf_uniqueid = CIFS_I(inode)->uniqueid; + fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; + cifs_fattr_to_inode(inode, &fattr); +cgfi_exit: + FreeXid(xid); + return rc; +} + int cifs_get_inode_info(struct inode **pinode, const unsigned char *full_path, FILE_ALL_INFO *pfindData, struct super_block *sb, int xid, const __u16 *pfid) @@ -1465,6 +1531,26 @@ cifs_invalidate_mapping(struct inode *inode) invalidate_remote_inode(inode); } +int cifs_revalidate_file(struct file *filp) +{ + int rc = 0; + struct inode *inode = filp->f_path.dentry->d_inode; + + if (!cifs_inode_needs_reval(inode)) + goto check_inval; + + if (CIFS_SB(inode->i_sb)->tcon->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) { |