Lines Matching +full:sync +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
13 #include <linux/dm-io.h>
14 #include <linux/dm-dirty-log.h>
16 #include <linux/device-mapper.h>
28 if (!strcmp(name, log_type->name)) in __find_dirty_log_type()
41 if (log_type && !try_module_get(log_type->module)) in _get_dirty_log_type()
56 * Log modules are named "dm-log-" followed by the 'type_name'.
58 * This function will first try the module "dm-log-<type_name>",
59 * then truncate 'type_name' on the last '-' and try again.
61 * For example, if type_name was "clustered-disk", it would search
62 * 'dm-log-clustered-disk' then 'dm-log-clustered'.
85 while (request_module("dm-log-%s", type_name_dup) || in get_type()
87 p = strrchr(type_name_dup, '-'); in get_type()
107 if (!__find_dirty_log_type(type->name)) in put_type()
110 module_put(type->module); in put_type()
121 if (!__find_dirty_log_type(type->name)) in dm_dirty_log_type_register()
122 list_add(&type->list, &_log_types); in dm_dirty_log_type_register()
124 r = -EEXIST; in dm_dirty_log_type_register()
135 if (!__find_dirty_log_type(type->name)) { in dm_dirty_log_type_unregister()
137 return -EINVAL; in dm_dirty_log_type_unregister()
140 list_del(&type->list); in dm_dirty_log_type_unregister()
166 log->flush_callback_fn = flush_callback_fn; in dm_dirty_log_create()
167 log->type = type; in dm_dirty_log_create()
168 if (type->ctr(log, ti, argc, argv)) { in dm_dirty_log_create()
180 log->type->dtr(log); in dm_dirty_log_destroy()
181 put_type(log->type); in dm_dirty_log_destroy()
187 *---------------------------------------------------------------
190 *---------------------------------------------------------------
198 * The on-disk version of the metadata.
237 enum sync { enum
239 NOSYNC, /* Devices known to be already in sync */
240 FORCESYNC, /* Force a sync to happen */
241 } sync; member
263 return test_bit_le(bit, bs) ? 1 : 0; in log_test_bit()
270 l->touched_cleaned = 1; in log_set_bit()
277 l->touched_dirtied = 1; in log_clear_bit()
281 *---------------------------------------------------------------
283 *--------------------------------------------------------------
287 disk->magic = cpu_to_le32(core->magic); in header_to_disk()
288 disk->version = cpu_to_le32(core->version); in header_to_disk()
289 disk->nr_regions = cpu_to_le64(core->nr_regions); in header_to_disk()
294 core->magic = le32_to_cpu(disk->magic); in header_from_disk()
295 core->version = le32_to_cpu(disk->version); in header_from_disk()
296 core->nr_regions = le64_to_cpu(disk->nr_regions); in header_from_disk()
301 lc->io_req.bi_opf = op; in rw_header()
303 return dm_io(&lc->io_req, 1, &lc->header_location, NULL, IOPRIO_DEFAULT); in rw_header()
309 .bdev = lc->header_location.bdev, in flush_header()
314 lc->io_req.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; in flush_header()
316 return dm_io(&lc->io_req, 1, &null_location, NULL, IOPRIO_DEFAULT); in flush_header()
327 header_from_disk(&log->header, log->disk_header); in read_header()
330 if (log->sync != DEFAULTSYNC || log->header.magic != MIRROR_MAGIC) { in read_header()
331 log->header.magic = MIRROR_MAGIC; in read_header()
332 log->header.version = MIRROR_DISK_VERSION; in read_header()
333 log->header.nr_regions = 0; in read_header()
337 if (log->header.version == 1) in read_header()
338 log->header.version = 2; in read_header()
341 if (log->header.version != MIRROR_DISK_VERSION) { in read_header()
343 return -EINVAL; in read_header()
351 if (region_size < 2 || region_size > ti->len) in _check_region_size()
357 return 1; in _check_region_size()
361 *--------------------------------------------------------------
364 * argv contains region_size followed optionally by [no]sync
365 *--------------------------------------------------------------
372 enum sync sync = DEFAULTSYNC; in create_log_context() local
381 if (argc < 1 || argc > 2) { in create_log_context()
383 return -EINVAL; in create_log_context()
386 if (argc > 1) { in create_log_context()
387 if (!strcmp(argv[1], "sync")) in create_log_context()
388 sync = FORCESYNC; in create_log_context()
389 else if (!strcmp(argv[1], "nosync")) in create_log_context()
390 sync = NOSYNC; in create_log_context()
392 DMWARN("unrecognised sync argument to dirty region log: %s", argv[1]); in create_log_context()
393 return -EINVAL; in create_log_context()
397 if (sscanf(argv[0], "%u%c", &region_size, &dummy) != 1 || in create_log_context()
400 return -EINVAL; in create_log_context()
403 region_count = dm_sector_div_up(ti->len, region_size); in create_log_context()
408 return -ENOMEM; in create_log_context()
411 lc->ti = ti; in create_log_context()
412 lc->touched_dirtied = 0; in create_log_context()
413 lc->touched_cleaned = 0; in create_log_context()
414 lc->flush_failed = 0; in create_log_context()
415 lc->region_size = region_size; in create_log_context()
416 lc->region_count = region_count; in create_log_context()
417 lc->sync = sync; in create_log_context()
425 lc->bitset_uint32_count = bitset_size / sizeof(*lc->clean_bits); in create_log_context()
431 lc->clean_bits = vmalloc(bitset_size); in create_log_context()
432 if (!lc->clean_bits) { in create_log_context()
435 return -ENOMEM; in create_log_context()
437 lc->disk_header = NULL; in create_log_context()
439 lc->log_dev = dev; in create_log_context()
440 lc->log_dev_failed = 0; in create_log_context()
441 lc->log_dev_flush_failed = 0; in create_log_context()
442 lc->header_location.bdev = lc->log_dev->bdev; in create_log_context()
443 lc->header_location.sector = 0; in create_log_context()
450 bdev_logical_block_size(lc->header_location.bdev)); in create_log_context()
452 if (buf_size > bdev_nr_bytes(dev->bdev)) { in create_log_context()
454 dev->name, (unsigned long long)buf_size); in create_log_context()
456 return -EINVAL; in create_log_context()
459 lc->header_location.count = buf_size >> SECTOR_SHIFT; in create_log_context()
461 lc->io_req.mem.type = DM_IO_VMA; in create_log_context()
462 lc->io_req.notify.fn = NULL; in create_log_context()
463 lc->io_req.client = dm_io_client_create(); in create_log_context()
464 if (IS_ERR(lc->io_req.client)) { in create_log_context()
465 r = PTR_ERR(lc->io_req.client); in create_log_context()
471 lc->disk_header = vmalloc(buf_size); in create_log_context()
472 if (!lc->disk_header) { in create_log_context()
474 dm_io_client_destroy(lc->io_req.client); in create_log_context()
476 return -ENOMEM; in create_log_context()
479 lc->io_req.mem.ptr.vma = lc->disk_header; in create_log_context()
480 lc->clean_bits = (void *)lc->disk_header + in create_log_context()
484 memset(lc->clean_bits, -1, bitset_size); in create_log_context()
486 lc->sync_bits = vmalloc(bitset_size); in create_log_context()
487 if (!lc->sync_bits) { in create_log_context()
488 DMWARN("couldn't allocate sync bitset"); in create_log_context()
490 vfree(lc->clean_bits); in create_log_context()
492 dm_io_client_destroy(lc->io_req.client); in create_log_context()
493 vfree(lc->disk_header); in create_log_context()
495 return -ENOMEM; in create_log_context()
497 memset(lc->sync_bits, (sync == NOSYNC) ? -1 : 0, bitset_size); in create_log_context()
498 lc->sync_count = (sync == NOSYNC) ? region_count : 0; in create_log_context()
500 lc->recovering_bits = vzalloc(bitset_size); in create_log_context()
501 if (!lc->recovering_bits) { in create_log_context()
502 DMWARN("couldn't allocate sync bitset"); in create_log_context()
503 vfree(lc->sync_bits); in create_log_context()
505 vfree(lc->clean_bits); in create_log_context()
507 dm_io_client_destroy(lc->io_req.client); in create_log_context()
508 vfree(lc->disk_header); in create_log_context()
510 return -ENOMEM; in create_log_context()
512 lc->sync_search = 0; in create_log_context()
513 log->context = lc; in create_log_context()
526 vfree(lc->sync_bits); in destroy_log_context()
527 vfree(lc->recovering_bits); in destroy_log_context()
533 struct log_c *lc = log->context; in core_dtr()
535 vfree(lc->clean_bits); in core_dtr()
540 *---------------------------------------------------------------------
543 * argv contains log_device region_size followed optionally by [no]sync
544 *---------------------------------------------------------------------
554 return -EINVAL; in disk_ctr()
557 r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dev); in disk_ctr()
561 r = create_log_context(log, ti, argc - 1, argv + 1, dev); in disk_ctr()
572 struct log_c *lc = log->context; in disk_dtr()
574 dm_put_device(lc->ti, lc->log_dev); in disk_dtr()
575 vfree(lc->disk_header); in disk_dtr()
576 dm_io_client_destroy(lc->io_req.client); in disk_dtr()
582 if (lc->log_dev_failed) in fail_log_device()
585 lc->log_dev_failed = 1; in fail_log_device()
586 dm_table_event(lc->ti->table); in fail_log_device()
593 struct log_c *lc = log->context; in disk_resume()
594 size_t size = lc->bitset_uint32_count * sizeof(uint32_t); in disk_resume()
600 lc->log_dev->name); in disk_resume()
604 * all regions are out-of-sync. If we simply return in disk_resume()
606 * lead us to return 'in-sync' status for regions in disk_resume()
607 * that are actually 'out-of-sync'. in disk_resume()
609 lc->header.nr_regions = 0; in disk_resume()
612 /* set or clear any new bits -- device has grown */ in disk_resume()
613 if (lc->sync == NOSYNC) in disk_resume()
614 for (i = lc->header.nr_regions; i < lc->region_count; i++) in disk_resume()
616 log_set_bit(lc, lc->clean_bits, i); in disk_resume()
618 for (i = lc->header.nr_regions; i < lc->region_count; i++) in disk_resume()
620 log_clear_bit(lc, lc->clean_bits, i); in disk_resume()
622 /* clear any old bits -- device has shrunk */ in disk_resume()
623 for (i = lc->region_count; i % BITS_PER_LONG; i++) in disk_resume()
624 log_clear_bit(lc, lc->clean_bits, i); in disk_resume()
626 /* copy clean across to sync */ in disk_resume()
627 memcpy(lc->sync_bits, lc->clean_bits, size); in disk_resume()
628 lc->sync_count = memweight(lc->clean_bits, in disk_resume()
629 lc->bitset_uint32_count * sizeof(uint32_t)); in disk_resume()
630 lc->sync_search = 0; in disk_resume()
633 lc->header.nr_regions = lc->region_count; in disk_resume()
635 header_to_disk(&lc->header, lc->disk_header); in disk_resume()
642 lc->log_dev_flush_failed = 1; in disk_resume()
646 lc->log_dev->name); in disk_resume()
655 struct log_c *lc = log->context; in core_get_region_size()
657 return lc->region_size; in core_get_region_size()
662 struct log_c *lc = log->context; in core_resume()
664 lc->sync_search = 0; in core_resume()
670 struct log_c *lc = log->context; in core_is_clean()
672 return log_test_bit(lc->clean_bits, region); in core_is_clean()
677 struct log_c *lc = log->context; in core_in_sync()
679 return log_test_bit(lc->sync_bits, region); in core_in_sync()
691 struct log_c *lc = log->context; in disk_flush()
694 if (!lc->touched_cleaned && !lc->touched_dirtied) in disk_flush()
697 if (lc->touched_cleaned && log->flush_callback_fn && in disk_flush()
698 log->flush_callback_fn(lc->ti)) { in disk_flush()
702 * re-reading the log off disk). So mark all of them in disk_flush()
705 lc->flush_failed = 1; in disk_flush()
706 for (i = 0; i < lc->region_count; i++) in disk_flush()
707 log_clear_bit(lc, lc->clean_bits, i); in disk_flush()
714 if (lc->touched_dirtied) { in disk_flush()
717 lc->log_dev_flush_failed = 1; in disk_flush()
720 lc->touched_dirtied = 0; in disk_flush()
722 lc->touched_cleaned = 0; in disk_flush()
730 struct log_c *lc = log->context; in core_mark_region()
732 log_clear_bit(lc, lc->clean_bits, region); in core_mark_region()
737 struct log_c *lc = log->context; in core_clear_region()
739 if (likely(!lc->flush_failed)) in core_clear_region()
740 log_set_bit(lc, lc->clean_bits, region); in core_clear_region()
745 struct log_c *lc = log->context; in core_get_resync_work()
747 if (lc->sync_search >= lc->region_count) in core_get_resync_work()
751 *region = find_next_zero_bit_le(lc->sync_bits, in core_get_resync_work()
752 lc->region_count, in core_get_resync_work()
753 lc->sync_search); in core_get_resync_work()
754 lc->sync_search = *region + 1; in core_get_resync_work()
756 if (*region >= lc->region_count) in core_get_resync_work()
759 } while (log_test_bit(lc->recovering_bits, *region)); in core_get_resync_work()
761 log_set_bit(lc, lc->recovering_bits, *region); in core_get_resync_work()
762 return 1; in core_get_resync_work()
768 struct log_c *lc = log->context; in core_set_region_sync()
770 log_clear_bit(lc, lc->recovering_bits, region); in core_set_region_sync()
772 log_set_bit(lc, lc->sync_bits, region); in core_set_region_sync()
773 lc->sync_count++; in core_set_region_sync()
774 } else if (log_test_bit(lc->sync_bits, region)) { in core_set_region_sync()
775 lc->sync_count--; in core_set_region_sync()
776 log_clear_bit(lc, lc->sync_bits, region); in core_set_region_sync()
782 struct log_c *lc = log->context; in core_get_sync_count()
784 return lc->sync_count; in core_get_sync_count()
789 if (lc->sync != DEFAULTSYNC) \
790 DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : ""); \
797 struct log_c *lc = log->context; in core_status()
801 DMEMIT("1 %s", log->type->name); in core_status()
805 DMEMIT("%s %u %u ", log->type->name, in core_status()
806 lc->sync == DEFAULTSYNC ? 1 : 2, lc->region_size); in core_status()
822 struct log_c *lc = log->context; in disk_status()
826 DMEMIT("3 %s %s %c", log->type->name, lc->log_dev->name, in disk_status()
827 lc->log_dev_flush_failed ? 'F' : in disk_status()
828 lc->log_dev_failed ? 'D' : in disk_status()
833 DMEMIT("%s %u %s %u ", log->type->name, in disk_status()
834 lc->sync == DEFAULTSYNC ? 2 : 3, lc->log_dev->name, in disk_status()
835 lc->region_size); in disk_status()
911 MODULE_AUTHOR("Joe Thornber, Heinz Mauelshagen <dm-devel@lists.linux.dev>");