diff options
-rw-r--r-- | fs/namei.c | 39 |
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 | */ |
1679 | static inline unsigned long hash_name(const char *name, struct qstr *res) | 1679 | static 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 | */ |
1721 | static inline long hash_name(const char *name, struct qstr *res) | 1718 | static 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; |