Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm array: introduce cursor api

More efficient way to iterate an array due to prefetching (makes use of
the new dm_btree_cursor_* api).

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>

authored by

Joe Thornber and committed by
Mike Snitzer
fdd1315a 7d111c81

+119
+86
drivers/md/persistent-data/dm-array.c
··· 899 899 EXPORT_SYMBOL_GPL(dm_array_walk); 900 900 901 901 /*----------------------------------------------------------------*/ 902 + 903 + static int load_ablock(struct dm_array_cursor *c) 904 + { 905 + int r; 906 + __le64 value_le; 907 + uint64_t key; 908 + 909 + if (c->block) 910 + unlock_ablock(c->info, c->block); 911 + 912 + c->block = NULL; 913 + c->ab = NULL; 914 + c->index = 0; 915 + 916 + r = dm_btree_cursor_get_value(&c->cursor, &key, &value_le); 917 + if (r) { 918 + DMERR("dm_btree_cursor_get_value failed"); 919 + dm_btree_cursor_end(&c->cursor); 920 + 921 + } else { 922 + r = get_ablock(c->info, le64_to_cpu(value_le), &c->block, &c->ab); 923 + if (r) { 924 + DMERR("get_ablock failed"); 925 + dm_btree_cursor_end(&c->cursor); 926 + } 927 + } 928 + 929 + return r; 930 + } 931 + 932 + int dm_array_cursor_begin(struct dm_array_info *info, dm_block_t root, 933 + struct dm_array_cursor *c) 934 + { 935 + int r; 936 + 937 + memset(c, 0, sizeof(*c)); 938 + c->info = info; 939 + r = dm_btree_cursor_begin(&info->btree_info, root, true, &c->cursor); 940 + if (r) { 941 + DMERR("couldn't create btree cursor"); 942 + return r; 943 + } 944 + 945 + return load_ablock(c); 946 + } 947 + EXPORT_SYMBOL_GPL(dm_array_cursor_begin); 948 + 949 + void dm_array_cursor_end(struct dm_array_cursor *c) 950 + { 951 + if (c->block) { 952 + unlock_ablock(c->info, c->block); 953 + dm_btree_cursor_end(&c->cursor); 954 + } 955 + } 956 + EXPORT_SYMBOL_GPL(dm_array_cursor_end); 957 + 958 + int dm_array_cursor_next(struct dm_array_cursor *c) 959 + { 960 + int r; 961 + 962 + if (!c->block) 963 + return -ENODATA; 964 + 965 + c->index++; 966 + 967 + if (c->index >= le32_to_cpu(c->ab->nr_entries)) { 968 + r = dm_btree_cursor_next(&c->cursor); 969 + if (r) 970 + return r; 971 + 972 + r = load_ablock(c); 973 + if (r) 974 + return r; 975 + } 976 + 977 + return 0; 978 + } 979 + EXPORT_SYMBOL_GPL(dm_array_cursor_next); 980 + 981 + void dm_array_cursor_get_value(struct dm_array_cursor *c, void **value_le) 982 + { 983 + *value_le = element_at(c->info, c->ab, c->index); 984 + } 985 + EXPORT_SYMBOL_GPL(dm_array_cursor_get_value); 986 + 987 + /*----------------------------------------------------------------*/
+33
drivers/md/persistent-data/dm-array.h
··· 182 182 183 183 /*----------------------------------------------------------------*/ 184 184 185 + /* 186 + * Cursor api. 187 + * 188 + * This lets you iterate through all the entries in an array efficiently 189 + * (it will preload metadata). 190 + * 191 + * I'm using a cursor, rather than a walk function with a callback because 192 + * the cache target needs to iterate both the mapping and hint arrays in 193 + * unison. 194 + */ 195 + struct dm_array_cursor { 196 + struct dm_array_info *info; 197 + struct dm_btree_cursor cursor; 198 + 199 + struct dm_block *block; 200 + struct array_block *ab; 201 + unsigned index; 202 + }; 203 + 204 + int dm_array_cursor_begin(struct dm_array_info *info, 205 + dm_block_t root, struct dm_array_cursor *c); 206 + void dm_array_cursor_end(struct dm_array_cursor *c); 207 + 208 + uint32_t dm_array_cursor_index(struct dm_array_cursor *c); 209 + int dm_array_cursor_next(struct dm_array_cursor *c); 210 + 211 + /* 212 + * value_le is only valid while the cursor points at the current value. 213 + */ 214 + void dm_array_cursor_get_value(struct dm_array_cursor *c, void **value_le); 215 + 216 + /*----------------------------------------------------------------*/ 217 + 185 218 #endif /* _LINUX_DM_ARRAY_H */