Skip to content

Commit

Permalink
cifs: add cifs_revalidate_file
Browse files Browse the repository at this point in the history
...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>
  • Loading branch information
Jeff Layton authored and Steve French committed Mar 9, 2010
1 parent c8634fd commit abab095
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 3 deletions.
2 changes: 1 addition & 1 deletion fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,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_dentry(file->f_path.dentry);
retval = cifs_revalidate_file(file);
if (retval < 0)
return (loff_t)retval;
}
Expand Down
1 change: 1 addition & 0 deletions fs/cifs/cifsfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ 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(struct file *filp);
extern int cifs_revalidate_dentry(struct dentry *);
extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int cifs_setattr(struct dentry *, struct iattr *);
Expand Down
2 changes: 2 additions & 0 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,12 @@ extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
extern struct inode *cifs_iget(struct super_block *sb,
struct cifs_fattr *fattr);

extern int cifs_get_file_info(struct file *filp);
extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path,
FILE_ALL_INFO *pfile_info,
struct super_block *sb, int xid, const __u16 *pfid);
extern int cifs_get_file_info_unix(struct file *filp);
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb, int xid);
Expand Down
3 changes: 1 addition & 2 deletions fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1890,11 +1890,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,

int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
struct dentry *dentry = file->f_path.dentry;
int rc, xid;

xid = GetXid();
rc = cifs_revalidate_dentry(dentry);
rc = cifs_revalidate_file(file);
if (rc) {
cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
FreeXid(xid);
Expand Down
86 changes: 86 additions & 0 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down

0 comments on commit abab095

Please sign in to comment.