mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Implement devices/global_filter.
The global filter is applied first, and is also applied in pvscan --cache (which is called from udev rules to keep lvmetad updated). Cf. example.conf.
This commit is contained in:
parent
ceb79c9a50
commit
c7b17836ea
@ -41,6 +41,8 @@ typedef struct {
|
||||
pthread_mutex_t vgid_to_metadata;
|
||||
pthread_mutex_t pvid_to_vgid;
|
||||
} lock;
|
||||
char token[128];
|
||||
pthread_mutex_t token_lock;
|
||||
} lvmetad_state;
|
||||
|
||||
static void lock_pvid_to_pvmeta(lvmetad_state *s) {
|
||||
@ -58,6 +60,16 @@ static void lock_pvid_to_vgid(lvmetad_state *s) {
|
||||
static void unlock_pvid_to_vgid(lvmetad_state *s) {
|
||||
pthread_mutex_unlock(&s->lock.pvid_to_vgid); }
|
||||
|
||||
static response reply_fail(const char *reason)
|
||||
{
|
||||
return daemon_reply_simple("failed", "reason = %s", reason, NULL);
|
||||
}
|
||||
|
||||
static response reply_unknown(const char *reason)
|
||||
{
|
||||
return daemon_reply_simple("unknown", "reason = %s", reason, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: It may be beneficial to clean up the vg lock hash from time to time,
|
||||
* since if we have many "rogue" requests for nonexistent things, we will keep
|
||||
@ -257,13 +269,13 @@ static response pv_lookup(lvmetad_state *s, request r)
|
||||
struct dm_config_node *pv;
|
||||
|
||||
if (!pvid && !devt)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need PVID or device", NULL);
|
||||
return reply_fail("need PVID or device");
|
||||
|
||||
if (!(res.cft = dm_config_create()))
|
||||
return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
|
||||
return reply_fail("out of memory");
|
||||
|
||||
if (!(res.cft->root = make_text_node(res.cft, "response", "OK", NULL, NULL)))
|
||||
return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
|
||||
return reply_fail("out of memory");
|
||||
|
||||
lock_pvid_to_pvmeta(s);
|
||||
if (!pvid && devt)
|
||||
@ -273,14 +285,14 @@ static response pv_lookup(lvmetad_state *s, request r)
|
||||
WARN(s, "pv_lookup: could not find device %" PRIu64, devt);
|
||||
unlock_pvid_to_pvmeta(s);
|
||||
dm_config_destroy(res.cft);
|
||||
return daemon_reply_simple("unknown", "reason = %s", "device not found", NULL);
|
||||
return reply_unknown("device not found");
|
||||
}
|
||||
|
||||
pv = make_pv_node(s, pvid, res.cft, NULL, res.cft->root);
|
||||
if (!pv) {
|
||||
unlock_pvid_to_pvmeta(s);
|
||||
dm_config_destroy(res.cft);
|
||||
return daemon_reply_simple("unknown", "reason = %s", "PV not found", NULL);
|
||||
return reply_unknown("PV not found");
|
||||
}
|
||||
|
||||
pv->key = "physical_volume";
|
||||
@ -381,12 +393,12 @@ static response vg_lookup(lvmetad_state *s, request r)
|
||||
DEBUG(s, "vg_lookup: updated uuid = %s, name = %s", uuid, name);
|
||||
|
||||
if (!uuid)
|
||||
return daemon_reply_simple("unknown", "reason = %s", "VG not found", NULL);
|
||||
return reply_unknown("VG not found");
|
||||
|
||||
cft = lock_vg(s, uuid);
|
||||
if (!cft || !cft->root) {
|
||||
unlock_vg(s, uuid);
|
||||
return daemon_reply_simple("unknown", "reason = %s", "UUID not found", NULL);
|
||||
return reply_unknown("UUID not found");
|
||||
}
|
||||
|
||||
metadata = cft->root;
|
||||
@ -426,7 +438,7 @@ static response vg_lookup(lvmetad_state *s, request r)
|
||||
return res;
|
||||
bad:
|
||||
unlock_vg(s, uuid);
|
||||
return daemon_reply_simple("failed", "reason = %s", "Out of memory", NULL);
|
||||
return reply_fail("out of memory");
|
||||
}
|
||||
|
||||
static int compare_value(struct dm_config_value *a, struct dm_config_value *b)
|
||||
@ -694,7 +706,7 @@ static response pv_gone(lvmetad_state *s, request r)
|
||||
pvid = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device));
|
||||
if (!pvid) {
|
||||
unlock_pvid_to_pvmeta(s);
|
||||
return daemon_reply_simple("unknown", "reason = %s", "device not in cache", NULL);
|
||||
return reply_unknown("device not in cache");
|
||||
}
|
||||
|
||||
DEBUG(s, "pv_gone (updated): %s / %" PRIu64, pvid, device);
|
||||
@ -709,7 +721,7 @@ static response pv_gone(lvmetad_state *s, request r)
|
||||
dm_config_destroy(pvmeta);
|
||||
return daemon_reply_simple("OK", NULL);
|
||||
} else
|
||||
return daemon_reply_simple("unknown", "reason = %s", "PVID does not exist", NULL);
|
||||
return reply_unknown("PVID does not exist");
|
||||
}
|
||||
|
||||
static response pv_found(lvmetad_state *s, request r)
|
||||
@ -726,12 +738,12 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
int complete = 0, orphan = 0;
|
||||
|
||||
if (!pvid)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need PV UUID", NULL);
|
||||
return reply_fail("need PV UUID");
|
||||
if (!pvmeta)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need PV metadata", NULL);
|
||||
return reply_fail("need PV metadata");
|
||||
|
||||
if (!dm_config_get_uint64(pvmeta, "pvmeta/device", &device))
|
||||
return daemon_reply_simple("failed", "reason = %s", "need PV device number", NULL);
|
||||
return reply_fail("need PV device number");
|
||||
|
||||
DEBUG(s, "pv_found %s, vgid = %s, device = %" PRIu64, pvid, vgid, device);
|
||||
|
||||
@ -745,14 +757,14 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
if (!(cft = dm_config_create()) ||
|
||||
!(cft->root = dm_config_clone_node(cft, pvmeta, 0))) {
|
||||
unlock_pvid_to_pvmeta(s);
|
||||
return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
|
||||
return reply_fail("out of memory");
|
||||
}
|
||||
|
||||
pvid_dup = dm_config_find_str(cft->root, "pvmeta/id", NULL);
|
||||
if (!dm_hash_insert(s->pvid_to_pvmeta, pvid, cft) ||
|
||||
!dm_hash_insert_binary(s->device_to_pvid, &device, sizeof(device), (void*)pvid_dup)) {
|
||||
unlock_pvid_to_pvmeta(s);
|
||||
return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
|
||||
return reply_fail("out of memory");
|
||||
}
|
||||
if (pvmeta_old)
|
||||
dm_config_destroy(pvmeta_old);
|
||||
@ -761,16 +773,15 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
|
||||
if (metadata) {
|
||||
if (!vgid)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need VG UUID", NULL);
|
||||
return reply_fail("need VG UUID");
|
||||
DEBUG(s, "obtained vgid = %s, vgname = %s", vgid, vgname);
|
||||
if (!vgname)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need VG name", NULL);
|
||||
return reply_fail("need VG name");
|
||||
if (daemon_request_int(r, "metadata/seqno", -1) < 0)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need VG seqno", NULL);
|
||||
return reply_fail("need VG seqno");
|
||||
|
||||
if (!update_metadata(s, vgname, vgid, metadata))
|
||||
return daemon_reply_simple("failed", "reason = %s",
|
||||
"metadata update failed", NULL);
|
||||
return reply_fail("metadata update failed");
|
||||
} else {
|
||||
lock_pvid_to_vgid(s);
|
||||
vgid = dm_hash_lookup(s->pvid_to_vgid, pvid);
|
||||
@ -784,8 +795,7 @@ static response pv_found(lvmetad_state *s, request r)
|
||||
orphan = 1;
|
||||
else {
|
||||
unlock_vg(s, vgid);
|
||||
return daemon_reply_simple("failed", "reason = %s",
|
||||
"non-orphan VG without metadata encountered", NULL);
|
||||
return reply_fail("non-orphan VG without metadata encountered");
|
||||
}
|
||||
unlock_vg(s, vgid);
|
||||
}
|
||||
@ -804,17 +814,16 @@ static response vg_update(lvmetad_state *s, request r)
|
||||
const char *vgname = daemon_request_str(r, "vgname", NULL);
|
||||
if (metadata) {
|
||||
if (!vgid)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need VG UUID", NULL);
|
||||
return reply_fail("need VG UUID");
|
||||
if (!vgname)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need VG name", NULL);
|
||||
return reply_fail("need VG name");
|
||||
if (daemon_request_int(r, "metadata/seqno", -1) < 0)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need VG seqno", NULL);
|
||||
return reply_fail("need VG seqno");
|
||||
|
||||
/* TODO defer metadata update here; add a separate vg_commit
|
||||
* call; if client does not commit, die */
|
||||
if (!update_metadata(s, vgname, vgid, metadata))
|
||||
return daemon_reply_simple("failed", "reason = %s",
|
||||
"metadata update failed", NULL);
|
||||
return reply_fail("metadata update failed");
|
||||
}
|
||||
return daemon_reply_simple("OK", NULL);
|
||||
}
|
||||
@ -824,7 +833,7 @@ static response vg_remove(lvmetad_state *s, request r)
|
||||
const char *vgid = daemon_request_str(r, "uuid", NULL);
|
||||
|
||||
if (!vgid)
|
||||
return daemon_reply_simple("failed", "reason = %s", "need VG UUID", NULL);
|
||||
return reply_fail("need VG UUID");
|
||||
|
||||
DEBUG(s, "vg_remove: %s", vgid);
|
||||
|
||||
@ -839,6 +848,24 @@ static response handler(daemon_state s, client_handle h, request r)
|
||||
{
|
||||
lvmetad_state *state = s.private;
|
||||
const char *rq = daemon_request_str(r, "request", "NONE");
|
||||
const char *token = daemon_request_str(r, "token", "NONE");
|
||||
|
||||
pthread_mutex_lock(&state->token_lock);
|
||||
if (!strcmp(rq, "token_update")) {
|
||||
strncpy(state->token, token, 128);
|
||||
state->token[127] = 0;
|
||||
pthread_mutex_unlock(&state->token_lock);
|
||||
return daemon_reply_simple("OK", NULL);
|
||||
}
|
||||
|
||||
if (strcmp(token, state->token)) {
|
||||
pthread_mutex_unlock(&state->token_lock);
|
||||
return daemon_reply_simple("token_mismatch",
|
||||
"expected = %s", state->token,
|
||||
"received = %s", token,
|
||||
"reason = %s", "token mismatch", NULL);
|
||||
}
|
||||
pthread_mutex_unlock(&state->token_lock);
|
||||
|
||||
/*
|
||||
* TODO Add a stats call, with transaction count/rate, time since last
|
||||
@ -869,7 +896,7 @@ static response handler(daemon_state s, client_handle h, request r)
|
||||
if (!strcmp(rq, "vg_list"))
|
||||
return vg_list(state, r);
|
||||
|
||||
return daemon_reply_simple("failed", "reason = %s", "no such request", NULL);
|
||||
return reply_fail("request not implemented");
|
||||
}
|
||||
|
||||
static int init(daemon_state *s)
|
||||
@ -885,11 +912,13 @@ static int init(daemon_state *s)
|
||||
ls->pvid_to_vgid = dm_hash_create(32);
|
||||
ls->vgname_to_vgid = dm_hash_create(32);
|
||||
ls->lock.vg = dm_hash_create(32);
|
||||
ls->token[0] = 0;
|
||||
pthread_mutexattr_init(&rec);
|
||||
pthread_mutexattr_settype(&rec, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
pthread_mutex_init(&ls->lock.pvid_to_pvmeta, &rec);
|
||||
pthread_mutex_init(&ls->lock.vgid_to_metadata, &rec);
|
||||
pthread_mutex_init(&ls->lock.pvid_to_vgid, NULL);
|
||||
pthread_mutex_init(&ls->token_lock, NULL);
|
||||
|
||||
/* Set up stderr logging depending on the -d option. */
|
||||
daemon_log_parse(ls->log, DAEMON_LOG_OUTLET_STDERR, ls->debug_config, 1);
|
||||
|
@ -79,6 +79,14 @@ devices {
|
||||
# Use anchors if you want to be really specific
|
||||
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
|
||||
|
||||
# Since "filter" is often overriden from command line, it is not suitable
|
||||
# for system-wide device filtering (udev rules, lvmetad). To hide devices
|
||||
# from LVM-specific udev processing and/or from lvmetad, you need to set
|
||||
# global_filter. The syntax is the same as for normal "filter"
|
||||
# above. Devices that fail the global_filter are not even opened by LVM.
|
||||
|
||||
# global_filter = []
|
||||
|
||||
# The results of the filtering are cached on disk to avoid
|
||||
# rescanning dud devices (which can take a very long time).
|
||||
# By default this cache is stored in the @DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@ directory
|
||||
|
2
lib/cache/lvmcache.c
vendored
2
lib/cache/lvmcache.c
vendored
@ -109,8 +109,6 @@ int lvmcache_init(void)
|
||||
_vg_global_lock_held = 0;
|
||||
}
|
||||
|
||||
lvmetad_init();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
167
lib/cache/lvmetad.c
vendored
167
lib/cache/lvmetad.c
vendored
@ -20,38 +20,120 @@
|
||||
#include "lvmcache.h"
|
||||
#include "lvmetad-client.h"
|
||||
#include "format-text.h" // TODO for disk_locn, used as a DA representation
|
||||
#include "filter.h"
|
||||
#include "assert.h"
|
||||
#include "crc.h"
|
||||
|
||||
static int _using_lvmetad = 0;
|
||||
static daemon_handle _lvmetad;
|
||||
static const char *_lvmetad_token;
|
||||
static int _lvmetad_use = 0;
|
||||
static int _lvmetad_connected = 0;
|
||||
|
||||
void lvmetad_init(void)
|
||||
static char *_lvmetad_token = NULL;
|
||||
static const char *_lvmetad_socket = NULL;
|
||||
static struct cmd_context *_lvmetad_cmd = NULL;
|
||||
|
||||
void lvmetad_disconnect(void)
|
||||
{
|
||||
const char *socket = getenv("LVM_LVMETAD_SOCKET");
|
||||
if (_using_lvmetad) { /* configured by the toolcontext */
|
||||
_lvmetad = lvmetad_open(socket ?: DEFAULT_RUN_DIR "/lvmetad.socket");
|
||||
if (_lvmetad.socket_fd < 0 || _lvmetad.error) {
|
||||
daemon_close(_lvmetad);
|
||||
_lvmetad_connected = 0;
|
||||
_lvmetad_cmd = NULL;
|
||||
}
|
||||
|
||||
void lvmetad_init(struct cmd_context *cmd)
|
||||
{
|
||||
if (_lvmetad_use && _lvmetad_socket && !_lvmetad_connected) {
|
||||
assert(_lvmetad_socket);
|
||||
_lvmetad = lvmetad_open(_lvmetad_socket);
|
||||
if (_lvmetad.socket_fd >= 0 && !_lvmetad.error) {
|
||||
_lvmetad_connected = 1;
|
||||
_lvmetad_cmd = cmd;
|
||||
} else
|
||||
log_warn("WARNING: Failed to connect to lvmetad: %s. Falling back to internal scanning.", strerror(_lvmetad.error));
|
||||
_using_lvmetad = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int lvmetad_active(void)
|
||||
{
|
||||
return _lvmetad_use && _lvmetad_connected;
|
||||
}
|
||||
|
||||
void lvmetad_set_active(int active)
|
||||
{
|
||||
_lvmetad_use = active;
|
||||
}
|
||||
|
||||
void lvmetad_set_token(const struct dm_config_value *filter)
|
||||
{
|
||||
if (_lvmetad_token)
|
||||
dm_free(_lvmetad_token);
|
||||
int ft = 0;
|
||||
while (filter && filter->type == DM_CFG_STRING) {
|
||||
ft = calc_crc(ft, (const uint8_t *) filter->v.str, strlen(filter->v.str));
|
||||
filter = filter->next;
|
||||
}
|
||||
if (!dm_asprintf(&_lvmetad_token, "filter:%u", ft))
|
||||
log_warn("WARNING: Failed to set lvmetad token. Out of memory?");
|
||||
}
|
||||
|
||||
void lvmetad_set_socket(const char *sock)
|
||||
{
|
||||
_lvmetad_socket = sock;
|
||||
}
|
||||
|
||||
static daemon_reply _lvmetad_send(const char *id, ...);
|
||||
|
||||
static int _token_update()
|
||||
{
|
||||
daemon_reply repl = _lvmetad_send("token_update", NULL);
|
||||
|
||||
if (strcmp(daemon_reply_str(repl, "response", ""), "OK")) {
|
||||
daemon_reply_destroy(repl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
daemon_reply_destroy(repl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static daemon_reply _lvmetad_send(const char *id, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, id);
|
||||
daemon_reply repl;
|
||||
daemon_request req = daemon_request_make(id);
|
||||
daemon_reply repl, token_set;
|
||||
daemon_request req;
|
||||
int try = 0;
|
||||
char *future_token;
|
||||
|
||||
// daemon_request_extend(req, "token", _lvmetad_token, NULL);
|
||||
retry:
|
||||
req = daemon_request_make(id);
|
||||
|
||||
if (_lvmetad_token)
|
||||
daemon_request_extend(req, "token = %s", _lvmetad_token, NULL);
|
||||
|
||||
va_start(ap, id);
|
||||
daemon_request_extend_v(req, ap);
|
||||
va_end(ap);
|
||||
|
||||
repl = daemon_send(_lvmetad, req);
|
||||
|
||||
daemon_request_destroy(req);
|
||||
|
||||
va_end(ap);
|
||||
if (!strcmp(daemon_reply_str(repl, "response", ""), "token_mismatch") && try < 2 && !test_mode()) {
|
||||
future_token = _lvmetad_token;
|
||||
_lvmetad_token = (char *) "update in progress";
|
||||
if (!_token_update()) goto out;
|
||||
|
||||
if (pvscan_lvmetad_all_devs(_lvmetad_cmd, NULL)) {
|
||||
_lvmetad_token = future_token;
|
||||
if (!_token_update()) goto out;
|
||||
}
|
||||
_lvmetad_token = future_token;
|
||||
++ try;
|
||||
daemon_reply_destroy(repl);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
out:
|
||||
return repl;
|
||||
}
|
||||
|
||||
@ -203,7 +285,7 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna
|
||||
struct pv_list *pvl;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!_using_lvmetad)
|
||||
if (!lvmetad_active())
|
||||
return NULL;
|
||||
|
||||
if (vgid) {
|
||||
@ -317,7 +399,7 @@ int lvmetad_vg_update(struct volume_group *vg)
|
||||
if (!vg)
|
||||
return 0;
|
||||
|
||||
if (!_using_lvmetad || test_mode())
|
||||
if (!lvmetad_active() || test_mode())
|
||||
return 1; /* fake it */
|
||||
|
||||
if (!(vgmeta = _export_vg_to_config_tree(vg)))
|
||||
@ -369,7 +451,7 @@ int lvmetad_vg_remove(struct volume_group *vg)
|
||||
daemon_reply reply;
|
||||
int result;
|
||||
|
||||
if (!_using_lvmetad || test_mode())
|
||||
if (!lvmetad_active() || test_mode())
|
||||
return 1; /* just fake it */
|
||||
|
||||
if (!id_write_format(&vg->id, uuid, sizeof(uuid)))
|
||||
@ -390,7 +472,7 @@ int lvmetad_pv_lookup(struct cmd_context *cmd, struct id pvid, int *found)
|
||||
int result = 0;
|
||||
struct dm_config_node *cn;
|
||||
|
||||
if (!_using_lvmetad)
|
||||
if (!lvmetad_active())
|
||||
return_0;
|
||||
|
||||
if (!id_write_format(&pvid, uuid, sizeof(uuid)))
|
||||
@ -423,7 +505,7 @@ int lvmetad_pv_lookup_by_dev(struct cmd_context *cmd, struct device *dev, int *f
|
||||
daemon_reply reply;
|
||||
struct dm_config_node *cn;
|
||||
|
||||
if (!_using_lvmetad)
|
||||
if (!lvmetad_active())
|
||||
return_0;
|
||||
|
||||
reply = _lvmetad_send("pv_lookup", "device = %d", dev->dev, NULL);
|
||||
@ -450,7 +532,7 @@ int lvmetad_pv_list_to_lvmcache(struct cmd_context *cmd)
|
||||
daemon_reply reply;
|
||||
struct dm_config_node *cn;
|
||||
|
||||
if (!_using_lvmetad)
|
||||
if (!lvmetad_active())
|
||||
return 1;
|
||||
|
||||
reply = _lvmetad_send("pv_list", NULL);
|
||||
@ -476,7 +558,7 @@ int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd)
|
||||
daemon_reply reply;
|
||||
struct dm_config_node *cn;
|
||||
|
||||
if (!_using_lvmetad)
|
||||
if (!lvmetad_active())
|
||||
return 1;
|
||||
|
||||
reply = _lvmetad_send("vg_list", NULL);
|
||||
@ -576,7 +658,7 @@ int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_
|
||||
const char *status;
|
||||
int result;
|
||||
|
||||
if (!_using_lvmetad || test_mode())
|
||||
if (!lvmetad_active() || test_mode())
|
||||
return 1;
|
||||
|
||||
if (!id_write_format(&pvid, uuid, sizeof(uuid)))
|
||||
@ -659,7 +741,7 @@ int lvmetad_pv_gone(dev_t device, const char *pv_name, activation_handler handle
|
||||
int result;
|
||||
int found;
|
||||
|
||||
if (!_using_lvmetad || test_mode())
|
||||
if (!lvmetad_active() || test_mode())
|
||||
return 1;
|
||||
|
||||
/*
|
||||
@ -669,7 +751,7 @@ int lvmetad_pv_gone(dev_t device, const char *pv_name, activation_handler handle
|
||||
* the whole stack from top to bottom (not yet upstream).
|
||||
*/
|
||||
|
||||
reply = daemon_send_simple(_lvmetad, "pv_gone", "device = %d", device, NULL);
|
||||
reply = _lvmetad_send("pv_gone", "device = %d", device, NULL);
|
||||
|
||||
result = _lvmetad_handle_reply(reply, "drop PV", pv_name, &found);
|
||||
/* We don't care whether or not the daemon had the PV cached. */
|
||||
@ -684,16 +766,6 @@ int lvmetad_pv_gone_by_dev(struct device *dev, activation_handler handler)
|
||||
return lvmetad_pv_gone(dev->dev, dev_name(dev), handler);
|
||||
}
|
||||
|
||||
int lvmetad_active(void)
|
||||
{
|
||||
return _using_lvmetad;
|
||||
}
|
||||
|
||||
void lvmetad_set_active(int active)
|
||||
{
|
||||
_using_lvmetad = active;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code implements pvscan --cache.
|
||||
*/
|
||||
@ -771,3 +843,30 @@ bad:
|
||||
"It is strongly recommended that you restart lvmetad immediately.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler)
|
||||
{
|
||||
struct dev_iter *iter;
|
||||
struct device *dev;
|
||||
int r = 1;
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->lvmetad_filter, 1))) {
|
||||
log_error("dev_iter creation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((dev = dev_iter_get(iter))) {
|
||||
if (!pvscan_lvmetad_single(cmd, dev, handler)) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sigint_caught())
|
||||
break;
|
||||
}
|
||||
|
||||
dev_iter_destroy(iter);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
27
lib/cache/lvmetad.h
vendored
27
lib/cache/lvmetad.h
vendored
@ -30,19 +30,36 @@ typedef int (*activation_handler) (struct volume_group *vg, int partial,
|
||||
* Initialise the communication with lvmetad. Normally called by
|
||||
* lvmcache_init. Sets up a global handle for our process.
|
||||
*/
|
||||
void lvmetad_init(void);
|
||||
void lvmetad_init(struct cmd_context *);
|
||||
|
||||
/*
|
||||
* Override the use of lvmetad for retrieving scan results and metadata.
|
||||
*/
|
||||
void lvmetad_set_active(int);
|
||||
|
||||
/*
|
||||
* Configure the socket that lvmetad_init will use to connect to the daemon.
|
||||
*/
|
||||
void lvmetad_set_socket(const char *);
|
||||
|
||||
/*
|
||||
* Check whether lvmetad is active (where active means both that it is running
|
||||
* and that we have a working connection with it).
|
||||
*/
|
||||
int lvmetad_active(void);
|
||||
|
||||
/*
|
||||
* Drop connection to lvmetad. A subsequent lvmetad_init() will re-establish
|
||||
* the connection (possibly at a different socket path).
|
||||
*/
|
||||
void lvmetad_disconnect(void);
|
||||
|
||||
/*
|
||||
* Set the "lvmetad validity token" (currently only consists of the lvmetad
|
||||
* filter. See lvm.conf.
|
||||
*/
|
||||
void lvmetad_set_token(const struct dm_config_value *filter);
|
||||
|
||||
/*
|
||||
* Send a new version of VG metadata to lvmetad. This is normally called after
|
||||
* vg_write but before vg_commit. After vg_commit, lvmetad_vg_commit is called
|
||||
@ -111,11 +128,16 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd,
|
||||
int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev,
|
||||
activation_handler handler);
|
||||
|
||||
int pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler);
|
||||
|
||||
# else /* LVMETAD_SUPPORT */
|
||||
|
||||
# define lvmetad_init() do { } while (0)
|
||||
# define lvmetad_init(cmd) do { } while (0)
|
||||
# define lvmetad_disconnect() do { } while (0)
|
||||
# define lvmetad_set_active(a) do { } while (0)
|
||||
# define lvmetad_set_socket(a) do { } while (0)
|
||||
# define lvmetad_active() (0)
|
||||
# define lvmetad_set_token(a) do { } while (0)
|
||||
# define lvmetad_vg_update(vg) (1)
|
||||
# define lvmetad_vg_remove(vg) (1)
|
||||
# define lvmetad_pv_found(pvid, device, fmt, label_sector, vg, handler) (1)
|
||||
@ -127,6 +149,7 @@ int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev,
|
||||
# define lvmetad_vg_list_to_lvmcache(cmd) (1)
|
||||
# define lvmetad_vg_lookup(cmd, vgname, vgid) (NULL)
|
||||
# define pvscan_lvmetad_single(cmd, dev, handler) (0)
|
||||
# define pvscan_lvmetad_all_devs(cmd, handler) (0)
|
||||
|
||||
# endif /* LVMETAD_SUPPORT */
|
||||
|
||||
|
@ -399,7 +399,20 @@ static int _process_config(struct cmd_context *cmd)
|
||||
(find_config_tree_int(cmd, "global/detect_internal_vg_cache_corruption",
|
||||
DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION));
|
||||
|
||||
lvmetad_disconnect();
|
||||
const char *lvmetad_socket = getenv("LVM_LVMETAD_SOCKET");
|
||||
if (!lvmetad_socket)
|
||||
lvmetad_socket = DEFAULT_RUN_DIR "/lvmetad.socket";
|
||||
|
||||
/* TODO?
|
||||
lvmetad_socket = find_config_tree_str(cmd, "lvmetad/socket_path",
|
||||
DEFAULT_RUN_DIR "/lvmetad.socket");
|
||||
*/
|
||||
lvmetad_set_socket(lvmetad_socket);
|
||||
cn = find_config_tree_node(cmd, "devices/global_filter");
|
||||
lvmetad_set_token(cn ? cn->v : NULL);
|
||||
lvmetad_set_active(find_config_tree_int(cmd, "global/use_lvmetad", 0));
|
||||
lvmetad_init(cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -818,13 +831,14 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
|
||||
{
|
||||
static char cache_file[PATH_MAX];
|
||||
const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
|
||||
struct dev_filter *f3, *f4;
|
||||
struct dev_filter *f3 = NULL, *f4 = NULL, *toplevel_components[2] = { 0 };
|
||||
struct stat st;
|
||||
const struct dm_config_node *cn;
|
||||
|
||||
cmd->dump_filter = 0;
|
||||
|
||||
if (!(f3 = _init_filter_components(cmd)))
|
||||
return_0;
|
||||
goto_bad;
|
||||
|
||||
init_ignore_suspended_devices(find_config_tree_int(cmd,
|
||||
"devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
|
||||
@ -843,8 +857,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
|
||||
cache_dir ? : DEFAULT_CACHE_SUBDIR,
|
||||
cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
|
||||
log_error("Persistent cache filename too long.");
|
||||
f3->destroy(f3);
|
||||
return 0;
|
||||
goto bad;
|
||||
}
|
||||
} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
|
||||
(dm_snprintf(cache_file, sizeof(cache_file),
|
||||
@ -852,8 +865,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
|
||||
cmd->system_dir, DEFAULT_CACHE_SUBDIR,
|
||||
DEFAULT_CACHE_FILE_PREFIX) < 0)) {
|
||||
log_error("Persistent cache filename too long.");
|
||||
f3->destroy(f3);
|
||||
return 0;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!dev_cache)
|
||||
@ -883,9 +895,26 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
|
||||
log_verbose("Failed to load existing device cache from %s",
|
||||
dev_cache);
|
||||
|
||||
cmd->filter = f4;
|
||||
if (!(cn = find_config_tree_node(cmd, "devices/global_filter"))) {
|
||||
cmd->filter = f4;
|
||||
} else if (!(cmd->lvmetad_filter = regex_filter_create(cn->v)))
|
||||
goto_bad;
|
||||
else {
|
||||
toplevel_components[0] = cmd->lvmetad_filter;
|
||||
toplevel_components[1] = f4;
|
||||
if (!(cmd->filter = composite_filter_create(2, toplevel_components)))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
return 1;
|
||||
bad:
|
||||
if (f3)
|
||||
f3->destroy(f3);
|
||||
if (f4)
|
||||
f4->destroy(f4);
|
||||
if (toplevel_components[0])
|
||||
toplevel_components[0]->destroy(toplevel_components[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct format_type *get_format_by_name(struct cmd_context *cmd, const char *format)
|
||||
@ -1495,6 +1524,8 @@ int refresh_filters(struct cmd_context *cmd)
|
||||
cmd->filter = NULL;
|
||||
}
|
||||
|
||||
cmd->lvmetad_filter = NULL;
|
||||
|
||||
if (!(r = _init_filters(cmd, 0)))
|
||||
stack;
|
||||
|
||||
|
@ -91,6 +91,7 @@ struct cmd_context {
|
||||
unsigned independent_metadata_areas:1; /* Active formats have MDAs outside PVs */
|
||||
|
||||
struct dev_filter *filter;
|
||||
struct dev_filter *lvmetad_filter;
|
||||
int dump_filter; /* Dump filter when exiting? */
|
||||
|
||||
struct dm_list config_files;
|
||||
|
@ -971,8 +971,8 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
|
||||
|
||||
if (dev_scan && !trust_cache()) {
|
||||
/* Flag gets reset between each command */
|
||||
if (!full_scan_done() && f)
|
||||
persistent_filter_wipe(f); /* Calls _full_scan(1) */
|
||||
if (!full_scan_done() && f && f->wipe)
|
||||
f->wipe(f); /* Calls _full_scan(1) */
|
||||
} else
|
||||
_full_scan(0);
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
struct dev_filter {
|
||||
int (*passes_filter) (struct dev_filter * f, struct device * dev);
|
||||
void (*destroy) (struct dev_filter * f);
|
||||
void (*wipe) (struct dev_filter * f);
|
||||
void *private;
|
||||
unsigned use_count;
|
||||
};
|
||||
|
@ -51,7 +51,7 @@ static int _init_hash(struct pfilter *pf)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int persistent_filter_wipe(struct dev_filter *f)
|
||||
static void _persistent_filter_wipe(struct dev_filter *f)
|
||||
{
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
|
||||
@ -60,8 +60,6 @@ int persistent_filter_wipe(struct dev_filter *f)
|
||||
|
||||
/* Trigger complete device scan */
|
||||
dev_cache_scan(1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_array(struct pfilter *pf, struct dm_config_tree *cft,
|
||||
@ -368,6 +366,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
|
||||
f->destroy = _persistent_destroy;
|
||||
f->use_count = 0;
|
||||
f->private = pf;
|
||||
f->wipe = _persistent_filter_wipe;
|
||||
|
||||
return f;
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
struct dev_filter *persistent_filter_create(struct dev_filter *f,
|
||||
const char *file);
|
||||
|
||||
int persistent_filter_wipe(struct dev_filter *f);
|
||||
int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out);
|
||||
int persistent_filter_dump(struct dev_filter *f, int merge_existing);
|
||||
|
||||
|
@ -221,8 +221,10 @@ static void chain_node(struct dm_config_node *cn,
|
||||
|
||||
if (parent && !parent->child)
|
||||
parent->child = cn;
|
||||
if (pre_sib)
|
||||
if (pre_sib) {
|
||||
cn->sib = pre_sib->sib;
|
||||
pre_sib->sib = cn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -527,5 +527,5 @@ target_at_least()
|
||||
|
||||
test -f DEVICES && devs=$(cat DEVICES)
|
||||
|
||||
unset LVM_VALGRIND
|
||||
#unset LVM_VALGRIND
|
||||
"$@"
|
||||
|
@ -106,32 +106,6 @@ static int _auto_activation_handler(struct volume_group *vg, int partial,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _pvscan_lvmetad_all_devs(struct cmd_context *cmd, activation_handler handler)
|
||||
{
|
||||
struct dev_iter *iter;
|
||||
struct device *dev;
|
||||
int r = 1;
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->filter, 1))) {
|
||||
log_error("dev_iter creation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((dev = dev_iter_get(iter))) {
|
||||
if (!pvscan_lvmetad_single(cmd, dev, handler)) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sigint_caught())
|
||||
break;
|
||||
}
|
||||
|
||||
dev_iter_destroy(iter);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
int ret = ECMD_PROCESSED;
|
||||
@ -168,7 +142,7 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
/* Scan everything? */
|
||||
if (!argc && !devno_args) {
|
||||
if (!_pvscan_lvmetad_all_devs(cmd, handler))
|
||||
if (!pvscan_lvmetad_all_devs(cmd, handler))
|
||||
ret = ECMD_FAILED;
|
||||
goto out;
|
||||
}
|
||||
@ -283,7 +257,8 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
persistent_filter_wipe(cmd->filter);
|
||||
if (cmd->filter->wipe)
|
||||
cmd->filter->wipe(cmd->filter);
|
||||
lvmcache_destroy(cmd, 1);
|
||||
|
||||
/* populate lvmcache */
|
||||
|
@ -181,7 +181,8 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
|
||||
vg_name_old, vg_name_new);
|
||||
|
||||
/* FIXME lvmcache corruption - vginfo duplicated instead of renamed */
|
||||
persistent_filter_wipe(cmd->filter);
|
||||
if (cmd->filter->wipe)
|
||||
cmd->filter->wipe(cmd->filter);
|
||||
lvmcache_destroy(cmd, 1);
|
||||
|
||||
return 1;
|
||||
|
@ -50,7 +50,8 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
persistent_filter_wipe(cmd->filter);
|
||||
if (cmd->filter->wipe)
|
||||
cmd->filter->wipe(cmd->filter);
|
||||
lvmcache_destroy(cmd, 1);
|
||||
|
||||
_lvmetad = lvmetad_active();
|
||||
|
Loading…
Reference in New Issue
Block a user