// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2003 Sistina Software * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. * * This file is released under the LGPL.
*/
log_type = __find_dirty_log_type(name); if (log_type && !try_module_get(log_type->module))
log_type = NULL;
spin_unlock(&_lock);
return log_type;
}
/* * get_type * @type_name * * Attempt to retrieve the dm_dirty_log_type by name. If not already * available, attempt to load the appropriate module. * * Log modules are named "dm-log-" followed by the 'type_name'. * Modules may contain multiple types. * This function will first try the module "dm-log-<type_name>", * then truncate 'type_name' on the last '-' and try again. * * For example, if type_name was "clustered-disk", it would search * 'dm-log-clustered-disk' then 'dm-log-clustered'. * * Returns: dirty_log_type* on success, NULL on failure
*/ staticstruct dm_dirty_log_type *get_type(constchar *type_name)
{ char *p, *type_name_dup; struct dm_dirty_log_type *log_type;
if (!type_name) return NULL;
log_type = _get_dirty_log_type(type_name); if (log_type) return log_type;
type_name_dup = kstrdup(type_name, GFP_KERNEL); if (!type_name_dup) {
DMWARN("No memory left to attempt log module load for \"%s\"",
type_name); return NULL;
}
while (request_module("dm-log-%s", type_name_dup) ||
!(log_type = _get_dirty_log_type(type_name))) {
p = strrchr(type_name_dup, '-'); if (!p) break;
p[0] = '\0';
}
if (!log_type)
DMWARN("Module for logging type \"%s\" not found.", type_name);
kfree(type_name_dup);
return log_type;
}
staticvoid put_type(struct dm_dirty_log_type *type)
{ if (!type) return;
spin_lock(&_lock); if (!__find_dirty_log_type(type->name)) goto out;
module_put(type->module);
out:
spin_unlock(&_lock);
}
int dm_dirty_log_type_register(struct dm_dirty_log_type *type)
{ int r = 0;
spin_lock(&_lock); if (!__find_dirty_log_type(type->name))
list_add(&type->list, &_log_types); else
r = -EEXIST;
spin_unlock(&_lock);
/* *--------------------------------------------------------------- * Persistent and core logs share a lot of their implementation. * FIXME: need a reload method to be called from a resume *---------------------------------------------------------------
*/ /* * Magic for persistent mirrors: "MiRr"
*/ #define MIRROR_MAGIC 0x4D695272
/* * The on-disk version of the metadata.
*/ #define MIRROR_DISK_VERSION 2 #define LOG_OFFSET 2
/* Resync flag */ enum sync {
DEFAULTSYNC, /* Synchronize if necessary */
NOSYNC, /* Devices known to be already in sync */
FORCESYNC, /* Force a sync to happen */
} sync;
struct dm_io_request io_req;
/* * Disk log fields
*/ int log_dev_failed; int log_dev_flush_failed; struct dm_dev *log_dev; struct log_header_core header;
/* * The touched member needs to be updated every time we access * one of the bitsets.
*/ staticinlineint log_test_bit(uint32_t *bs, unsignedint bit)
{ return test_bit_le(bit, bs) ? 1 : 0;
}
/* * Work out how many "unsigned long"s we need to hold the bitset.
*/
bitset_size = dm_round_up(region_count, BITS_PER_LONG);
bitset_size >>= BYTE_SHIFT;
/* read the disk header */
r = read_header(lc); if (r) {
DMWARN("%s: Failed to read header on dirty region 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 % BITS_PER_LONG; 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 = memweight(lc->clean_bits,
lc->bitset_uint32_count * sizeof(uint32_t));
lc->sync_search = 0;
/* set the correct number of regions in the header */
lc->header.nr_regions = lc->region_count;
header_to_disk(&lc->header, lc->disk_header);
/* write the new header */
r = rw_header(lc, REQ_OP_WRITE); if (!r) {
r = flush_header(lc); if (r)
lc->log_dev_flush_failed = 1;
} if (r) {
DMWARN("%s: Failed to write header on dirty region log device",
lc->log_dev->name);
fail_log_device(lc);
}
/* only write if the log has changed */ if (!lc->touched_cleaned && !lc->touched_dirtied) return 0;
if (lc->touched_cleaned && log->flush_callback_fn &&
log->flush_callback_fn(lc->ti)) { /* * At this point it is impossible to determine which * regions are clean and which are dirty (without * re-reading the log off disk). So mark all of them * dirty.
*/
lc->flush_failed = 1; for (i = 0; i < lc->region_count; i++)
log_clear_bit(lc, lc->clean_bits, i);
}
r = rw_header(lc, REQ_OP_WRITE); if (r)
fail_log_device(lc); else { if (lc->touched_dirtied) {
r = flush_header(lc); if (r) {
lc->log_dev_flush_failed = 1;
fail_log_device(lc);
} else
lc->touched_dirtied = 0;
}
lc->touched_cleaned = 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.