aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namei.c39
1 files changed, 18 insertions, 21 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 215e44254c53..01d03892316c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1674,14 +1674,13 @@ EXPORT_SYMBOL(full_name_hash);
1674 1674
1675/* 1675/*
1676 * Calculate the length and hash of the path component, and 1676 * Calculate the length and hash of the path component, and
1677 * fill in the qstr. return the "len" as the result. 1677 * return the "hash_len" as the result.
1678 */ 1678 */
1679static inline unsigned long hash_name(const char *name, struct qstr *res) 1679static inline u64 hash_name(const char *name)
1680{ 1680{
1681 unsigned long a, b, adata, bdata, mask, hash, len; 1681 unsigned long a, b, adata, bdata, mask, hash, len;
1682 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;
1683 1683
1684 res->name = name;
1685 hash = a = 0; 1684 hash = a = 0;
1686 len = -sizeof(unsigned long); 1685 len = -sizeof(unsigned long);
1687 do { 1686 do {
@@ -1698,9 +1697,7 @@ static inline unsigned long hash_name(const char *name, struct qstr *res)
1698 1697
1699 hash += a & zero_bytemask(mask); 1698 hash += a & zero_bytemask(mask);
1700 len += find_zero(mask); 1699 len += find_zero(mask);
1701 res->hash_len = hashlen_create(fold_hash(hash), len); 1700 return hashlen_create(fold_hash(hash), len);
1702
1703 return len;
1704} 1701}
1705 1702
1706#else 1703#else
@@ -1718,20 +1715,18 @@ EXPORT_SYMBOL(full_name_hash);
1718 * 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
1719 * one character. 1716 * one character.
1720 */ 1717 */
1721static inline long hash_name(const char *name, struct qstr *res) 1718static inline u64 hash_name(const char *name)
1722{ 1719{
1723 unsigned long hash = init_name_hash(); 1720 unsigned long hash = init_name_hash();
1724 unsigned long len = 0, c; 1721 unsigned long len = 0, c;
1725 1722
1726 res->name = name;
1727 c = (unsigned char)*name; 1723 c = (unsigned char)*name;
1728 do { 1724 do {
1729 len++; 1725 len++;
1730 hash = partial_name_hash(c, hash); 1726 hash = partial_name_hash(c, hash);
1731 c = (unsigned char)name[len]; 1727 c = (unsigned char)name[len];
1732 } while (c && c != '/'); 1728 } while (c && c != '/');
1733 res->hash_len = hashlen_create(end_name_hash(hash), len); 1729 return hashlen_create(end_name_hash(hash), len);
1734 return len;
1735} 1730}
1736 1731
1737#endif 1732#endif
@@ -1756,18 +1751,17 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1756 1751
1757 /* At this point we know we have a real path component. */ 1752 /* At this point we know we have a real path component. */
1758 for(;;) { 1753 for(;;) {
1759 struct qstr this; 1754 u64 hash_len;
1760 long len;
1761 int type; 1755 int type;
1762 1756
1763 err = may_lookup(nd); 1757 err = may_lookup(nd);
1764 if (err) 1758 if (err)
1765 break; 1759 break;
1766 1760
1767 len = hash_name(name, &this); 1761 hash_len = hash_name(name);
1768 1762
1769 type = LAST_NORM; 1763 type = LAST_NORM;
1770 if (name[0] == '.') switch (len) { 1764 if (name[0] == '.') switch (hashlen_len(hash_len)) {
1771 case 2: 1765 case 2:
1772 if (name[1] == '.') { 1766 if (name[1] == '.') {
1773 type = LAST_DOTDOT; 1767 type = LAST_DOTDOT;
@@ -1781,29 +1775,32 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1781 struct dentry *parent = nd->path.dentry; 1775 struct dentry *parent = nd->path.dentry;
1782 nd->flags &= ~LOOKUP_JUMPED; 1776 nd->flags &= ~LOOKUP_JUMPED;
1783 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 };
1784 err = parent->d_op->d_hash(parent, &this); 1779 err = parent->d_op->d_hash(parent, &this);
1785 if (err < 0) 1780 if (err < 0)
1786 break; 1781 break;
1782 hash_len = this.hash_len;
1783 name = this.name;
1787 } 1784 }
1788 } 1785 }
1789 1786
1790 nd->last = this; 1787 nd->last.hash_len = hash_len;
1788 nd->last.name = name;
1791 nd->last_type = type; 1789 nd->last_type = type;
1792 1790
1793 if (!name[len]) 1791 name += hashlen_len(hash_len);
1792 if (!*name)
1794 return 0; 1793 return 0;
1795 /* 1794 /*
1796 * If it wasn't NUL, we know it was '/'. Skip that 1795 * If it wasn't NUL, we know it was '/'. Skip that
1797 * slash, and continue until no more slashes. 1796 * slash, and continue until no more slashes.
1798 */ 1797 */
1799 do { 1798 do {
1800 len++; 1799 name++;
1801 } while (unlikely(name[len] == '/')); 1800 } while (unlikely(*name == '/'));
1802 if (!name[len]) 1801 if (!*name)
1803 return 0; 1802 return 0;
1804 1803
1805 name += len;
1806
1807 err = walk_component(nd, &next, LOOKUP_FOLLOW); 1804 err = walk_component(nd, &next, LOOKUP_FOLLOW);
1808 if (err < 0) 1805 if (err < 0)
1809 return err; 1806 return err;