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 15:22:53 -0500 |
commit | abab095d1fd25986b910d3c46289d8fa3582cdc5 (patch) | |
tree | 2b70291e5159f9a8332cbeb17b21999962eadad0 /fs/cifs | |
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')
-rw-r--r-- | fs/cifs/cifsfs.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 3 | ||||
-rw-r--r-- | fs/cifs/inode.c | 86 |
5 files changed, 91 insertions, 3 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index cf85a4165b01..5183bc2a1916 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -639,7 +639,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) | |||
639 | setting the revalidate time to zero */ | 639 | setting the revalidate time to zero */ |
640 | CIFS_I(file->f_path.dentry->d_inode)->time = 0; | 640 | CIFS_I(file->f_path.dentry->d_inode)->time = 0; |
641 | 641 | ||
642 | retval = cifs_revalidate_dentry(file->f_path.dentry); | 642 | retval = cifs_revalidate_file(file); |
643 | if (retval < 0) | 643 | if (retval < 0) |
644 | return (loff_t)retval; | 644 | return (loff_t)retval; |
645 | } | 645 | } |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 2af995ca8955..7aa57ecdc437 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -61,6 +61,7 @@ extern int cifs_mkdir(struct inode *, struct dentry *, int); | |||
61 | extern int cifs_rmdir(struct inode *, struct dentry *); | 61 | extern int cifs_rmdir(struct inode *, struct dentry *); |
62 | extern int cifs_rename(struct inode *, struct dentry *, struct inode *, | 62 | extern int cifs_rename(struct inode *, struct dentry *, struct inode *, |
63 | struct dentry *); | 63 | struct dentry *); |
64 | extern int cifs_revalidate_file(struct file *filp); | ||
64 | extern int cifs_revalidate_dentry(struct dentry *); | 65 | extern int cifs_revalidate_dentry(struct dentry *); |
65 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 66 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
66 | extern int cifs_setattr(struct dentry *, struct iattr *); | 67 | extern int cifs_setattr(struct dentry *, struct iattr *); |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index ce9199f0af9d..39e47f46dea5 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -104,10 +104,12 @@ extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); | |||
104 | extern struct inode *cifs_iget(struct super_block *sb, | 104 | extern struct inode *cifs_iget(struct super_block *sb, |
105 | struct cifs_fattr *fattr); | 105 | struct cifs_fattr *fattr); |
106 | 106 | ||
107 | extern int cifs_get_file_info(struct file *filp); | ||
107 | extern int cifs_get_inode_info(struct inode **pinode, | 108 | extern int cifs_get_inode_info(struct inode **pinode, |
108 | const unsigned char *search_path, | 109 | const unsigned char *search_path, |
109 | FILE_ALL_INFO *pfile_info, | 110 | FILE_ALL_INFO *pfile_info, |
110 | struct super_block *sb, int xid, const __u16 *pfid); | 111 | struct super_block *sb, int xid, const __u16 *pfid); |
112 | extern int cifs_get_file_info_unix(struct file *filp); | ||
111 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 113 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
112 | const unsigned char *search_path, | 114 | const unsigned char *search_path, |
113 | struct super_block *sb, int xid); | 115 | struct super_block *sb, int xid); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index b90f8f2ca85c..1389f6ecef9e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1890,11 +1890,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1890 | 1890 | ||
1891 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) | 1891 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) |
1892 | { | 1892 | { |
1893 | struct dentry *dentry = file->f_path.dentry; | ||
1894 | int rc, xid; | 1893 | int rc, xid; |
1895 | 1894 | ||
1896 | xid = GetXid(); | 1895 | xid = GetXid(); |
1897 | rc = cifs_revalidate_dentry(dentry); | 1896 | rc = cifs_revalidate_file(file); |
1898 | if (rc) { | 1897 | if (rc) { |
1899 | cFYI(1, ("Validation prior to mmap failed, error=%d", rc)); | 1898 | cFYI(1, ("Validation prior to mmap failed, error=%d", rc)); |
1900 | FreeXid(xid); | 1899 | FreeXid(xid); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index f050dba920cb..0d034a84bb8d 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) | |||
268 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; | 268 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; |
269 | } | 269 | } |
270 | 270 | ||
271 | int cifs_get_file_info_unix(struct file *filp) | ||
272 | { | ||
273 | int rc; | ||
274 | int xid; | ||
275 | FILE_UNIX_BASIC_INFO find_data; | ||
276 | struct cifs_fattr fattr; | ||
277 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
278 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
279 | struct cifsTconInfo *tcon = cifs_sb->tcon; | ||
280 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | ||
281 | |||
282 | xid = GetXid(); | ||
283 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); | ||
284 | if (!rc) { | ||
285 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); | ||
286 | } else if (rc == -EREMOTE) { | ||
287 | cifs_create_dfs_fattr(&fattr, inode->i_sb); | ||
288 | rc = 0; | ||
289 | } | ||
290 | |||
291 | cifs_fattr_to_inode(inode, &fattr); | ||
292 | FreeXid(xid); | ||
293 | return rc; | ||
294 | } | ||
295 | |||
271 | int cifs_get_inode_info_unix(struct inode **pinode, | 296 | int cifs_get_inode_info_unix(struct inode **pinode, |
272 | const unsigned char *full_path, | 297 | const unsigned char *full_path, |
273 | struct super_block *sb, int xid) | 298 | struct super_block *sb, int xid) |
@@ -469,6 +494,47 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
469 | fattr->cf_gid = cifs_sb->mnt_gid; | 494 | fattr->cf_gid = cifs_sb->mnt_gid; |
470 | } | 495 | } |
471 | 496 | ||
497 | int cifs_get_file_info(struct file *filp) | ||
498 | { | ||
499 | int rc; | ||
500 | int xid; | ||
501 | FILE_ALL_INFO find_data; | ||
502 | struct cifs_fattr fattr; | ||
503 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
504 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
505 | struct cifsTconInfo *tcon = cifs_sb->tcon; | ||
506 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | ||
507 | |||
508 | xid = GetXid(); | ||
509 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); | ||
510 | if (rc == -EOPNOTSUPP || rc == -EINVAL) { | ||
511 | /* | ||
512 | * FIXME: legacy server -- fall back to path-based call? | ||
513 | * for now, just skip revalidating and mark inode for | ||
514 | * immediate reval. | ||
515 | */ | ||
516 | rc = 0; | ||
517 | CIFS_I(inode)->time = 0; | ||
518 | goto cgfi_exit; | ||
519 | } else if (rc == -EREMOTE) { | ||
520 | cifs_create_dfs_fattr(&fattr, inode->i_sb); | ||
521 | rc = 0; | ||
522 | } else if (rc) | ||
523 | goto cgfi_exit; | ||
524 | |||
525 | /* | ||
526 | * don't bother with SFU junk here -- just mark inode as needing | ||
527 | * revalidation. | ||
528 | */ | ||
529 | cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false); | ||
530 | fattr.cf_uniqueid = CIFS_I(inode)->uniqueid; | ||
531 | fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; | ||
532 | cifs_fattr_to_inode(inode, &fattr); | ||
533 | cgfi_exit: | ||
534 | FreeXid(xid); | ||
535 | return rc; | ||
536 | } | ||
537 | |||
472 | int cifs_get_inode_info(struct inode **pinode, | 538 | int cifs_get_inode_info(struct inode **pinode, |
473 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, | 539 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, |
474 | struct super_block *sb, int xid, const __u16 *pfid) | 540 | struct super_block *sb, int xid, const __u16 *pfid) |
@@ -1465,6 +1531,26 @@ cifs_invalidate_mapping(struct inode *inode) | |||
1465 | invalidate_remote_inode(inode); | 1531 | invalidate_remote_inode(inode); |
1466 | } | 1532 | } |
1467 | 1533 | ||
1534 | int cifs_revalidate_file(struct file *filp) | ||
1535 | { | ||
1536 | int rc = 0; | ||
1537 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
1538 | |||
1539 | if (!cifs_inode_needs_reval(inode)) | ||
1540 | goto check_inval; | ||
1541 | |||
1542 | if (CIFS_SB(inode->i_sb)->tcon->unix_ext) | ||
1543 | rc = cifs_get_file_info_unix(filp); | ||
1544 | else | ||
1545 | rc = cifs_get_file_info(filp); | ||
1546 | |||
1547 | check_inval: | ||
1548 | if (CIFS_I(inode)->invalid_mapping) | ||
1549 | cifs_invalidate_mapping(inode); | ||
1550 | |||
1551 | return rc; | ||
1552 | } | ||
1553 | |||
1468 | /* revalidate a dentry's inode attributes */ | 1554 | /* revalidate a dentry's inode attributes */ |
1469 | int cifs_revalidate_dentry(struct dentry *dentry) | 1555 | int cifs_revalidate_dentry(struct dentry *dentry) |
1470 | { | 1556 | { |