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; |
