diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 117 |
1 files changed, 75 insertions, 42 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index fbe7d5858563..0cc7eddb077f 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1683,18 +1683,15 @@ cifs_inode_needs_reval(struct inode *inode) | |||
1683 | /* | 1683 | /* |
1684 | * Zap the cache. Called when invalid_mapping flag is set. | 1684 | * Zap the cache. Called when invalid_mapping flag is set. |
1685 | */ | 1685 | */ |
1686 | void | 1686 | int |
1687 | cifs_invalidate_mapping(struct inode *inode) | 1687 | cifs_invalidate_mapping(struct inode *inode) |
1688 | { | 1688 | { |
1689 | int rc; | 1689 | int rc = 0; |
1690 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 1690 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
1691 | 1691 | ||
1692 | cifs_i->invalid_mapping = false; | 1692 | cifs_i->invalid_mapping = false; |
1693 | 1693 | ||
1694 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { | 1694 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { |
1695 | /* write back any cached data */ | ||
1696 | rc = filemap_write_and_wait(inode->i_mapping); | ||
1697 | mapping_set_error(inode->i_mapping, rc); | ||
1698 | rc = invalidate_inode_pages2(inode->i_mapping); | 1695 | rc = invalidate_inode_pages2(inode->i_mapping); |
1699 | if (rc) { | 1696 | if (rc) { |
1700 | cERROR(1, "%s: could not invalidate inode %p", __func__, | 1697 | cERROR(1, "%s: could not invalidate inode %p", __func__, |
@@ -1704,56 +1701,52 @@ cifs_invalidate_mapping(struct inode *inode) | |||
1704 | } | 1701 | } |
1705 | 1702 | ||
1706 | cifs_fscache_reset_inode_cookie(inode); | 1703 | cifs_fscache_reset_inode_cookie(inode); |
1704 | return rc; | ||
1707 | } | 1705 | } |
1708 | 1706 | ||
1709 | int cifs_revalidate_file(struct file *filp) | 1707 | int cifs_revalidate_file_attr(struct file *filp) |
1710 | { | 1708 | { |
1711 | int rc = 0; | 1709 | int rc = 0; |
1712 | struct inode *inode = filp->f_path.dentry->d_inode; | 1710 | struct inode *inode = filp->f_path.dentry->d_inode; |
1713 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | 1711 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; |
1714 | 1712 | ||
1715 | if (!cifs_inode_needs_reval(inode)) | 1713 | if (!cifs_inode_needs_reval(inode)) |
1716 | goto check_inval; | 1714 | return rc; |
1717 | 1715 | ||
1718 | if (tlink_tcon(cfile->tlink)->unix_ext) | 1716 | if (tlink_tcon(cfile->tlink)->unix_ext) |
1719 | rc = cifs_get_file_info_unix(filp); | 1717 | rc = cifs_get_file_info_unix(filp); |
1720 | else | 1718 | else |
1721 | rc = cifs_get_file_info(filp); | 1719 | rc = cifs_get_file_info(filp); |
1722 | 1720 | ||
1723 | check_inval: | ||
1724 | if (CIFS_I(inode)->invalid_mapping) | ||
1725 | cifs_invalidate_mapping(inode); | ||
1726 | |||
1727 | return rc; | 1721 | return rc; |
1728 | } | 1722 | } |
1729 | 1723 | ||
1730 | /* revalidate a dentry's inode attributes */ | 1724 | int cifs_revalidate_dentry_attr(struct dentry *dentry) |
1731 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1732 | { | 1725 | { |
1733 | int xid; | 1726 | int xid; |
1734 | int rc = 0; | 1727 | int rc = 0; |
1735 | char *full_path = NULL; | ||
1736 | struct inode *inode = dentry->d_inode; | 1728 | struct inode *inode = dentry->d_inode; |
1737 | struct super_block *sb = dentry->d_sb; | 1729 | struct super_block *sb = dentry->d_sb; |
1730 | char *full_path = NULL; | ||
1738 | 1731 | ||
1739 | if (inode == NULL) | 1732 | if (inode == NULL) |
1740 | return -ENOENT; | 1733 | return -ENOENT; |
1741 | 1734 | ||
1742 | xid = GetXid(); | ||
1743 | |||
1744 | if (!cifs_inode_needs_reval(inode)) | 1735 | if (!cifs_inode_needs_reval(inode)) |
1745 | goto check_inval; | 1736 | return rc; |
1737 | |||
1738 | xid = GetXid(); | ||
1746 | 1739 | ||
1747 | /* can not safely grab the rename sem here if rename calls revalidate | 1740 | /* can not safely grab the rename sem here if rename calls revalidate |
1748 | since that would deadlock */ | 1741 | since that would deadlock */ |
1749 | full_path = build_path_from_dentry(dentry); | 1742 | full_path = build_path_from_dentry(dentry); |
1750 | if (full_path == NULL) { | 1743 | if (full_path == NULL) { |
1751 | rc = -ENOMEM; | 1744 | rc = -ENOMEM; |
1752 | goto check_inval; | 1745 | goto out; |
1753 | } | 1746 | } |
1754 | 1747 | ||
1755 | cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " | 1748 | cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time " |
1756 | "jiffies %ld", full_path, inode, inode->i_count.counter, | 1749 | "%ld jiffies %ld", full_path, inode, inode->i_count.counter, |
1757 | dentry, dentry->d_time, jiffies); | 1750 | dentry, dentry->d_time, jiffies); |
1758 | 1751 | ||
1759 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) | 1752 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) |
@@ -1762,41 +1755,81 @@ int cifs_revalidate_dentry(struct dentry *dentry) | |||
1762 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 1755 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
1763 | xid, NULL); | 1756 | xid, NULL); |
1764 | 1757 | ||
1765 | check_inval: | 1758 | out: |
1766 | if (CIFS_I(inode)->invalid_mapping) | ||
1767 | cifs_invalidate_mapping(inode); | ||
1768 | |||
1769 | kfree(full_path); | 1759 | kfree(full_path); |
1770 | FreeXid(xid); | 1760 | FreeXid(xid); |
1771 | return rc; | 1761 | return rc; |
1772 | } | 1762 | } |
1773 | 1763 | ||
1764 | int cifs_revalidate_file(struct file *filp) | ||
1765 | { | ||
1766 | int rc; | ||
1767 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
1768 | |||
1769 | rc = cifs_revalidate_file_attr(filp); | ||
1770 | if (rc) | ||
1771 | return rc; | ||
1772 | |||
1773 | if (CIFS_I(inode)->invalid_mapping) | ||
1774 | rc = cifs_invalidate_mapping(inode); | ||
1775 | return rc; | ||
1776 | } | ||
1777 | |||
1778 | /* revalidate a dentry's inode attributes */ | ||
1779 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1780 | { | ||
1781 | int rc; | ||
1782 | struct inode *inode = dentry->d_inode; | ||
1783 | |||
1784 | rc = cifs_revalidate_dentry_attr(dentry); | ||
1785 | if (rc) | ||
1786 | return rc; | ||
1787 | |||
1788 | if (CIFS_I(inode)->invalid_mapping) | ||
1789 | rc = cifs_invalidate_mapping(inode); | ||
1790 | return rc; | ||
1791 | } | ||
1792 | |||
1774 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | 1793 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, |
1775 | struct kstat *stat) | 1794 | struct kstat *stat) |
1776 | { | 1795 | { |
1777 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); | 1796 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); |
1778 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | 1797 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); |
1779 | int err = cifs_revalidate_dentry(dentry); | 1798 | struct inode *inode = dentry->d_inode; |
1799 | int rc; | ||
1780 | 1800 | ||
1781 | if (!err) { | 1801 | /* |
1782 | generic_fillattr(dentry->d_inode, stat); | 1802 | * We need to be sure that all dirty pages are written and the server |
1783 | stat->blksize = CIFS_MAX_MSGSIZE; | 1803 | * has actual ctime, mtime and file length. |
1784 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | 1804 | */ |
1805 | if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && | ||
1806 | inode->i_mapping->nrpages != 0) { | ||
1807 | rc = filemap_fdatawait(inode->i_mapping); | ||
1808 | mapping_set_error(inode->i_mapping, rc); | ||
1809 | return rc; | ||
1810 | } | ||
1785 | 1811 | ||
1786 | /* | 1812 | rc = cifs_revalidate_dentry_attr(dentry); |
1787 | * If on a multiuser mount without unix extensions, and the | 1813 | if (rc) |
1788 | * admin hasn't overridden them, set the ownership to the | 1814 | return rc; |
1789 | * fsuid/fsgid of the current process. | 1815 | |
1790 | */ | 1816 | generic_fillattr(inode, stat); |
1791 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | 1817 | stat->blksize = CIFS_MAX_MSGSIZE; |
1792 | !tcon->unix_ext) { | 1818 | stat->ino = CIFS_I(inode)->uniqueid; |
1793 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | 1819 | |
1794 | stat->uid = current_fsuid(); | 1820 | /* |
1795 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | 1821 | * If on a multiuser mount without unix extensions, and the admin hasn't |
1796 | stat->gid = current_fsgid(); | 1822 | * overridden them, set the ownership to the fsuid/fsgid of the current |
1797 | } | 1823 | * process. |
1824 | */ | ||
1825 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | ||
1826 | !tcon->unix_ext) { | ||
1827 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | ||
1828 | stat->uid = current_fsuid(); | ||
1829 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | ||
1830 | stat->gid = current_fsgid(); | ||
1798 | } | 1831 | } |
1799 | return err; | 1832 | return rc; |
1800 | } | 1833 | } |
1801 | 1834 | ||
1802 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) | 1835 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) |