diff options
| -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 | { |
