1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00
lvm2/lib/thin/thin.c
Petr Rockai e59e2f7c3c Move the core of the lib/config/config.c functionality into libdevmapper,
leaving behind the LVM-specific parts of the code (convenience wrappers that
handle `struct device` and `struct cmd_context`, basically). A number of
functions have been renamed (in addition to getting a dm_ prefix) -- namely,
all of the config interface now has a dm_config_ prefix.
2011-08-30 14:55:15 +00:00

244 lines
6.6 KiB
C

/*
* Copyright (C) 2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "toolcontext.h"
#include "metadata.h"
#include "segtype.h"
#include "text_export.h"
#include "text_import.h"
#include "config.h"
#include "activate.h"
#include "str_list.h"
#ifdef DMEVENTD
# include "sharedlib.h"
# include "libdevmapper-event.h"
#endif
/* Dm kernel module name for thin provisiong */
#define THIN_MODULE "thin-pool"
/*
* Macro used as return argument - returns 0.
* return is left to be written in the function for better readability.
*/
#define SEG_LOG_ERROR(t, p...) \
log_error(t " segment %s of logical volume %s.", ## p, \
dm_config_parent_name(sn), seg->lv->name), 0;
static const char *_thin_pool_name(const struct lv_segment *seg)
{
return seg->segtype->name;
}
static int _thin_pool_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)))
{
const struct dm_config_node *cn;
if (!(cn = dm_config_find_node(sn, "data")) ||
!cn->v || cn->v->type != DM_CFG_STRING)
return SEG_LOG_ERROR("Thin pool data must be a string in");
if (!(seg->data_lv = find_lv(seg->lv->vg, cn->v->v.str)))
return SEG_LOG_ERROR("Unknown pool data %s in",
cn->v->v.str);
if (!(cn = dm_config_find_node(sn, "metadata")) ||
!cn->v || cn->v->type != DM_CFG_STRING)
return SEG_LOG_ERROR("Thin pool metadata must be a string in");
if (!(seg->metadata_lv = find_lv(seg->lv->vg, cn->v->v.str)))
return SEG_LOG_ERROR("Unknown pool metadata %s in",
cn->v->v.str);
if (!dm_config_get_uint64(sn, "transaction_id", &seg->transaction_id))
return SEG_LOG_ERROR("Could not read transaction_id for");
if (dm_config_find_node(sn, "zero_new_blocks") &&
!dm_config_get_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks))
return SEG_LOG_ERROR("Could not read zero_new_blocks for");
return 1;
}
static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter *f)
{
outf(f, "data = \"%s\"", seg->data_lv->name);
outf(f, "metadata = \"%s\"", seg->metadata_lv->name);
outf(f, "transaction_id = %" PRIu64, seg->transaction_id);
if (seg->zero_new_blocks)
outf(f, "zero_new_blocks = 1");
return 1;
}
static const char *_thin_name(const struct lv_segment *seg)
{
return seg->segtype->name;
}
static int _thin_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)))
{
const struct dm_config_node *cn;
if (!(cn = dm_config_find_node(sn, "thin_pool")) ||
!cn->v || cn->v->type != DM_CFG_STRING)
return SEG_LOG_ERROR("Thin pool must be a string in");
if (!(seg->thin_pool_lv = find_lv(seg->lv->vg, cn->v->v.str)))
return SEG_LOG_ERROR("Unknown thin pool %s in",
cn->v->v.str);
if ((cn = dm_config_find_node(sn, "origin"))) {
if (!cn->v || cn->v->type != DM_CFG_STRING)
return SEG_LOG_ERROR("Thin pool origin must be a string in");
if (!(seg->origin = find_lv(seg->lv->vg, cn->v->v.str)))
return SEG_LOG_ERROR("Unknown origin %s in",
cn->v->v.str);
}
if (!dm_config_get_uint64(sn, "device_id", &seg->device_id))
return SEG_LOG_ERROR("Could not read device_id for");
return 1;
}
static int _thin_text_export(const struct lv_segment *seg, struct formatter *f)
{
outf(f, "thin_pool = \"%s\"", seg->thin_pool_lv->name);
outf(f, "device_id = %" PRIu64, seg->device_id);
if (seg->origin)
outf(f, "origin = \"%s\"", seg->origin->name);
return 1;
}
#ifdef DEVMAPPER_SUPPORT
static int _thin_target_percent(void **target_state __attribute__((unused)),
percent_t *percent,
struct dm_pool *mem __attribute__((unused)),
struct cmd_context *cmd __attribute__((unused)),
struct lv_segment *seg __attribute__((unused)),
char *params, uint64_t *total_numerator,
uint64_t *total_denominator)
{
return 1;
}
static int _thin_target_present(struct cmd_context *cmd,
const struct lv_segment *seg,
unsigned *attributes __attribute__((unused)))
{
static int _checked = 0;
static int _present = 0;
if (!_checked) {
_present = target_present(cmd, THIN_MODULE, 1);
_checked = 1;
}
return _present;
}
#endif
static int _thin_modules_needed(struct dm_pool *mem,
const struct lv_segment *seg __attribute__((unused)),
struct dm_list *modules)
{
if (!str_list_add(mem, modules, THIN_MODULE)) {
log_error("thin string list allocation failed");
return 0;
}
return 1;
}
static void _thin_destroy(struct segment_type *segtype)
{
dm_free(segtype);
}
static struct segtype_handler _thin_pool_ops = {
.name = _thin_pool_name,
.text_import = _thin_pool_text_import,
.text_export = _thin_pool_text_export,
.modules_needed = _thin_modules_needed,
.destroy = _thin_destroy,
};
static struct segtype_handler _thin_ops = {
.name = _thin_name,
.text_import = _thin_text_import,
.text_export = _thin_text_export,
#ifdef DEVMAPPER_SUPPORT
.target_percent = _thin_target_percent,
.target_present = _thin_target_present,
#endif
.modules_needed = _thin_modules_needed,
.destroy = _thin_destroy,
};
#ifdef THIN_INTERNAL
int init_thin_segtypes(struct cmd_context *cmd, struct segtype_library *seglib)
#else /* Shared */
int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *seglib)
#endif
{
static const struct {
struct segtype_handler *ops;
const char name[16];
uint32_t flags;
} reg_segtypes[] = {
{ &_thin_pool_ops, "thin_pool", SEG_THIN_POOL },
{ &_thin_ops, "thin", SEG_THIN_VOLUME }
};
struct segment_type *segtype;
unsigned i;
for (i = 0; i < sizeof(reg_segtypes)/sizeof(reg_segtypes[0]); ++i) {
segtype = dm_zalloc(sizeof(*segtype));
if (!segtype) {
log_error("Failed to allocate memory for %s segtype",
reg_segtypes[i].name);
return 0;
}
segtype->ops = reg_segtypes[i].ops;
segtype->name = reg_segtypes[i].name;
segtype->flags = reg_segtypes[i].flags;
#ifdef DEVMAPPER_SUPPORT
# ifdef DMEVENTD
// FIXME if (_get_thin_dso_path(cmd))
// FIXME segtype->flags |= SEG_MONITORED;
# endif /* DMEVENTD */
#endif
if (!lvm_register_segtype(seglib, segtype))
return_0;
log_very_verbose("Initialised segtype: %s", segtype->name);
}
return 1;
}