aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c96
1 files changed, 53 insertions, 43 deletions
diff --git a/fs/namei.c b/fs/namei.c
index a996bb48dfab..a7b05bf82d31 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -34,6 +34,7 @@
34#include <linux/device_cgroup.h> 34#include <linux/device_cgroup.h>
35#include <linux/fs_struct.h> 35#include <linux/fs_struct.h>
36#include <linux/posix_acl.h> 36#include <linux/posix_acl.h>
37#include <linux/hash.h>
37#include <asm/uaccess.h> 38#include <asm/uaccess.h>
38 39
39#include "internal.h" 40#include "internal.h"
@@ -643,24 +644,22 @@ static int complete_walk(struct nameidata *nd)
643 644
644static __always_inline void set_root(struct nameidata *nd) 645static __always_inline void set_root(struct nameidata *nd)
645{ 646{
646 if (!nd->root.mnt) 647 get_fs_root(current->fs, &nd->root);
647 get_fs_root(current->fs, &nd->root);
648} 648}
649 649
650static int link_path_walk(const char *, struct nameidata *); 650static int link_path_walk(const char *, struct nameidata *);
651 651
652static __always_inline void set_root_rcu(struct nameidata *nd) 652static __always_inline unsigned set_root_rcu(struct nameidata *nd)
653{ 653{
654 if (!nd->root.mnt) { 654 struct fs_struct *fs = current->fs;
655 struct fs_struct *fs = current->fs; 655 unsigned seq, res;
656 unsigned seq;
657 656
658 do { 657 do {
659 seq = read_seqcount_begin(&fs->seq); 658 seq = read_seqcount_begin(&fs->seq);
660 nd->root = fs->root; 659 nd->root = fs->root;
661 nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq); 660 res = __read_seqcount_begin(&nd->root.dentry->d_seq);
662 } while (read_seqcount_retry(&fs->seq, seq)); 661 } while (read_seqcount_retry(&fs->seq, seq));
663 } 662 return res;
664} 663}
665 664
666static void path_put_conditional(struct path *path, struct nameidata *nd) 665static void path_put_conditional(struct path *path, struct nameidata *nd)
@@ -860,7 +859,8 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
860 return PTR_ERR(s); 859 return PTR_ERR(s);
861 } 860 }
862 if (*s == '/') { 861 if (*s == '/') {
863 set_root(nd); 862 if (!nd->root.mnt)
863 set_root(nd);
864 path_put(&nd->path); 864 path_put(&nd->path);
865 nd->path = nd->root; 865 nd->path = nd->root;
866 path_get(&nd->root); 866 path_get(&nd->root);
@@ -1137,13 +1137,15 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
1137 */ 1137 */
1138 *inode = path->dentry->d_inode; 1138 *inode = path->dentry->d_inode;
1139 } 1139 }
1140 return read_seqretry(&mount_lock, nd->m_seq) && 1140 return !read_seqretry(&mount_lock, nd->m_seq) &&
1141 !(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT); 1141 !(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT);
1142} 1142}
1143 1143
1144static int follow_dotdot_rcu(struct nameidata *nd) 1144static int follow_dotdot_rcu(struct nameidata *nd)
1145{ 1145{
1146 set_root_rcu(nd); 1146 struct inode *inode = nd->inode;
1147 if (!nd->root.mnt)
1148 set_root_rcu(nd);
1147 1149
1148 while (1) { 1150 while (1) {
1149 if (nd->path.dentry == nd->root.dentry && 1151 if (nd->path.dentry == nd->root.dentry &&
@@ -1155,6 +1157,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
1155 struct dentry *parent = old->d_parent; 1157 struct dentry *parent = old->d_parent;
1156 unsigned seq; 1158 unsigned seq;
1157 1159
1160 inode = parent->d_inode;
1158 seq = read_seqcount_begin(&parent->d_seq); 1161 seq = read_seqcount_begin(&parent->d_seq);
1159 if (read_seqcount_retry(&old->d_seq, nd->seq)) 1162 if (read_seqcount_retry(&old->d_seq, nd->seq))
1160 goto failed; 1163 goto failed;
@@ -1164,6 +1167,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
1164 } 1167 }
1165 if (!follow_up_rcu(&nd->path)) 1168 if (!follow_up_rcu(&nd->path))
1166 break; 1169 break;
1170 inode = nd->path.dentry->d_inode;
1167 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); 1171 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
1168 } 1172 }
1169 while (d_mountpoint(nd->path.dentry)) { 1173 while (d_mountpoint(nd->path.dentry)) {
@@ -1173,11 +1177,12 @@ static int follow_dotdot_rcu(struct nameidata *nd)
1173 break; 1177 break;
1174 nd->path.mnt = &mounted->mnt; 1178 nd->path.mnt = &mounted->mnt;
1175 nd->path.dentry = mounted->mnt.mnt_root; 1179 nd->path.dentry = mounted->mnt.mnt_root;
1180 inode = nd->path.dentry->d_inode;
1176 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); 1181 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
1177 if (!read_seqretry(&mount_lock, nd->m_seq)) 1182 if (read_seqretry(&mount_lock, nd->m_seq))
1178 goto failed; 1183 goto failed;
1179 } 1184 }
1180 nd->inode = nd->path.dentry->d_inode; 1185 nd->inode = inode;
1181 return 0; 1186 return 0;
1182 1187
1183failed: 1188failed:
@@ -1256,7 +1261,8 @@ static void follow_mount(struct path *path)
1256 1261
1257static void follow_dotdot(struct nameidata *nd) 1262static void follow_dotdot(struct nameidata *nd)
1258{ 1263{
1259 set_root(nd); 1264 if (!nd->root.mnt)
1265 set_root(nd);
1260 1266
1261 while(1) { 1267 while(1) {
1262 struct dentry *old = nd->path.dentry; 1268 struct dentry *old = nd->path.dentry;
@@ -1634,8 +1640,7 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
1634 1640
1635static inline unsigned int fold_hash(unsigned long hash) 1641static inline unsigned int fold_hash(unsigned long hash)
1636{ 1642{
1637 hash += hash >> (8*sizeof(int)); 1643 return hash_64(hash, 32);
1638 return hash;
1639} 1644}
1640 1645
1641#else /* 32-bit case */ 1646#else /* 32-bit case */
@@ -1669,9 +1674,9 @@ EXPORT_SYMBOL(full_name_hash);
1669 1674
1670/* 1675/*
1671 * Calculate the length and hash of the path component, and 1676 * Calculate the length and hash of the path component, and
1672 * return the length of the component; 1677 * return the "hash_len" as the result.
1673 */ 1678 */
1674static inline unsigned long hash_name(const char *name, unsigned int *hashp) 1679static inline u64 hash_name(const char *name)
1675{ 1680{
1676 unsigned long a, b, adata, bdata, mask, hash, len; 1681 unsigned long a, b, adata, bdata, mask, hash, len;
1677 const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; 1682 const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
@@ -1691,9 +1696,8 @@ static inline unsigned long hash_name(const char *name, unsigned int *hashp)
1691 mask = create_zero_mask(adata | bdata); 1696 mask = create_zero_mask(adata | bdata);
1692 1697
1693 hash += a & zero_bytemask(mask); 1698 hash += a & zero_bytemask(mask);
1694 *hashp = fold_hash(hash); 1699 len += find_zero(mask);
1695 1700 return hashlen_create(fold_hash(hash), len);
1696 return len + find_zero(mask);
1697} 1701}
1698 1702
1699#else 1703#else
@@ -1711,7 +1715,7 @@ EXPORT_SYMBOL(full_name_hash);
1711 * We know there's a real path component here of at least 1715 * We know there's a real path component here of at least
1712 * one character. 1716 * one character.
1713 */ 1717 */
1714static inline unsigned long hash_name(const char *name, unsigned int *hashp) 1718static inline u64 hash_name(const char *name)
1715{ 1719{
1716 unsigned long hash = init_name_hash(); 1720 unsigned long hash = init_name_hash();
1717 unsigned long len = 0, c; 1721 unsigned long len = 0, c;
@@ -1722,8 +1726,7 @@ static inline unsigned long hash_name(const char *name, unsigned int *hashp)
1722 hash = partial_name_hash(c, hash); 1726 hash = partial_name_hash(c, hash);
1723 c = (unsigned char)name[len]; 1727 c = (unsigned char)name[len];
1724 } while (c && c != '/'); 1728 } while (c && c != '/');
1725 *hashp = end_name_hash(hash); 1729 return hashlen_create(end_name_hash(hash), len);
1726 return len;
1727} 1730}
1728 1731
1729#endif 1732#endif
@@ -1748,20 +1751,17 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1748 1751
1749 /* At this point we know we have a real path component. */ 1752 /* At this point we know we have a real path component. */
1750 for(;;) { 1753 for(;;) {
1751 struct qstr this; 1754 u64 hash_len;
1752 long len;
1753 int type; 1755 int type;
1754 1756
1755 err = may_lookup(nd); 1757 err = may_lookup(nd);
1756 if (err) 1758 if (err)
1757 break; 1759 break;
1758 1760
1759 len = hash_name(name, &this.hash); 1761 hash_len = hash_name(name);
1760 this.name = name;
1761 this.len = len;
1762 1762
1763 type = LAST_NORM; 1763 type = LAST_NORM;
1764 if (name[0] == '.') switch (len) { 1764 if (name[0] == '.') switch (hashlen_len(hash_len)) {
1765 case 2: 1765 case 2:
1766 if (name[1] == '.') { 1766 if (name[1] == '.') {
1767 type = LAST_DOTDOT; 1767 type = LAST_DOTDOT;
@@ -1775,29 +1775,32 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1775 struct dentry *parent = nd->path.dentry; 1775 struct dentry *parent = nd->path.dentry;
1776 nd->flags &= ~LOOKUP_JUMPED; 1776 nd->flags &= ~LOOKUP_JUMPED;
1777 if (unlikely(parent->d_flags & DCACHE_OP_HASH)) { 1777 if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
1778 struct qstr this = { { .hash_len = hash_len }, .name = name };
1778 err = parent->d_op->d_hash(parent, &this); 1779 err = parent->d_op->d_hash(parent, &this);
1779 if (err < 0) 1780 if (err < 0)
1780 break; 1781 break;
1782 hash_len = this.hash_len;
1783 name = this.name;
1781 } 1784 }
1782 } 1785 }
1783 1786
1784 nd->last = this; 1787 nd->last.hash_len = hash_len;
1788 nd->last.name = name;
1785 nd->last_type = type; 1789 nd->last_type = type;
1786 1790
1787 if (!name[len]) 1791 name += hashlen_len(hash_len);
1792 if (!*name)
1788 return 0; 1793 return 0;
1789 /* 1794 /*
1790 * If it wasn't NUL, we know it was '/'. Skip that 1795 * If it wasn't NUL, we know it was '/'. Skip that
1791 * slash, and continue until no more slashes. 1796 * slash, and continue until no more slashes.
1792 */ 1797 */
1793 do { 1798 do {
1794 len++; 1799 name++;
1795 } while (unlikely(name[len] == '/')); 1800 } while (unlikely(*name == '/'));
1796 if (!name[len]) 1801 if (!*name)
1797 return 0; 1802 return 0;
1798 1803
1799 name += len;
1800
1801 err = walk_component(nd, &next, LOOKUP_FOLLOW); 1804 err = walk_component(nd, &next, LOOKUP_FOLLOW);
1802 if (err < 0) 1805 if (err < 0)
1803 return err; 1806 return err;
@@ -1852,7 +1855,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1852 if (*name=='/') { 1855 if (*name=='/') {
1853 if (flags & LOOKUP_RCU) { 1856 if (flags & LOOKUP_RCU) {
1854 rcu_read_lock(); 1857 rcu_read_lock();
1855 set_root_rcu(nd); 1858 nd->seq = set_root_rcu(nd);
1856 } else { 1859 } else {
1857 set_root(nd); 1860 set_root(nd);
1858 path_get(&nd->root); 1861 path_get(&nd->root);
@@ -1903,7 +1906,14 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1903 } 1906 }
1904 1907
1905 nd->inode = nd->path.dentry->d_inode; 1908 nd->inode = nd->path.dentry->d_inode;
1906 return 0; 1909 if (!(flags & LOOKUP_RCU))
1910 return 0;
1911 if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
1912 return 0;
1913 if (!(nd->flags & LOOKUP_ROOT))
1914 nd->root.mnt = NULL;
1915 rcu_read_unlock();
1916 return -ECHILD;
1907} 1917}
1908 1918
1909static inline int lookup_last(struct nameidata *nd, struct path *path) 1919static inline int lookup_last(struct nameidata *nd, struct path *path)