diff options
author | Matthew Wilcox <willy@infradead.org> | 2017-12-01 00:06:52 -0500 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2018-10-21 10:45:59 -0400 |
commit | 64d3e9a9e0cc51957d243dd2b0adc5d74ff5e128 (patch) | |
tree | 2e829cc456ea717293f388f283e2c29242cb8df7 /lib/xarray.c | |
parent | 687149fca1f37c447e5d161e0a4a04cb2c880cb6 (diff) |
xarray: Step through an XArray
The xas_next and xas_prev functions move the xas index by one position,
and adjust the rest of the iterator state to match it. This is more
efficient than calling xas_set() as it keeps the iterator at the leaves
of the tree instead of walking the iterator from the root each time.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/lib/xarray.c b/lib/xarray.c index 057dbe0d3bf6..303c46579598 100644 --- a/lib/xarray.c +++ b/lib/xarray.c | |||
@@ -876,6 +876,80 @@ void xas_pause(struct xa_state *xas) | |||
876 | } | 876 | } |
877 | EXPORT_SYMBOL_GPL(xas_pause); | 877 | EXPORT_SYMBOL_GPL(xas_pause); |
878 | 878 | ||
879 | /* | ||
880 | * __xas_prev() - Find the previous entry in the XArray. | ||
881 | * @xas: XArray operation state. | ||
882 | * | ||
883 | * Helper function for xas_prev() which handles all the complex cases | ||
884 | * out of line. | ||
885 | */ | ||
886 | void *__xas_prev(struct xa_state *xas) | ||
887 | { | ||
888 | void *entry; | ||
889 | |||
890 | if (!xas_frozen(xas->xa_node)) | ||
891 | xas->xa_index--; | ||
892 | if (xas_not_node(xas->xa_node)) | ||
893 | return xas_load(xas); | ||
894 | |||
895 | if (xas->xa_offset != get_offset(xas->xa_index, xas->xa_node)) | ||
896 | xas->xa_offset--; | ||
897 | |||
898 | while (xas->xa_offset == 255) { | ||
899 | xas->xa_offset = xas->xa_node->offset - 1; | ||
900 | xas->xa_node = xa_parent(xas->xa, xas->xa_node); | ||
901 | if (!xas->xa_node) | ||
902 | return set_bounds(xas); | ||
903 | } | ||
904 | |||
905 | for (;;) { | ||
906 | entry = xa_entry(xas->xa, xas->xa_node, xas->xa_offset); | ||
907 | if (!xa_is_node(entry)) | ||
908 | return entry; | ||
909 | |||
910 | xas->xa_node = xa_to_node(entry); | ||
911 | xas_set_offset(xas); | ||
912 | } | ||
913 | } | ||
914 | EXPORT_SYMBOL_GPL(__xas_prev); | ||
915 | |||
916 | /* | ||
917 | * __xas_next() - Find the next entry in the XArray. | ||
918 | * @xas: XArray operation state. | ||
919 | * | ||
920 | * Helper function for xas_next() which handles all the complex cases | ||
921 | * out of line. | ||
922 | */ | ||
923 | void *__xas_next(struct xa_state *xas) | ||
924 | { | ||
925 | void *entry; | ||
926 | |||
927 | if (!xas_frozen(xas->xa_node)) | ||
928 | xas->xa_index++; | ||
929 | if (xas_not_node(xas->xa_node)) | ||
930 | return xas_load(xas); | ||
931 | |||
932 | if (xas->xa_offset != get_offset(xas->xa_index, xas->xa_node)) | ||
933 | xas->xa_offset++; | ||
934 | |||
935 | while (xas->xa_offset == XA_CHUNK_SIZE) { | ||
936 | xas->xa_offset = xas->xa_node->offset + 1; | ||
937 | xas->xa_node = xa_parent(xas->xa, xas->xa_node); | ||
938 | if (!xas->xa_node) | ||
939 | return set_bounds(xas); | ||
940 | } | ||
941 | |||
942 | for (;;) { | ||
943 | entry = xa_entry(xas->xa, xas->xa_node, xas->xa_offset); | ||
944 | if (!xa_is_node(entry)) | ||
945 | return entry; | ||
946 | |||
947 | xas->xa_node = xa_to_node(entry); | ||
948 | xas_set_offset(xas); | ||
949 | } | ||
950 | } | ||
951 | EXPORT_SYMBOL_GPL(__xas_next); | ||
952 | |||
879 | /** | 953 | /** |
880 | * xas_find() - Find the next present entry in the XArray. | 954 | * xas_find() - Find the next present entry in the XArray. |
881 | * @xas: XArray operation state. | 955 | * @xas: XArray operation state. |