diff options
Diffstat (limited to 'fs/ubifs')
-rw-r--r-- | fs/ubifs/dir.c | 7 | ||||
-rw-r--r-- | fs/ubifs/journal.c | 1 | ||||
-rw-r--r-- | fs/ubifs/tnc.c | 90 | ||||
-rw-r--r-- | fs/ubifs/ubifs-media.h | 5 | ||||
-rw-r--r-- | fs/ubifs/ubifs.h | 2 |
5 files changed, 98 insertions, 7 deletions
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 7d3bc3fb8831..7f01f3d2ac3b 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
@@ -253,7 +253,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, | |||
253 | ubifs_assert(fname_len(&nm) == 0); | 253 | ubifs_assert(fname_len(&nm) == 0); |
254 | ubifs_assert(fname_name(&nm) == NULL); | 254 | ubifs_assert(fname_name(&nm) == NULL); |
255 | dent_key_init_hash(c, &key, dir->i_ino, nm.hash); | 255 | dent_key_init_hash(c, &key, dir->i_ino, nm.hash); |
256 | err = ubifs_tnc_lookup(c, &key, dent); | 256 | err = ubifs_tnc_lookup_dh(c, &key, dent, nm.minor_hash); |
257 | } else { | 257 | } else { |
258 | dent_key_init(c, &key, dir->i_ino, &nm); | 258 | dent_key_init(c, &key, dir->i_ino, &nm); |
259 | err = ubifs_tnc_lookup_nm(c, &key, dent, &nm); | 259 | err = ubifs_tnc_lookup_nm(c, &key, dent, &nm); |
@@ -628,7 +628,10 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx) | |||
628 | if (encrypted) { | 628 | if (encrypted) { |
629 | fstr.len = fstr_real_len; | 629 | fstr.len = fstr_real_len; |
630 | 630 | ||
631 | err = fscrypt_fname_disk_to_usr(dir, key_hash_flash(c, &dent->key), 0, &nm.disk_name, &fstr); | 631 | err = fscrypt_fname_disk_to_usr(dir, key_hash_flash(c, |
632 | &dent->key), | ||
633 | le32_to_cpu(dent->cookie), | ||
634 | &nm.disk_name, &fstr); | ||
632 | if (err) | 635 | if (err) |
633 | goto out; | 636 | goto out; |
634 | } else { | 637 | } else { |
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index f2b989dbe25a..0698cccc6223 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c | |||
@@ -78,7 +78,6 @@ static inline void zero_ino_node_unused(struct ubifs_ino_node *ino) | |||
78 | static inline void zero_dent_node_unused(struct ubifs_dent_node *dent) | 78 | static inline void zero_dent_node_unused(struct ubifs_dent_node *dent) |
79 | { | 79 | { |
80 | dent->padding1 = 0; | 80 | dent->padding1 = 0; |
81 | memset(dent->padding2, 0, 4); | ||
82 | } | 81 | } |
83 | 82 | ||
84 | /** | 83 | /** |
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 0d751297873e..1bba4c8b5d3d 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c | |||
@@ -1783,7 +1783,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu) | |||
1783 | * @node: the node is returned here | 1783 | * @node: the node is returned here |
1784 | * @nm: node name | 1784 | * @nm: node name |
1785 | * | 1785 | * |
1786 | * This function look up and reads a node which contains name hash in the key. | 1786 | * This function looks up and reads a node which contains name hash in the key. |
1787 | * Since the hash may have collisions, there may be many nodes with the same | 1787 | * Since the hash may have collisions, there may be many nodes with the same |
1788 | * key, so we have to sequentially look to all of them until the needed one is | 1788 | * key, so we have to sequentially look to all of them until the needed one is |
1789 | * found. This function returns zero in case of success, %-ENOENT if the node | 1789 | * found. This function returns zero in case of success, %-ENOENT if the node |
@@ -1831,7 +1831,7 @@ out_unlock: | |||
1831 | * @node: the node is returned here | 1831 | * @node: the node is returned here |
1832 | * @nm: node name | 1832 | * @nm: node name |
1833 | * | 1833 | * |
1834 | * This function look up and reads a node which contains name hash in the key. | 1834 | * This function looks up and reads a node which contains name hash in the key. |
1835 | * Since the hash may have collisions, there may be many nodes with the same | 1835 | * Since the hash may have collisions, there may be many nodes with the same |
1836 | * key, so we have to sequentially look to all of them until the needed one is | 1836 | * key, so we have to sequentially look to all of them until the needed one is |
1837 | * found. This function returns zero in case of success, %-ENOENT if the node | 1837 | * found. This function returns zero in case of success, %-ENOENT if the node |
@@ -1859,9 +1859,95 @@ int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, | |||
1859 | * Unluckily, there are hash collisions and we have to iterate over | 1859 | * Unluckily, there are hash collisions and we have to iterate over |
1860 | * them look at each direntry with colliding name hash sequentially. | 1860 | * them look at each direntry with colliding name hash sequentially. |
1861 | */ | 1861 | */ |
1862 | |||
1862 | return do_lookup_nm(c, key, node, nm); | 1863 | return do_lookup_nm(c, key, node, nm); |
1863 | } | 1864 | } |
1864 | 1865 | ||
1866 | static int do_lookup_dh(struct ubifs_info *c, const union ubifs_key *key, | ||
1867 | struct ubifs_dent_node *dent, uint32_t cookie) | ||
1868 | { | ||
1869 | int n, err, type = key_type(c, key); | ||
1870 | struct ubifs_znode *znode; | ||
1871 | struct ubifs_zbranch *zbr; | ||
1872 | union ubifs_key *dkey, start_key; | ||
1873 | |||
1874 | ubifs_assert(is_hash_key(c, key)); | ||
1875 | |||
1876 | lowest_dent_key(c, &start_key, key_inum(c, key)); | ||
1877 | |||
1878 | mutex_lock(&c->tnc_mutex); | ||
1879 | err = ubifs_lookup_level0(c, &start_key, &znode, &n); | ||
1880 | if (unlikely(err < 0)) | ||
1881 | goto out_unlock; | ||
1882 | |||
1883 | for (;;) { | ||
1884 | if (!err) { | ||
1885 | err = tnc_next(c, &znode, &n); | ||
1886 | if (err) | ||
1887 | goto out_unlock; | ||
1888 | } | ||
1889 | |||
1890 | zbr = &znode->zbranch[n]; | ||
1891 | dkey = &zbr->key; | ||
1892 | |||
1893 | if (key_inum(c, dkey) != key_inum(c, key) || | ||
1894 | key_type(c, dkey) != type) { | ||
1895 | err = -ENOENT; | ||
1896 | goto out_unlock; | ||
1897 | } | ||
1898 | |||
1899 | err = tnc_read_hashed_node(c, zbr, dent); | ||
1900 | if (err) | ||
1901 | goto out_unlock; | ||
1902 | |||
1903 | if (key_hash(c, key) == key_hash(c, dkey) && | ||
1904 | le32_to_cpu(dent->cookie) == cookie) | ||
1905 | goto out_unlock; | ||
1906 | } | ||
1907 | |||
1908 | out_unlock: | ||
1909 | mutex_unlock(&c->tnc_mutex); | ||
1910 | return err; | ||
1911 | } | ||
1912 | |||
1913 | /** | ||
1914 | * ubifs_tnc_lookup_dh - look up a "double hashed" node. | ||
1915 | * @c: UBIFS file-system description object | ||
1916 | * @key: node key to lookup | ||
1917 | * @node: the node is returned here | ||
1918 | * @cookie: node cookie for collision resolution | ||
1919 | * | ||
1920 | * This function looks up and reads a node which contains name hash in the key. | ||
1921 | * Since the hash may have collisions, there may be many nodes with the same | ||
1922 | * key, so we have to sequentially look to all of them until the needed one | ||
1923 | * with the same cookie value is found. | ||
1924 | * This function returns zero in case of success, %-ENOENT if the node | ||
1925 | * was not found, and a negative error code in case of failure. | ||
1926 | */ | ||
1927 | int ubifs_tnc_lookup_dh(struct ubifs_info *c, const union ubifs_key *key, | ||
1928 | void *node, uint32_t cookie) | ||
1929 | { | ||
1930 | int err; | ||
1931 | const struct ubifs_dent_node *dent = node; | ||
1932 | |||
1933 | /* | ||
1934 | * We assume that in most of the cases there are no name collisions and | ||
1935 | * 'ubifs_tnc_lookup()' returns us the right direntry. | ||
1936 | */ | ||
1937 | err = ubifs_tnc_lookup(c, key, node); | ||
1938 | if (err) | ||
1939 | return err; | ||
1940 | |||
1941 | if (le32_to_cpu(dent->cookie) == cookie) | ||
1942 | return 0; | ||
1943 | |||
1944 | /* | ||
1945 | * Unluckily, there are hash collisions and we have to iterate over | ||
1946 | * them look at each direntry with colliding name hash sequentially. | ||
1947 | */ | ||
1948 | return do_lookup_dh(c, key, node, cookie); | ||
1949 | } | ||
1950 | |||
1865 | /** | 1951 | /** |
1866 | * correct_parent_keys - correct parent znodes' keys. | 1952 | * correct_parent_keys - correct parent znodes' keys. |
1867 | * @c: UBIFS file-system description object | 1953 | * @c: UBIFS file-system description object |
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index e46331dcca4c..249124d9a801 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h | |||
@@ -530,7 +530,8 @@ struct ubifs_ino_node { | |||
530 | * @padding1: reserved for future, zeroes | 530 | * @padding1: reserved for future, zeroes |
531 | * @type: type of the target inode (%UBIFS_ITYPE_REG, %UBIFS_ITYPE_DIR, etc) | 531 | * @type: type of the target inode (%UBIFS_ITYPE_REG, %UBIFS_ITYPE_DIR, etc) |
532 | * @nlen: name length | 532 | * @nlen: name length |
533 | * @padding2: reserved for future, zeroes | 533 | * @cookie: A 32bits random number, used to construct a 64bits |
534 | * identifier. | ||
534 | * @name: zero-terminated name | 535 | * @name: zero-terminated name |
535 | * | 536 | * |
536 | * Note, do not forget to amend 'zero_dent_node_unused()' function when | 537 | * Note, do not forget to amend 'zero_dent_node_unused()' function when |
@@ -543,7 +544,7 @@ struct ubifs_dent_node { | |||
543 | __u8 padding1; | 544 | __u8 padding1; |
544 | __u8 type; | 545 | __u8 type; |
545 | __le16 nlen; | 546 | __le16 nlen; |
546 | __u8 padding2[4]; /* Watch 'zero_dent_node_unused()' if changing! */ | 547 | __le32 cookie; |
547 | __u8 name[]; | 548 | __u8 name[]; |
548 | } __packed; | 549 | } __packed; |
549 | 550 | ||
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 8ccd19257a81..a80610758543 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
@@ -1571,6 +1571,8 @@ int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key, | |||
1571 | struct ubifs_znode **zn, int *n); | 1571 | struct ubifs_znode **zn, int *n); |
1572 | int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, | 1572 | int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, |
1573 | void *node, const struct fscrypt_name *nm); | 1573 | void *node, const struct fscrypt_name *nm); |
1574 | int ubifs_tnc_lookup_dh(struct ubifs_info *c, const union ubifs_key *key, | ||
1575 | void *node, uint32_t secondary_hash); | ||
1574 | int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, | 1576 | int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, |
1575 | void *node, int *lnum, int *offs); | 1577 | void *node, int *lnum, int *offs); |
1576 | int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, | 1578 | int ubifs_tnc_add(struct ubifs_info *c, const union ubifs_key *key, int lnum, |