dm-log.c
来自「linux 内核源代码」· C语言 代码 · 共 740 行 · 第 1/2 页
C
740 行
lc->recovering_bits = vmalloc(bitset_size); if (!lc->recovering_bits) { DMWARN("couldn't allocate sync bitset"); vfree(lc->sync_bits); if (!dev) vfree(lc->clean_bits); vfree(lc->disk_header); kfree(lc); return -ENOMEM; } memset(lc->recovering_bits, 0, bitset_size); lc->sync_search = 0; log->context = lc; return 0;}static int core_ctr(struct dirty_log *log, struct dm_target *ti, unsigned int argc, char **argv){ return create_log_context(log, ti, argc, argv, NULL);}static void destroy_log_context(struct log_c *lc){ vfree(lc->sync_bits); vfree(lc->recovering_bits); kfree(lc);}static void core_dtr(struct dirty_log *log){ struct log_c *lc = (struct log_c *) log->context; vfree(lc->clean_bits); destroy_log_context(lc);}/*---------------------------------------------------------------- * disk log constructor/destructor * * argv contains log_device region_size followed optionally by [no]sync *--------------------------------------------------------------*/static int disk_ctr(struct dirty_log *log, struct dm_target *ti, unsigned int argc, char **argv){ int r; struct dm_dev *dev; if (argc < 2 || argc > 3) { DMWARN("wrong number of arguments to disk mirror log"); return -EINVAL; } r = dm_get_device(ti, argv[0], 0, 0 /* FIXME */, FMODE_READ | FMODE_WRITE, &dev); if (r) return r; r = create_log_context(log, ti, argc - 1, argv + 1, dev); if (r) { dm_put_device(ti, dev); return r; } return 0;}static void disk_dtr(struct dirty_log *log){ struct log_c *lc = (struct log_c *) log->context; dm_put_device(lc->ti, lc->log_dev); vfree(lc->disk_header); dm_io_client_destroy(lc->io_req.client); destroy_log_context(lc);}static int count_bits32(uint32_t *addr, unsigned size){ int count = 0, i; for (i = 0; i < size; i++) { count += hweight32(*(addr+i)); } return count;}static void fail_log_device(struct log_c *lc){ if (lc->log_dev_failed) return; lc->log_dev_failed = 1; dm_table_event(lc->ti->table);}static int disk_resume(struct dirty_log *log){ int r; unsigned i; struct log_c *lc = (struct log_c *) log->context; size_t size = lc->bitset_uint32_count * sizeof(uint32_t); /* read the disk header */ r = read_header(lc); if (r) { DMWARN("%s: Failed to read header on mirror log device", lc->log_dev->name); fail_log_device(lc); /* * If the log device cannot be read, we must assume * all regions are out-of-sync. If we simply return * here, the state will be uninitialized and could * lead us to return 'in-sync' status for regions * that are actually 'out-of-sync'. */ lc->header.nr_regions = 0; } /* set or clear any new bits -- device has grown */ if (lc->sync == NOSYNC) for (i = lc->header.nr_regions; i < lc->region_count; i++) /* FIXME: amazingly inefficient */ log_set_bit(lc, lc->clean_bits, i); else for (i = lc->header.nr_regions; i < lc->region_count; i++) /* FIXME: amazingly inefficient */ log_clear_bit(lc, lc->clean_bits, i); /* clear any old bits -- device has shrunk */ for (i = lc->region_count; i % (sizeof(*lc->clean_bits) << BYTE_SHIFT); i++) log_clear_bit(lc, lc->clean_bits, i); /* copy clean across to sync */ memcpy(lc->sync_bits, lc->clean_bits, size); lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count); lc->sync_search = 0; /* set the correct number of regions in the header */ lc->header.nr_regions = lc->region_count; /* write the new header */ r = write_header(lc); if (r) { DMWARN("%s: Failed to write header on mirror log device", lc->log_dev->name); fail_log_device(lc); } return r;}static uint32_t core_get_region_size(struct dirty_log *log){ struct log_c *lc = (struct log_c *) log->context; return lc->region_size;}static int core_resume(struct dirty_log *log){ struct log_c *lc = (struct log_c *) log->context; lc->sync_search = 0; return 0;}static int core_is_clean(struct dirty_log *log, region_t region){ struct log_c *lc = (struct log_c *) log->context; return log_test_bit(lc->clean_bits, region);}static int core_in_sync(struct dirty_log *log, region_t region, int block){ struct log_c *lc = (struct log_c *) log->context; return log_test_bit(lc->sync_bits, region);}static int core_flush(struct dirty_log *log){ /* no op */ return 0;}static int disk_flush(struct dirty_log *log){ int r; struct log_c *lc = (struct log_c *) log->context; /* only write if the log has changed */ if (!lc->touched) return 0; r = write_header(lc); if (r) fail_log_device(lc); else lc->touched = 0; return r;}static void core_mark_region(struct dirty_log *log, region_t region){ struct log_c *lc = (struct log_c *) log->context; log_clear_bit(lc, lc->clean_bits, region);}static void core_clear_region(struct dirty_log *log, region_t region){ struct log_c *lc = (struct log_c *) log->context; log_set_bit(lc, lc->clean_bits, region);}static int core_get_resync_work(struct dirty_log *log, region_t *region){ struct log_c *lc = (struct log_c *) log->context; if (lc->sync_search >= lc->region_count) return 0; do { *region = ext2_find_next_zero_bit( (unsigned long *) lc->sync_bits, lc->region_count, lc->sync_search); lc->sync_search = *region + 1; if (*region >= lc->region_count) return 0; } while (log_test_bit(lc->recovering_bits, *region)); log_set_bit(lc, lc->recovering_bits, *region); return 1;}static void core_set_region_sync(struct dirty_log *log, region_t region, int in_sync){ struct log_c *lc = (struct log_c *) log->context; log_clear_bit(lc, lc->recovering_bits, region); if (in_sync) { log_set_bit(lc, lc->sync_bits, region); lc->sync_count++; } else if (log_test_bit(lc->sync_bits, region)) { lc->sync_count--; log_clear_bit(lc, lc->sync_bits, region); }}static region_t core_get_sync_count(struct dirty_log *log){ struct log_c *lc = (struct log_c *) log->context; return lc->sync_count;}#define DMEMIT_SYNC \ if (lc->sync != DEFAULTSYNC) \ DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "")static int core_status(struct dirty_log *log, status_type_t status, char *result, unsigned int maxlen){ int sz = 0; struct log_c *lc = log->context; switch(status) { case STATUSTYPE_INFO: DMEMIT("1 %s", log->type->name); break; case STATUSTYPE_TABLE: DMEMIT("%s %u %u ", log->type->name, lc->sync == DEFAULTSYNC ? 1 : 2, lc->region_size); DMEMIT_SYNC; } return sz;}static int disk_status(struct dirty_log *log, status_type_t status, char *result, unsigned int maxlen){ int sz = 0; struct log_c *lc = log->context; switch(status) { case STATUSTYPE_INFO: DMEMIT("3 %s %s %c", log->type->name, lc->log_dev->name, lc->log_dev_failed ? 'D' : 'A'); break; case STATUSTYPE_TABLE: DMEMIT("%s %u %s %u ", log->type->name, lc->sync == DEFAULTSYNC ? 2 : 3, lc->log_dev->name, lc->region_size); DMEMIT_SYNC; } return sz;}static struct dirty_log_type _core_type = { .name = "core", .module = THIS_MODULE, .ctr = core_ctr, .dtr = core_dtr, .resume = core_resume, .get_region_size = core_get_region_size, .is_clean = core_is_clean, .in_sync = core_in_sync, .flush = core_flush, .mark_region = core_mark_region, .clear_region = core_clear_region, .get_resync_work = core_get_resync_work, .set_region_sync = core_set_region_sync, .get_sync_count = core_get_sync_count, .status = core_status,};static struct dirty_log_type _disk_type = { .name = "disk", .module = THIS_MODULE, .ctr = disk_ctr, .dtr = disk_dtr, .postsuspend = disk_flush, .resume = disk_resume, .get_region_size = core_get_region_size, .is_clean = core_is_clean, .in_sync = core_in_sync, .flush = disk_flush, .mark_region = core_mark_region, .clear_region = core_clear_region, .get_resync_work = core_get_resync_work, .set_region_sync = core_set_region_sync, .get_sync_count = core_get_sync_count, .status = disk_status,};int __init dm_dirty_log_init(void){ int r; r = dm_register_dirty_log_type(&_core_type); if (r) DMWARN("couldn't register core log"); r = dm_register_dirty_log_type(&_disk_type); if (r) { DMWARN("couldn't register disk type"); dm_unregister_dirty_log_type(&_core_type); } return r;}void dm_dirty_log_exit(void){ dm_unregister_dirty_log_type(&_disk_type); dm_unregister_dirty_log_type(&_core_type);}EXPORT_SYMBOL(dm_register_dirty_log_type);EXPORT_SYMBOL(dm_unregister_dirty_log_type);EXPORT_SYMBOL(dm_create_dirty_log);EXPORT_SYMBOL(dm_destroy_dirty_log);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?