| 1250 | } |
| 1251 | |
| 1252 | static int |
| 1253 | sync_status(struct rte_memseg_list *primary_msl, |
| 1254 | struct rte_memseg_list *local_msl, struct hugepage_info *hi, |
| 1255 | unsigned int msl_idx, bool used) |
| 1256 | { |
| 1257 | struct rte_fbarray *l_arr, *p_arr; |
| 1258 | int p_idx, l_chunk_len, p_chunk_len, ret; |
| 1259 | int start, end; |
| 1260 | |
| 1261 | /* this is a little bit tricky, but the basic idea is - walk both lists |
| 1262 | * and spot any places where there are discrepancies. walking both lists |
| 1263 | * and noting discrepancies in a single go is a hard problem, so we do |
| 1264 | * it in two passes - first we spot any places where allocated segments |
| 1265 | * mismatch (i.e. ensure that everything that's allocated in the primary |
| 1266 | * is also allocated in the secondary), and then we do it by looking at |
| 1267 | * free segments instead. |
| 1268 | * |
| 1269 | * we also need to aggregate changes into chunks, as we have to call |
| 1270 | * callbacks per allocation, not per page. |
| 1271 | */ |
| 1272 | l_arr = &local_msl->memseg_arr; |
| 1273 | p_arr = &primary_msl->memseg_arr; |
| 1274 | |
| 1275 | if (used) |
| 1276 | p_idx = rte_fbarray_find_next_used(p_arr, 0); |
| 1277 | else |
| 1278 | p_idx = rte_fbarray_find_next_free(p_arr, 0); |
| 1279 | |
| 1280 | while (p_idx >= 0) { |
| 1281 | int next_chunk_search_idx; |
| 1282 | |
| 1283 | if (used) { |
| 1284 | p_chunk_len = rte_fbarray_find_contig_used(p_arr, |
| 1285 | p_idx); |
| 1286 | l_chunk_len = rte_fbarray_find_contig_used(l_arr, |
| 1287 | p_idx); |
| 1288 | } else { |
| 1289 | p_chunk_len = rte_fbarray_find_contig_free(p_arr, |
| 1290 | p_idx); |
| 1291 | l_chunk_len = rte_fbarray_find_contig_free(l_arr, |
| 1292 | p_idx); |
| 1293 | } |
| 1294 | /* best case scenario - no differences (or bigger, which will be |
| 1295 | * fixed during next iteration), look for next chunk |
| 1296 | */ |
| 1297 | if (l_chunk_len >= p_chunk_len) { |
| 1298 | next_chunk_search_idx = p_idx + p_chunk_len; |
| 1299 | goto next_chunk; |
| 1300 | } |
| 1301 | |
| 1302 | /* if both chunks start at the same point, skip parts we know |
| 1303 | * are identical, and sync the rest. each call to sync_chunk |
| 1304 | * will only sync contiguous segments, so we need to call this |
| 1305 | * until we are sure there are no more differences in this |
| 1306 | * chunk. |
| 1307 | */ |
| 1308 | start = p_idx + l_chunk_len; |
| 1309 | end = p_idx + p_chunk_len; |
no test coverage detected