Lines Matching +full:config +full:- +full:cond
1 // SPDX-License-Identifier: GPL-2.0-only
10 #include "memory-alloc.h"
12 #include "funnel-requestqueue.h"
13 #include "hash-utils.h"
14 #include "sparse-cache.h"
22 * committed (either the open chapter or a recently closed one), the index searches the in-memory
61 struct cond_var cond; member
80 return uds_is_chapter_sparse(zone->index->volume->geometry, in is_zone_chapter_sparse()
81 zone->oldest_virtual_chapter, in is_zone_chapter_sparse()
82 zone->newest_virtual_chapter, virtual_chapter); in is_zone_chapter_sparse()
95 request->index = index; in launch_zone_message()
96 request->unbatched = true; in launch_zone_message()
97 request->zone_number = zone; in launch_zone_message()
98 request->zone_message = message; in launch_zone_message()
112 for (zone = 0; zone < index->zone_count; zone++) { in enqueue_barrier_messages()
129 virtual_chapter = uds_lookup_volume_index_name(index->volume_index, in triage_index_request()
130 &request->record_name); in triage_index_request()
134 zone = index->zones[request->zone_number]; in triage_index_request()
147 * Simulate a message to change the sparse cache membership for a single-zone sparse index. This
148 * allows us to forgo the complicated locking required by a multi-zone sparse index. Any other kind
156 if ((zone->index->zone_count > 1) || in simulate_index_zone_barrier_message()
157 !uds_is_sparse_index_geometry(zone->index->volume->geometry)) in simulate_index_zone_barrier_message()
160 sparse_virtual_chapter = triage_index_request(zone->index, request); in simulate_index_zone_barrier_message()
170 struct uds_index *index = request->index; in triage_request()
182 struct chapter_writer *writer = index->chapter_writer; in finish_previous_chapter()
184 mutex_lock(&writer->mutex); in finish_previous_chapter()
185 while (index->newest_virtual_chapter < current_chapter_number) in finish_previous_chapter()
186 uds_wait_cond(&writer->cond, &writer->mutex); in finish_previous_chapter()
187 result = writer->result; in finish_previous_chapter()
188 mutex_unlock(&writer->mutex); in finish_previous_chapter()
201 result = finish_previous_chapter(zone->index, zone->newest_virtual_chapter); in swap_open_chapter()
205 swap(zone->open_chapter, zone->writing_chapter); in swap_open_chapter()
218 struct chapter_writer *writer = index->chapter_writer; in start_closing_chapter()
220 mutex_lock(&writer->mutex); in start_closing_chapter()
221 finished_zones = ++writer->zones_to_write; in start_closing_chapter()
222 writer->chapters[zone_number] = chapter; in start_closing_chapter()
223 uds_broadcast_cond(&writer->cond); in start_closing_chapter()
224 mutex_unlock(&writer->mutex); in start_closing_chapter()
238 for (i = 0; i < zone->index->zone_count; i++) { in announce_chapter_closed()
239 if (zone->id == i) in announce_chapter_closed()
242 result = launch_zone_message(zone_message, i, zone->index); in announce_chapter_closed()
259 (unsigned long long) zone->newest_virtual_chapter, zone->id, in open_next_chapter()
260 zone->open_chapter->size, in open_next_chapter()
261 zone->open_chapter->capacity - zone->open_chapter->size); in open_next_chapter()
267 closed_chapter = zone->newest_virtual_chapter++; in open_next_chapter()
268 uds_set_volume_index_zone_open_chapter(zone->index->volume_index, zone->id, in open_next_chapter()
269 zone->newest_virtual_chapter); in open_next_chapter()
270 uds_reset_open_chapter(zone->open_chapter); in open_next_chapter()
272 finished_zones = start_closing_chapter(zone->index, zone->id, in open_next_chapter()
273 zone->writing_chapter); in open_next_chapter()
274 if ((finished_zones == 1) && (zone->index->zone_count > 1)) { in open_next_chapter()
280 expiring = zone->oldest_virtual_chapter; in open_next_chapter()
281 expire_chapters = uds_chapters_to_expire(zone->index->volume->geometry, in open_next_chapter()
282 zone->newest_virtual_chapter); in open_next_chapter()
283 zone->oldest_virtual_chapter += expire_chapters; in open_next_chapter()
285 if (finished_zones < zone->index->zone_count) in open_next_chapter()
288 while (expire_chapters-- > 0) in open_next_chapter()
289 uds_forget_chapter(zone->index->volume, expiring++); in open_next_chapter()
296 if (zone->newest_virtual_chapter == virtual_chapter) in handle_chapter_closed()
304 struct uds_zone_message *message = &request->zone_message; in dispatch_index_zone_control_request()
305 struct index_zone *zone = request->index->zones[request->zone_number]; in dispatch_index_zone_control_request()
307 switch (message->type) { in dispatch_index_zone_control_request()
309 return uds_update_sparse_cache(zone, message->virtual_chapter); in dispatch_index_zone_control_request()
312 return handle_chapter_closed(zone, message->virtual_chapter); in dispatch_index_zone_control_request()
315 vdo_log_error("invalid message type: %d", message->type); in dispatch_index_zone_control_request()
323 request->location = new_location; in set_request_location()
324 request->found = ((new_location == UDS_LOCATION_IN_OPEN_CHAPTER) || in set_request_location()
332 request->found = true; in set_chapter_location()
333 if (virtual_chapter == zone->newest_virtual_chapter) in set_chapter_location()
334 request->location = UDS_LOCATION_IN_OPEN_CHAPTER; in set_chapter_location()
336 request->location = UDS_LOCATION_IN_SPARSE; in set_chapter_location()
338 request->location = UDS_LOCATION_IN_DENSE; in set_chapter_location()
349 result = uds_search_sparse_cache(zone, &request->record_name, &virtual_chapter, in search_sparse_cache_in_zone()
354 request->virtual_chapter = virtual_chapter; in search_sparse_cache_in_zone()
355 volume = zone->index->volume; in search_sparse_cache_in_zone()
356 chapter = uds_map_to_physical_chapter(volume->geometry, virtual_chapter); in search_sparse_cache_in_zone()
366 if (request->location == UDS_LOCATION_RECORD_PAGE_LOOKUP) { in get_record_from_zone()
369 } else if (request->location == UDS_LOCATION_UNAVAILABLE) { in get_record_from_zone()
374 if (request->virtual_chapter == zone->newest_virtual_chapter) { in get_record_from_zone()
375 uds_search_open_chapter(zone->open_chapter, &request->record_name, in get_record_from_zone()
376 &request->old_metadata, found); in get_record_from_zone()
380 if ((zone->newest_virtual_chapter > 0) && in get_record_from_zone()
381 (request->virtual_chapter == (zone->newest_virtual_chapter - 1)) && in get_record_from_zone()
382 (zone->writing_chapter->size > 0)) { in get_record_from_zone()
383 uds_search_open_chapter(zone->writing_chapter, &request->record_name, in get_record_from_zone()
384 &request->old_metadata, found); in get_record_from_zone()
388 volume = zone->index->volume; in get_record_from_zone()
389 if (is_zone_chapter_sparse(zone, request->virtual_chapter) && in get_record_from_zone()
390 uds_sparse_cache_contains(volume->sparse_cache, request->virtual_chapter, in get_record_from_zone()
391 request->zone_number)) in get_record_from_zone()
393 request->virtual_chapter, found); in get_record_from_zone()
403 remaining = uds_put_open_chapter(zone->open_chapter, &request->record_name, in put_record_in_zone()
419 result = uds_get_volume_index_record(zone->index->volume_index, in search_index_zone()
420 &request->record_name, &record); in search_index_zone()
425 if (request->requeued && request->virtual_chapter != record.virtual_chapter) in search_index_zone()
428 request->virtual_chapter = record.virtual_chapter; in search_index_zone()
444 chapter = zone->newest_virtual_chapter; in search_index_zone()
446 if ((request->type == UDS_QUERY_NO_UPDATE) || in search_index_zone()
447 ((request->type == UDS_QUERY) && overflow_record)) { in search_index_zone()
459 } else if (request->type != UDS_UPDATE) { in search_index_zone()
469 if (request->location == UDS_LOCATION_RECORD_PAGE_LOOKUP) { in search_index_zone()
471 } else if (request->location == UDS_LOCATION_UNAVAILABLE) { in search_index_zone()
473 } else if (uds_is_sparse_index_geometry(zone->index->volume->geometry) && in search_index_zone()
474 !uds_is_volume_index_sample(zone->index->volume_index, in search_index_zone()
475 &request->record_name)) { in search_index_zone()
485 if ((request->type == UDS_QUERY_NO_UPDATE) || in search_index_zone()
486 ((request->type == UDS_QUERY) && !found)) { in search_index_zone()
509 if (!found || (request->type == UDS_UPDATE)) { in search_index_zone()
511 metadata = &request->new_metadata; in search_index_zone()
514 metadata = &request->old_metadata; in search_index_zone()
525 result = uds_get_volume_index_record(zone->index->volume_index, in remove_from_index_zone()
526 &request->record_name, &record); in remove_from_index_zone()
538 /* Non-collision records are hints, so resolve the name in the chapter. */ in remove_from_index_zone()
541 if (request->requeued && request->virtual_chapter != record.virtual_chapter) in remove_from_index_zone()
544 request->virtual_chapter = record.virtual_chapter; in remove_from_index_zone()
570 if (request->location == UDS_LOCATION_IN_OPEN_CHAPTER) in remove_from_index_zone()
571 uds_remove_from_open_chapter(zone->open_chapter, &request->record_name); in remove_from_index_zone()
579 struct index_zone *zone = index->zones[request->zone_number]; in dispatch_index_request()
581 if (!request->requeued) { in dispatch_index_request()
587 switch (request->type) { in dispatch_index_request()
602 request->type); in dispatch_index_request()
613 struct uds_index *index = request->index; in execute_zone_request()
615 if (request->zone_message.type != UDS_MESSAGE_NONE) { in execute_zone_request()
619 request->zone_message.type); in execute_zone_request()
627 index->need_to_save = true; in execute_zone_request()
628 if (request->requeued && (request->status != UDS_SUCCESS)) { in execute_zone_request()
630 index->callback(request); in execute_zone_request()
640 if (!request->found) in execute_zone_request()
643 request->status = result; in execute_zone_request()
644 index->callback(request); in execute_zone_request()
653 for (i = 0; i < index->zone_count; i++) { in initialize_index_queues()
655 &index->zone_queues[i]); in initialize_index_queues()
660 /* The triage queue is only needed for sparse multi-zone indexes. */ in initialize_index_queues()
661 if ((index->zone_count > 1) && uds_is_sparse_index_geometry(geometry)) { in initialize_index_queues()
663 &index->triage_queue); in initialize_index_queues()
676 struct uds_index *index = writer->index; in close_chapters()
679 mutex_lock(&writer->mutex); in close_chapters()
681 while (writer->zones_to_write < index->zone_count) { in close_chapters()
682 if (writer->stop && (writer->zones_to_write == 0)) { in close_chapters()
687 mutex_unlock(&writer->mutex); in close_chapters()
691 uds_wait_cond(&writer->cond, &writer->mutex); in close_chapters()
699 mutex_unlock(&writer->mutex); in close_chapters()
701 if (index->has_saved_open_chapter) { in close_chapters()
708 index->has_saved_open_chapter = false; in close_chapters()
709 result = uds_discard_open_chapter(index->layout); in close_chapters()
714 result = uds_close_open_chapter(writer->chapters, index->zone_count, in close_chapters()
715 index->volume, in close_chapters()
716 writer->open_chapter_index, in close_chapters()
717 writer->collated_records, in close_chapters()
718 index->newest_virtual_chapter); in close_chapters()
720 mutex_lock(&writer->mutex); in close_chapters()
721 index->newest_virtual_chapter++; in close_chapters()
722 index->oldest_virtual_chapter += in close_chapters()
723 uds_chapters_to_expire(index->volume->geometry, in close_chapters()
724 index->newest_virtual_chapter); in close_chapters()
725 writer->result = result; in close_chapters()
726 writer->zones_to_write = 0; in close_chapters()
727 uds_broadcast_cond(&writer->cond); in close_chapters()
735 mutex_lock(&writer->mutex); in stop_chapter_writer()
736 if (writer->thread != NULL) { in stop_chapter_writer()
737 writer_thread = writer->thread; in stop_chapter_writer()
738 writer->thread = NULL; in stop_chapter_writer()
739 writer->stop = true; in stop_chapter_writer()
740 uds_broadcast_cond(&writer->cond); in stop_chapter_writer()
742 mutex_unlock(&writer->mutex); in stop_chapter_writer()
754 uds_free_open_chapter_index(writer->open_chapter_index); in free_chapter_writer()
755 vdo_free(writer->collated_records); in free_chapter_writer()
765 (sizeof(struct uds_volume_record) * index->volume->geometry->records_per_chapter); in make_chapter_writer()
767 result = vdo_allocate_extended(struct chapter_writer, index->zone_count, in make_chapter_writer()
773 writer->index = index; in make_chapter_writer()
774 mutex_init(&writer->mutex); in make_chapter_writer()
775 uds_init_cond(&writer->cond); in make_chapter_writer()
778 &writer->collated_records); in make_chapter_writer()
784 result = uds_make_open_chapter_index(&writer->open_chapter_index, in make_chapter_writer()
785 index->volume->geometry, in make_chapter_writer()
786 index->volume->nonce); in make_chapter_writer()
792 writer->memory_size = (sizeof(struct chapter_writer) + in make_chapter_writer()
793 index->zone_count * sizeof(struct open_chapter_zone *) + in make_chapter_writer()
795 writer->open_chapter_index->memory_size); in make_chapter_writer()
797 result = vdo_create_thread(close_chapters, writer, "writer", &writer->thread); in make_chapter_writer()
812 result = uds_load_index_state(index->layout, index); in load_index()
816 last_save_chapter = ((index->last_save != NO_LAST_SAVE) ? index->last_save : 0); in load_index()
819 (unsigned long long) index->oldest_virtual_chapter, in load_index()
829 struct index_geometry *geometry = index->volume->geometry; in rebuild_index_page_map()
837 index_page_number < geometry->index_pages_per_chapter; in rebuild_index_page_map()
839 result = uds_get_volume_index_page(index->volume, chapter, in rebuild_index_page_map()
848 lowest_delta_list = chapter_index_page->lowest_list_number; in rebuild_index_page_map()
849 highest_delta_list = chapter_index_page->highest_list_number; in rebuild_index_page_map()
856 uds_update_index_page_map(index->volume->index_page_map, vcn, chapter, in rebuild_index_page_map()
872 !uds_is_volume_index_sample(index->volume_index, name)) { in replay_record()
880 result = uds_get_volume_index_record(index->volume_index, name, &record); in replay_record()
910 result = uds_search_volume_page_cache_for_rebuild(index->volume, in replay_record()
932 * we would want to un-sparsify if it did exist. in replay_record()
949 if (index->load_context == NULL) in check_for_suspend()
952 mutex_lock(&index->load_context->mutex); in check_for_suspend()
953 if (index->load_context->status != INDEX_SUSPENDING) { in check_for_suspend()
954 mutex_unlock(&index->load_context->mutex); in check_for_suspend()
959 index->load_context->status = INDEX_SUSPENDED; in check_for_suspend()
960 uds_broadcast_cond(&index->load_context->cond); in check_for_suspend()
962 while ((index->load_context->status != INDEX_OPENING) && in check_for_suspend()
963 (index->load_context->status != INDEX_FREEING)) in check_for_suspend()
964 uds_wait_cond(&index->load_context->cond, &index->load_context->mutex); in check_for_suspend()
966 closing = (index->load_context->status == INDEX_FREEING); in check_for_suspend()
967 mutex_unlock(&index->load_context->mutex); in check_for_suspend()
982 return -EBUSY; in replay_chapter()
985 geometry = index->volume->geometry; in replay_chapter()
987 uds_prefetch_volume_chapter(index->volume, physical_chapter); in replay_chapter()
988 uds_set_volume_index_open_chapter(index->volume_index, virtual); in replay_chapter()
997 for (i = 0; i < geometry->record_pages_per_chapter; i++) { in replay_chapter()
1001 record_page_number = geometry->index_pages_per_chapter + i; in replay_chapter()
1002 result = uds_get_volume_record_page(index->volume, physical_chapter, in replay_chapter()
1009 for (j = 0; j < geometry->records_per_page; j++) { in replay_chapter()
1030 u64 from_virtual = index->oldest_virtual_chapter; in replay_volume()
1031 u64 upto_virtual = index->newest_virtual_chapter; in replay_volume()
1040 * in order, skipping non-hooks in chapters which will be sparse to save time. in replay_volume()
1044 * on-disk volume. Also skip the on-disk chapter corresponding to upto_virtual, as this in replay_volume()
1049 old_map_update = index->volume->index_page_map->last_update; in replay_volume()
1051 will_be_sparse = uds_is_chapter_sparse(index->volume->geometry, in replay_volume()
1060 uds_set_volume_index_open_chapter(index->volume_index, upto_virtual); in replay_volume()
1062 new_map_update = index->volume->index_page_map->last_update; in replay_volume()
1078 u32 chapters_per_volume = index->volume->geometry->chapters_per_volume; in rebuild_index()
1080 index->volume->lookup_mode = LOOKUP_FOR_REBUILD; in rebuild_index()
1081 result = uds_find_volume_chapter_boundaries(index->volume, &lowest, &highest, in rebuild_index()
1089 index->newest_virtual_chapter = 0; in rebuild_index()
1090 index->oldest_virtual_chapter = 0; in rebuild_index()
1091 index->volume->lookup_mode = LOOKUP_NORMAL; in rebuild_index()
1095 index->newest_virtual_chapter = highest + 1; in rebuild_index()
1096 index->oldest_virtual_chapter = lowest; in rebuild_index()
1097 if (index->newest_virtual_chapter == in rebuild_index()
1098 (index->oldest_virtual_chapter + chapters_per_volume)) { in rebuild_index()
1100 index->oldest_virtual_chapter++; in rebuild_index()
1107 index->volume->lookup_mode = LOOKUP_NORMAL; in rebuild_index()
1116 uds_free_open_chapter(zone->open_chapter); in free_index_zone()
1117 uds_free_open_chapter(zone->writing_chapter); in free_index_zone()
1130 result = uds_make_open_chapter(index->volume->geometry, index->zone_count, in make_index_zone()
1131 &zone->open_chapter); in make_index_zone()
1137 result = uds_make_open_chapter(index->volume->geometry, index->zone_count, in make_index_zone()
1138 &zone->writing_chapter); in make_index_zone()
1144 zone->index = index; in make_index_zone()
1145 zone->id = zone_number; in make_index_zone()
1146 index->zones[zone_number] = zone; in make_index_zone()
1151 int uds_make_index(struct uds_configuration *config, enum uds_open_index_type open_type, in uds_make_index() argument
1163 result = vdo_allocate_extended(struct uds_index, config->zone_count, in uds_make_index()
1168 index->zone_count = config->zone_count; in uds_make_index()
1170 result = uds_make_index_layout(config, new, &index->layout); in uds_make_index()
1176 result = vdo_allocate(index->zone_count, struct index_zone *, "zones", in uds_make_index()
1177 &index->zones); in uds_make_index()
1183 result = uds_make_volume(config, index->layout, &index->volume); in uds_make_index()
1189 index->volume->lookup_mode = LOOKUP_NORMAL; in uds_make_index()
1190 for (z = 0; z < index->zone_count; z++) { in uds_make_index()
1199 nonce = uds_get_volume_nonce(index->layout); in uds_make_index()
1200 result = uds_make_volume_index(config, nonce, &index->volume_index); in uds_make_index()
1206 index->load_context = load_context; in uds_make_index()
1207 index->callback = callback; in uds_make_index()
1209 result = initialize_index_queues(index, config->geometry); in uds_make_index()
1215 result = make_chapter_writer(index, &index->chapter_writer); in uds_make_index()
1227 case -ENOMEM: in uds_make_index()
1249 for (z = 0; z < index->zone_count; z++) { in uds_make_index()
1250 zone = index->zones[z]; in uds_make_index()
1251 zone->oldest_virtual_chapter = index->oldest_virtual_chapter; in uds_make_index()
1252 zone->newest_virtual_chapter = index->newest_virtual_chapter; in uds_make_index()
1255 if (index->load_context != NULL) { in uds_make_index()
1256 mutex_lock(&index->load_context->mutex); in uds_make_index()
1257 index->load_context->status = INDEX_READY; in uds_make_index()
1262 uds_broadcast_cond(&index->load_context->cond); in uds_make_index()
1263 mutex_unlock(&index->load_context->mutex); in uds_make_index()
1266 index->has_saved_open_chapter = loaded; in uds_make_index()
1267 index->need_to_save = !loaded; in uds_make_index()
1279 uds_request_queue_finish(index->triage_queue); in uds_free_index()
1280 for (i = 0; i < index->zone_count; i++) in uds_free_index()
1281 uds_request_queue_finish(index->zone_queues[i]); in uds_free_index()
1283 free_chapter_writer(index->chapter_writer); in uds_free_index()
1285 uds_free_volume_index(index->volume_index); in uds_free_index()
1286 if (index->zones != NULL) { in uds_free_index()
1287 for (i = 0; i < index->zone_count; i++) in uds_free_index()
1288 free_index_zone(index->zones[i]); in uds_free_index()
1289 vdo_free(index->zones); in uds_free_index()
1292 uds_free_volume(index->volume); in uds_free_index()
1293 uds_free_index_layout(vdo_forget(index->layout)); in uds_free_index()
1300 struct chapter_writer *writer = index->chapter_writer; in uds_wait_for_idle_index()
1302 mutex_lock(&writer->mutex); in uds_wait_for_idle_index()
1303 while (writer->zones_to_write > 0) in uds_wait_for_idle_index()
1304 uds_wait_cond(&writer->cond, &writer->mutex); in uds_wait_for_idle_index()
1305 mutex_unlock(&writer->mutex); in uds_wait_for_idle_index()
1313 if (!index->need_to_save) in uds_save_index()
1317 index->prev_save = index->last_save; in uds_save_index()
1318 index->last_save = ((index->newest_virtual_chapter == 0) ? in uds_save_index()
1319 NO_LAST_SAVE : index->newest_virtual_chapter - 1); in uds_save_index()
1320 vdo_log_info("beginning save (vcn %llu)", (unsigned long long) index->last_save); in uds_save_index()
1322 result = uds_save_index_state(index->layout, index); in uds_save_index()
1325 index->last_save = index->prev_save; in uds_save_index()
1327 index->has_saved_open_chapter = true; in uds_save_index()
1328 index->need_to_save = false; in uds_save_index()
1330 (unsigned long long) index->last_save); in uds_save_index()
1338 return uds_replace_volume_storage(index->volume, index->layout, bdev); in uds_replace_index_storage()
1346 uds_get_volume_index_stats(index->volume_index, &stats); in uds_get_index_stats()
1347 counters->entries_indexed = stats.record_count; in uds_get_index_stats()
1348 counters->collisions = stats.collision_count; in uds_get_index_stats()
1349 counters->entries_discarded = stats.discard_count; in uds_get_index_stats()
1351 counters->memory_used = (index->volume_index->memory_size + in uds_get_index_stats()
1352 index->volume->cache_size + in uds_get_index_stats()
1353 index->chapter_writer->memory_size); in uds_get_index_stats()
1358 struct uds_index *index = request->index; in uds_enqueue_request()
1363 if (index->triage_queue != NULL) { in uds_enqueue_request()
1364 queue = index->triage_queue; in uds_enqueue_request()
1371 request->zone_number = in uds_enqueue_request()
1372 uds_get_volume_index_zone(index->volume_index, &request->record_name); in uds_enqueue_request()
1376 queue = index->zone_queues[request->zone_number]; in uds_enqueue_request()