diff options
| author | Matthew Wilcox <willy@infradead.org> | 2018-06-01 22:46:02 -0400 |
|---|---|---|
| committer | Matthew Wilcox <willy@infradead.org> | 2018-10-21 10:45:59 -0400 |
| commit | 4e99d4e9579d3b950bf4b38d0d64eb1b9be78761 (patch) | |
| tree | a3ecd9d06b4f0eb8bb05369887c9fbe133218e01 /lib/xarray.c | |
| parent | 64d3e9a9e0cc51957d243dd2b0adc5d74ff5e128 (diff) | |
xarray: Add xas_for_each_conflict
This iterator iterates over each entry that is stored in the index or
indices specified by the xa_state. This is intended for use for a
conditional store of a multiindex entry, or to allow entries which are
about to be removed from the xarray to be disposed of properly.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'lib/xarray.c')
| -rw-r--r-- | lib/xarray.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/lib/xarray.c b/lib/xarray.c index 303c46579598..41f8ebc651f5 100644 --- a/lib/xarray.c +++ b/lib/xarray.c | |||
| @@ -1111,6 +1111,67 @@ max: | |||
| 1111 | EXPORT_SYMBOL_GPL(xas_find_marked); | 1111 | EXPORT_SYMBOL_GPL(xas_find_marked); |
| 1112 | 1112 | ||
| 1113 | /** | 1113 | /** |
| 1114 | * xas_find_conflict() - Find the next present entry in a range. | ||
| 1115 | * @xas: XArray operation state. | ||
| 1116 | * | ||
| 1117 | * The @xas describes both a range and a position within that range. | ||
| 1118 | * | ||
| 1119 | * Context: Any context. Expects xa_lock to be held. | ||
| 1120 | * Return: The next entry in the range covered by @xas or %NULL. | ||
| 1121 | */ | ||
| 1122 | void *xas_find_conflict(struct xa_state *xas) | ||
| 1123 | { | ||
| 1124 | void *curr; | ||
| 1125 | |||
| 1126 | if (xas_error(xas)) | ||
| 1127 | return NULL; | ||
| 1128 | |||
| 1129 | if (!xas->xa_node) | ||
| 1130 | return NULL; | ||
| 1131 | |||
| 1132 | if (xas_top(xas->xa_node)) { | ||
| 1133 | curr = xas_start(xas); | ||
| 1134 | if (!curr) | ||
| 1135 | return NULL; | ||
| 1136 | while (xa_is_node(curr)) { | ||
| 1137 | struct xa_node *node = xa_to_node(curr); | ||
| 1138 | curr = xas_descend(xas, node); | ||
| 1139 | } | ||
| 1140 | if (curr) | ||
| 1141 | return curr; | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | if (xas->xa_node->shift > xas->xa_shift) | ||
| 1145 | return NULL; | ||
| 1146 | |||
| 1147 | for (;;) { | ||
| 1148 | if (xas->xa_node->shift == xas->xa_shift) { | ||
| 1149 | if ((xas->xa_offset & xas->xa_sibs) == xas->xa_sibs) | ||
| 1150 | break; | ||
| 1151 | } else if (xas->xa_offset == XA_CHUNK_MASK) { | ||
| 1152 | xas->xa_offset = xas->xa_node->offset; | ||
| 1153 | xas->xa_node = xa_parent_locked(xas->xa, xas->xa_node); | ||
| 1154 | if (!xas->xa_node) | ||
| 1155 | break; | ||
| 1156 | continue; | ||
| 1157 | } | ||
| 1158 | curr = xa_entry_locked(xas->xa, xas->xa_node, ++xas->xa_offset); | ||
| 1159 | if (xa_is_sibling(curr)) | ||
| 1160 | continue; | ||
| 1161 | while (xa_is_node(curr)) { | ||
| 1162 | xas->xa_node = xa_to_node(curr); | ||
| 1163 | xas->xa_offset = 0; | ||
| 1164 | curr = xa_entry_locked(xas->xa, xas->xa_node, 0); | ||
| 1165 | } | ||
| 1166 | if (curr) | ||
| 1167 | return curr; | ||
| 1168 | } | ||
| 1169 | xas->xa_offset -= xas->xa_sibs; | ||
| 1170 | return NULL; | ||
| 1171 | } | ||
| 1172 | EXPORT_SYMBOL_GPL(xas_find_conflict); | ||
| 1173 | |||
| 1174 | /** | ||
| 1114 | * xa_init_flags() - Initialise an empty XArray with flags. | 1175 | * xa_init_flags() - Initialise an empty XArray with flags. |
| 1115 | * @xa: XArray. | 1176 | * @xa: XArray. |
| 1116 | * @flags: XA_FLAG values. | 1177 | * @flags: XA_FLAG values. |
