// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2001-2002 Sistina Software (UK) Limited. * Copyright (C) 2006-2008 Red Hat GmbH * * This file is released under the GPL.
*/
if (type && !try_module_get(type->module))
type = NULL;
spin_unlock(&_lock);
return type;
}
/* * get_type * @type_name * * Attempt to retrieve the dm_exception_store_type by name. If not already * available, attempt to load the appropriate module. * * Exstore modules are named "dm-exstore-" followed by the 'type_name'. * Modules may contain multiple types. * This function will first try the module "dm-exstore-<type_name>", * then truncate 'type_name' on the last '-' and try again. * * For example, if type_name was "clustered-shared", it would search * 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'. * * 'dm-exception-store-<type_name>' is too long of a name in my * opinion, which is why I've chosen to have the files * containing exception store implementations be 'dm-exstore-<type_name>'. * If you want your module to be autoloaded, you will follow this * naming convention. * * Returns: dm_exception_store_type* on success, NULL on failure
*/ staticstruct dm_exception_store_type *get_type(constchar *type_name)
{ char *p, *type_name_dup; struct dm_exception_store_type *type;
type = _get_exception_store_type(type_name); if (type) return type;
type_name_dup = kstrdup(type_name, GFP_KERNEL); if (!type_name_dup) {
DMERR("No memory left to attempt load for \"%s\"", type_name); return NULL;
}
while (request_module("dm-exstore-%s", type_name_dup) ||
!(type = _get_exception_store_type(type_name))) {
p = strrchr(type_name_dup, '-'); if (!p) break;
p[0] = '\0';
}
if (!type)
DMWARN("Module for exstore type \"%s\" not found.", type_name);
int dm_exception_store_type_register(struct dm_exception_store_type *type)
{ int r = 0;
spin_lock(&_lock); if (!__find_exception_store_type(type->name))
list_add(&type->list, &_exception_store_types); else
r = -EEXIST;
spin_unlock(&_lock);
int dm_exception_store_set_chunk_size(struct dm_exception_store *store, unsignedint chunk_size, char **error)
{ /* Check chunk_size is a power of 2 */ if (!is_power_of_2(chunk_size)) {
*error = "Chunk size is not a power of 2"; return -EINVAL;
}
/* Validate the chunk size against the device block size */ if (chunk_size %
(bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) ||
chunk_size %
(bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) {
*error = "Chunk size is not a multiple of device blocksize"; return -EINVAL;
}
if (chunk_size > INT_MAX >> SECTOR_SHIFT) {
*error = "Chunk size is too high"; return -EINVAL;
}
int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, struct dm_snapshot *snap, unsignedint *args_used, struct dm_exception_store **store)
{ int r = 0; struct dm_exception_store_type *type = NULL; struct dm_exception_store *tmp_store; char persistent;
if (argc < 2) {
ti->error = "Insufficient exception store arguments"; return -EINVAL;
}
tmp_store = kzalloc(sizeof(*tmp_store), GFP_KERNEL); if (!tmp_store) {
ti->error = "Exception store allocation failed"; return -ENOMEM;
}
persistent = toupper(*argv[0]); if (persistent == 'P')
type = get_type("P"); elseif (persistent == 'N')
type = get_type("N"); else {
ti->error = "Exception store type is not P or N";
r = -EINVAL; goto bad_type;
}
if (!type) {
ti->error = "Exception store type not recognised";
r = -EINVAL; goto bad_type;
}
tmp_store->type = type;
tmp_store->snap = snap;
r = set_chunk_size(tmp_store, argv[1], &ti->error); if (r) goto bad;
r = type->ctr(tmp_store, (strlen(argv[0]) > 1 ? &argv[0][1] : NULL)); if (r) {
ti->error = "Exception store type constructor failed"; goto bad;
}
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.