aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c149
1 files changed, 93 insertions, 56 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 6f0683c68952..4bc47e5b5f29 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -29,6 +29,7 @@
29#include "cifsproto.h" 29#include "cifsproto.h"
30#include "cifs_debug.h" 30#include "cifs_debug.h"
31#include "cifs_fs_sb.h" 31#include "cifs_fs_sb.h"
32#include "fscache.h"
32 33
33 34
34static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) 35static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
@@ -288,7 +289,7 @@ int cifs_get_file_info_unix(struct file *filp)
288 struct inode *inode = filp->f_path.dentry->d_inode; 289 struct inode *inode = filp->f_path.dentry->d_inode;
289 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 290 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
290 struct cifsTconInfo *tcon = cifs_sb->tcon; 291 struct cifsTconInfo *tcon = cifs_sb->tcon;
291 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; 292 struct cifsFileInfo *cfile = filp->private_data;
292 293
293 xid = GetXid(); 294 xid = GetXid();
294 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); 295 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -515,7 +516,7 @@ int cifs_get_file_info(struct file *filp)
515 struct inode *inode = filp->f_path.dentry->d_inode; 516 struct inode *inode = filp->f_path.dentry->d_inode;
516 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 517 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
517 struct cifsTconInfo *tcon = cifs_sb->tcon; 518 struct cifsTconInfo *tcon = cifs_sb->tcon;
518 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; 519 struct cifsFileInfo *cfile = filp->private_data;
519 520
520 xid = GetXid(); 521 xid = GetXid();
521 rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); 522 rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -723,18 +724,17 @@ cifs_find_inode(struct inode *inode, void *opaque)
723{ 724{
724 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; 725 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
725 726
727 /* don't match inode with different uniqueid */
726 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) 728 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
727 return 0; 729 return 0;
728 730
729 /* 731 /* don't match inode of different type */
730 * uh oh -- it's a directory. We can't use it since hardlinked dirs are 732 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
731 * verboten. Disable serverino and return it as if it were found, the 733 return 0;
732 * caller can discard it, generate a uniqueid and retry the find 734
733 */ 735 /* if it's not a directory or has no dentries, then flag it */
734 if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) { 736 if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry))
735 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; 737 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
736 cifs_autodisable_serverino(CIFS_SB(inode->i_sb));
737 }
738 738
739 return 1; 739 return 1;
740} 740}
@@ -748,6 +748,27 @@ cifs_init_inode(struct inode *inode, void *opaque)
748 return 0; 748 return 0;
749} 749}
750 750
751/*
752 * walk dentry list for an inode and report whether it has aliases that
753 * are hashed. We use this to determine if a directory inode can actually
754 * be used.
755 */
756static bool
757inode_has_hashed_dentries(struct inode *inode)
758{
759 struct dentry *dentry;
760
761 spin_lock(&dcache_lock);
762 list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
763 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
764 spin_unlock(&dcache_lock);
765 return true;
766 }
767 }
768 spin_unlock(&dcache_lock);
769 return false;
770}
771
751/* Given fattrs, get a corresponding inode */ 772/* Given fattrs, get a corresponding inode */
752struct inode * 773struct inode *
753cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) 774cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
@@ -763,12 +784,16 @@ retry_iget5_locked:
763 784
764 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); 785 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
765 if (inode) { 786 if (inode) {
766 /* was there a problematic inode number collision? */ 787 /* was there a potentially problematic inode collision? */
767 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) { 788 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
768 iput(inode);
769 fattr->cf_uniqueid = iunique(sb, ROOT_I);
770 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION; 789 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
771 goto retry_iget5_locked; 790
791 if (inode_has_hashed_dentries(inode)) {
792 cifs_autodisable_serverino(CIFS_SB(sb));
793 iput(inode);
794 fattr->cf_uniqueid = iunique(sb, ROOT_I);
795 goto retry_iget5_locked;
796 }
772 } 797 }
773 798
774 cifs_fattr_to_inode(inode, fattr); 799 cifs_fattr_to_inode(inode, fattr);
@@ -776,6 +801,10 @@ retry_iget5_locked:
776 inode->i_flags |= S_NOATIME | S_NOCMTIME; 801 inode->i_flags |= S_NOATIME | S_NOCMTIME;
777 if (inode->i_state & I_NEW) { 802 if (inode->i_state & I_NEW) {
778 inode->i_ino = hash; 803 inode->i_ino = hash;
804#ifdef CONFIG_CIFS_FSCACHE
805 /* initialize per-inode cache cookie pointer */
806 CIFS_I(inode)->fscache = NULL;
807#endif
779 unlock_new_inode(inode); 808 unlock_new_inode(inode);
780 } 809 }
781 } 810 }
@@ -807,6 +836,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
807 if (!inode) 836 if (!inode)
808 return ERR_PTR(-ENOMEM); 837 return ERR_PTR(-ENOMEM);
809 838
839#ifdef CONFIG_CIFS_FSCACHE
840 /* populate tcon->resource_id */
841 cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid;
842#endif
843
810 if (rc && cifs_sb->tcon->ipc) { 844 if (rc && cifs_sb->tcon->ipc) {
811 cFYI(1, "ipc connection - fake read inode"); 845 cFYI(1, "ipc connection - fake read inode");
812 inode->i_mode |= S_IFDIR; 846 inode->i_mode |= S_IFDIR;
@@ -1568,6 +1602,7 @@ cifs_invalidate_mapping(struct inode *inode)
1568 cifs_i->write_behind_rc = rc; 1602 cifs_i->write_behind_rc = rc;
1569 } 1603 }
1570 invalidate_remote_inode(inode); 1604 invalidate_remote_inode(inode);
1605 cifs_fscache_reset_inode_cookie(inode);
1571} 1606}
1572 1607
1573int cifs_revalidate_file(struct file *filp) 1608int cifs_revalidate_file(struct file *filp)
@@ -1663,26 +1698,16 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1663 return rc; 1698 return rc;
1664} 1699}
1665 1700
1666static int cifs_vmtruncate(struct inode *inode, loff_t offset) 1701static void cifs_setsize(struct inode *inode, loff_t offset)
1667{ 1702{
1668 loff_t oldsize; 1703 loff_t oldsize;
1669 int err;
1670 1704
1671 spin_lock(&inode->i_lock); 1705 spin_lock(&inode->i_lock);
1672 err = inode_newsize_ok(inode, offset);
1673 if (err) {
1674 spin_unlock(&inode->i_lock);
1675 goto out;
1676 }
1677
1678 oldsize = inode->i_size; 1706 oldsize = inode->i_size;
1679 i_size_write(inode, offset); 1707 i_size_write(inode, offset);
1680 spin_unlock(&inode->i_lock); 1708 spin_unlock(&inode->i_lock);
1709
1681 truncate_pagecache(inode, oldsize, offset); 1710 truncate_pagecache(inode, oldsize, offset);
1682 if (inode->i_op->truncate)
1683 inode->i_op->truncate(inode);
1684out:
1685 return err;
1686} 1711}
1687 1712
1688static int 1713static int
@@ -1755,7 +1780,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1755 1780
1756 if (rc == 0) { 1781 if (rc == 0) {
1757 cifsInode->server_eof = attrs->ia_size; 1782 cifsInode->server_eof = attrs->ia_size;
1758 rc = cifs_vmtruncate(inode, attrs->ia_size); 1783 cifs_setsize(inode, attrs->ia_size);
1759 cifs_truncate_page(inode->i_mapping, inode->i_size); 1784 cifs_truncate_page(inode->i_mapping, inode->i_size);
1760 } 1785 }
1761 1786
@@ -1780,14 +1805,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1780 1805
1781 xid = GetXid(); 1806 xid = GetXid();
1782 1807
1783 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { 1808 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1784 /* check if we have permission to change attrs */ 1809 attrs->ia_valid |= ATTR_FORCE;
1785 rc = inode_change_ok(inode, attrs); 1810
1786 if (rc < 0) 1811 rc = inode_change_ok(inode, attrs);
1787 goto out; 1812 if (rc < 0)
1788 else 1813 goto out;
1789 rc = 0;
1790 }
1791 1814
1792 full_path = build_path_from_dentry(direntry); 1815 full_path = build_path_from_dentry(direntry);
1793 if (full_path == NULL) { 1816 if (full_path == NULL) {
@@ -1873,18 +1896,24 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1873 CIFS_MOUNT_MAP_SPECIAL_CHR); 1896 CIFS_MOUNT_MAP_SPECIAL_CHR);
1874 } 1897 }
1875 1898
1876 if (!rc) { 1899 if (rc)
1877 rc = inode_setattr(inode, attrs); 1900 goto out;
1878 1901
1879 /* force revalidate when any of these times are set since some 1902 if ((attrs->ia_valid & ATTR_SIZE) &&
1880 of the fs types (eg ext3, fat) do not have fine enough 1903 attrs->ia_size != i_size_read(inode))
1881 time granularity to match protocol, and we do not have a 1904 truncate_setsize(inode, attrs->ia_size);
1882 a way (yet) to query the server fs's time granularity (and 1905
1883 whether it rounds times down). 1906 setattr_copy(inode, attrs);
1884 */ 1907 mark_inode_dirty(inode);
1885 if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))) 1908
1886 cifsInode->time = 0; 1909 /* force revalidate when any of these times are set since some
1887 } 1910 of the fs types (eg ext3, fat) do not have fine enough
1911 time granularity to match protocol, and we do not have a
1912 a way (yet) to query the server fs's time granularity (and
1913 whether it rounds times down).
1914 */
1915 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
1916 cifsInode->time = 0;
1888out: 1917out:
1889 kfree(args); 1918 kfree(args);
1890 kfree(full_path); 1919 kfree(full_path);
@@ -1909,14 +1938,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1909 cFYI(1, "setattr on file %s attrs->iavalid 0x%x", 1938 cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
1910 direntry->d_name.name, attrs->ia_valid); 1939 direntry->d_name.name, attrs->ia_valid);
1911 1940
1912 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { 1941 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1913 /* check if we have permission to change attrs */ 1942 attrs->ia_valid |= ATTR_FORCE;
1914 rc = inode_change_ok(inode, attrs); 1943
1915 if (rc < 0) { 1944 rc = inode_change_ok(inode, attrs);
1916 FreeXid(xid); 1945 if (rc < 0) {
1917 return rc; 1946 FreeXid(xid);
1918 } else 1947 return rc;
1919 rc = 0;
1920 } 1948 }
1921 1949
1922 full_path = build_path_from_dentry(direntry); 1950 full_path = build_path_from_dentry(direntry);
@@ -2024,8 +2052,17 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
2024 2052
2025 /* do not need local check to inode_check_ok since the server does 2053 /* do not need local check to inode_check_ok since the server does
2026 that */ 2054 that */
2027 if (!rc) 2055 if (rc)
2028 rc = inode_setattr(inode, attrs); 2056 goto cifs_setattr_exit;
2057
2058 if ((attrs->ia_valid & ATTR_SIZE) &&
2059 attrs->ia_size != i_size_read(inode))
2060 truncate_setsize(inode, attrs->ia_size);
2061
2062 setattr_copy(inode, attrs);
2063 mark_inode_dirty(inode);
2064 return 0;
2065
2029cifs_setattr_exit: 2066cifs_setattr_exit:
2030 kfree(full_path); 2067 kfree(full_path);
2031 FreeXid(xid); 2068 FreeXid(xid);