~ubuntu-branches/ubuntu/saucy/lvm2/saucy

« back to all changes in this revision

Viewing changes to daemons/lvmetad/lvmetad-core.c

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-05-30 11:02:10 UTC
  • mfrom: (3.1.28 sid)
  • Revision ID: package-import@ubuntu.com-20130530110210-q8bou4f333ruwhn0
Tags: 2.02.98-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - debian/patches/avoid-dev-block.patch: Prefer any other device name over
    names in /dev/block/ since lvm.conf won't handle this.
  - debian/rules:
    - copy .po file to .pot file for Rosetta (Ubuntu specific).
  - debian/{dmsetup,lvm2}-udeb.install:
    - install initramfs and udev hooks in udebs (Debian bug 504341).
  - auto-start VGs as their PVs are discovered (Ubuntu specific):
    - add debian/tree/lvm2/lib/udev/rules.d/85-lvm2.rules: use watershed plus
      the sledgehammer of vgscan/vgchange to turn on VGs as they come online.
    - debian/tree/lvm2/usr/share/initramfs-tools/scripts/hooks/lvm2:
      - add 85-lvm2.rules to the list of udev rules to copy.
      - depend on udev.
    - debian/control:
      - add versioned Depend on watershed in lvm2 for udev rules.
      - add Depends on watershed-udeb in lvm2-udeb for udev rules.
      - add versioned Depend/Breaks on udev in dmsetup for udev rules.
      - add Depend on initramfs-tools in dmsetup so system is not potentially
        rendered unbootable by out-of-order dpkg configuration.
      - In libdevmapper-event1.02.1 add Breaks: dmeventd
        (<< 2.02.95-4ubuntu1) due to debian symbol rename
    - debian/rules:
      - do not install local-top scripts since Ubuntu mounts root using udev.
      - do not install init scripts for lvm2, since udev starts LVM.
      - continue to build clvm support.
    - debian/lvm2.postinst: handle missing lvm2 init script.
    - debian/tree/dmsetup/lib/udev/rules.d/60-persistent-storage-dm.rules:
      watch dm devices for changes with inotify
  - add mountroot failure hooks to help fix bad boots (Debian bug 468115):
    - debian/tree/lvm2/usr/share/initramfs-tools/scripts/init-premount/lvm2
  - remaining changes to upstream event manager packages (Debian bug 514706):
    - debian/rules:
      - enable dmeventd during configure.
    - debian/dmeventd.{8,manpages}: install dmeventd files.
  - rename debian/clvm.defaults to debian/clvm.default so it is installed
    correctly.
  - debian/control: add dmsetup-udeb to libdevmapper1.02.1-udeb recommends.
  - debian/rules: make sure dmsetup and lvm2 initramfs-tools scripts are
    executable.  When the Ubuntu-specific ones are added with a patch,
    they may lose their executable bit.
  - Add and install clvmd resource agent
  - Add dependency on libudev-dev to libdevmapper-dev so that the .pc file
    works.
  - debian/{clvmd.ra,clvm.init}:
    - create /run/lvm if it doesn't exist.
  - debian/clvm.init:
    - exit 3 if not running on status action.
  - Call dh_installman so that our dmeventd manpage actually gets installed
  - Install the missing fsadm manpage.
  - Complete libdevmapper-dev multiarch:
    - move .so symlinks and pkgconfig files to multiarched locations.
    - mark libdevmapper-dev M-A: same

* Dropped changes, applied upstream:
  - Update Micron PCIe SSD and other device-types to latest available.
  - Cherry pick from upstream, remove unsupported udev_get_dev_path() call.
  - Move thin check to global section.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
#define _XOPEN_SOURCE 500  /* pthread */
16
16
 
17
17
#include "configure.h"
18
 
#include "daemon-shared.h"
 
18
#include "daemon-io.h"
 
19
#include "config-util.h"
19
20
#include "daemon-server.h"
 
21
#include "daemon-log.h"
 
22
#include "lvm-version.h"
20
23
 
21
24
#include <assert.h>
22
25
#include <pthread.h>
23
 
#include <malloc.h>
24
26
#include <stdint.h>
25
27
#include <unistd.h>
26
28
 
27
29
typedef struct {
 
30
        log_state *log; /* convenience */
 
31
        const char *log_config;
 
32
 
28
33
        struct dm_hash_table *pvid_to_pvmeta;
29
34
        struct dm_hash_table *device_to_pvid; /* shares locks with above */
30
35
 
34
39
        struct dm_hash_table *pvid_to_vgid;
35
40
        struct {
36
41
                struct dm_hash_table *vg;
 
42
                pthread_mutex_t vg_lock_map;
37
43
                pthread_mutex_t pvid_to_pvmeta;
38
44
                pthread_mutex_t vgid_to_metadata;
39
45
                pthread_mutex_t pvid_to_vgid;
40
46
        } lock;
 
47
        char token[128];
 
48
        pthread_mutex_t token_lock;
41
49
} lvmetad_state;
42
50
 
43
 
__attribute__ ((format(printf, 1, 2)))
44
 
static void debug(const char *fmt, ...) {
45
 
        va_list ap;
46
 
        va_start(ap, fmt);
47
 
        fprintf(stderr, "[D %lu] ", pthread_self());
48
 
        vfprintf(stderr, fmt, ap);
49
 
        va_end(ap);
50
 
        fflush(stderr);
51
 
}
52
 
 
53
 
static int debug_cft_line(const char *line, void *baton) {
54
 
        fprintf(stderr, "| %s\n", line);
55
 
        return 0;
56
 
}
57
 
 
58
 
static void debug_cft(const char *id, struct dm_config_node *n) {
59
 
        debug("%s\n", id);
60
 
        dm_config_write_node(n, &debug_cft_line, NULL);
 
51
static void destroy_metadata_hashes(lvmetad_state *s)
 
52
{
 
53
        struct dm_hash_node *n = NULL;
 
54
 
 
55
        n = dm_hash_get_first(s->vgid_to_metadata);
 
56
        while (n) {
 
57
                dm_config_destroy(dm_hash_get_data(s->vgid_to_metadata, n));
 
58
                n = dm_hash_get_next(s->vgid_to_metadata, n);
 
59
        }
 
60
 
 
61
        n = dm_hash_get_first(s->pvid_to_pvmeta);
 
62
        while (n) {
 
63
                dm_config_destroy(dm_hash_get_data(s->pvid_to_pvmeta, n));
 
64
                n = dm_hash_get_next(s->pvid_to_pvmeta, n);
 
65
        }
 
66
        dm_hash_destroy(s->pvid_to_pvmeta);
 
67
        dm_hash_destroy(s->vgid_to_metadata);
 
68
        dm_hash_destroy(s->vgid_to_vgname);
 
69
        dm_hash_destroy(s->vgname_to_vgid);
 
70
 
 
71
        n = dm_hash_get_first(s->device_to_pvid);
 
72
        while (n) {
 
73
                dm_free(dm_hash_get_data(s->device_to_pvid, n));
 
74
                n = dm_hash_get_next(s->device_to_pvid, n);
 
75
        }
 
76
 
 
77
        dm_hash_destroy(s->device_to_pvid);
 
78
        dm_hash_destroy(s->pvid_to_vgid);
 
79
}
 
80
 
 
81
static void create_metadata_hashes(lvmetad_state *s)
 
82
{
 
83
        s->pvid_to_pvmeta = dm_hash_create(32);
 
84
        s->device_to_pvid = dm_hash_create(32);
 
85
        s->vgid_to_metadata = dm_hash_create(32);
 
86
        s->vgid_to_vgname = dm_hash_create(32);
 
87
        s->pvid_to_vgid = dm_hash_create(32);
 
88
        s->vgname_to_vgid = dm_hash_create(32);
61
89
}
62
90
 
63
91
static void lock_pvid_to_pvmeta(lvmetad_state *s) {
75
103
static void unlock_pvid_to_vgid(lvmetad_state *s) {
76
104
        pthread_mutex_unlock(&s->lock.pvid_to_vgid); }
77
105
 
 
106
static response reply_fail(const char *reason)
 
107
{
 
108
        return daemon_reply_simple("failed", "reason = %s", reason, NULL);
 
109
}
 
110
 
 
111
static response reply_unknown(const char *reason)
 
112
{
 
113
        return daemon_reply_simple("unknown", "reason = %s", reason, NULL);
 
114
}
 
115
 
78
116
/*
79
117
 * TODO: It may be beneficial to clean up the vg lock hash from time to time,
80
118
 * since if we have many "rogue" requests for nonexistent things, we will keep
84
122
        pthread_mutex_t *vg;
85
123
        struct dm_config_tree *cft;
86
124
 
87
 
        lock_vgid_to_metadata(s);
 
125
        pthread_mutex_lock(&s->lock.vg_lock_map);
88
126
        vg = dm_hash_lookup(s->lock.vg, id);
89
127
        if (!vg) {
90
128
                pthread_mutexattr_t rec;
98
136
                        return NULL;
99
137
                }
100
138
        }
101
 
        // debug("lock VG %s\n", id);
 
139
        /* We never remove items from s->lock.vg => the pointer remains valid. */
 
140
        pthread_mutex_unlock(&s->lock.vg_lock_map);
 
141
 
 
142
        DEBUGLOG(s, "locking VG %s", id);
102
143
        pthread_mutex_lock(vg);
 
144
 
 
145
        /* Protect against structure changes of the vgid_to_metadata hash. */
 
146
        lock_vgid_to_metadata(s);
103
147
        cft = dm_hash_lookup(s->vgid_to_metadata, id);
104
148
        unlock_vgid_to_metadata(s);
105
149
        return cft;
108
152
static void unlock_vg(lvmetad_state *s, const char *id) {
109
153
        pthread_mutex_t *vg;
110
154
 
111
 
        // debug("unlock VG %s\n", id);
112
 
        lock_vgid_to_metadata(s); /* someone might be changing the s->lock.vg structure right
113
 
                                   * now, so avoid stepping on each other's toes */
 
155
        DEBUGLOG(s, "unlocking VG %s", id);
 
156
        /* Protect the s->lock.vg structure from concurrent access. */
 
157
        pthread_mutex_lock(&s->lock.vg_lock_map);
114
158
        if ((vg = dm_hash_lookup(s->lock.vg, id)))
115
159
                pthread_mutex_unlock(vg);
116
 
        unlock_vgid_to_metadata(s);
 
160
        pthread_mutex_unlock(&s->lock.vg_lock_map);
117
161
}
118
162
 
119
163
static struct dm_config_node *pvs(struct dm_config_node *vg)
124
168
        return pv;
125
169
}
126
170
 
127
 
/*
128
 
 * TODO: This set_flag function is pretty generic and might make sense in a
129
 
 * library here or there.
130
 
 */
131
 
static int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
132
 
                     const char *field, const char *flag, int want) {
133
 
        struct dm_config_value *value = NULL, *pred = NULL;
134
 
        struct dm_config_node *node = dm_config_find_node(parent->child, field);
135
 
        struct dm_config_value *new;
136
 
 
137
 
        if (node)
138
 
                value = node->v;
139
 
 
140
 
        while (value && value->type != DM_CFG_EMPTY_ARRAY && strcmp(value->v.str, flag)) {
141
 
                pred = value;
142
 
                value = value->next;
143
 
        }
144
 
 
145
 
        if (value && want)
146
 
                return 1;
147
 
 
148
 
        if (!value && !want)
149
 
                return 1;
150
 
 
151
 
        if (value && !want) {
152
 
                if (pred) {
153
 
                        pred->next = value->next;
154
 
                } else if (value == node->v && value->next) {
155
 
                        node->v = value->next;
156
 
                } else {
157
 
                        node->v->type = DM_CFG_EMPTY_ARRAY;
158
 
                }
159
 
        }
160
 
 
161
 
        if (!value && want) {
162
 
                if (!node) {
163
 
                        if (!(node = dm_config_create_node(cft, field)))
164
 
                                return 0;
165
 
                        node->sib = parent->child;
166
 
                        if (!(node->v = dm_config_create_value(cft)))
167
 
                                return 0;
168
 
                        node->v->type = DM_CFG_EMPTY_ARRAY;
169
 
                        node->parent = parent;
170
 
                        parent->child = node;
171
 
                }
172
 
                if (!(new = dm_config_create_value(cft))) {
173
 
                        /* FIXME error reporting */
174
 
                        return 0;
175
 
                }
176
 
                new->type = DM_CFG_STRING;
177
 
                new->v.str = flag;
178
 
                new->next = node->v;
179
 
                node->v = new;
180
 
        }
181
 
 
182
 
        return 1;
183
 
}
184
 
 
185
 
static struct dm_config_node *make_config_node(struct dm_config_tree *cft,
186
 
                                               const char *key,
187
 
                                               struct dm_config_node *parent,
188
 
                                               struct dm_config_node *pre_sib)
189
 
{
190
 
        struct dm_config_node *cn;
191
 
 
192
 
        if (!(cn = dm_config_create_node(cft, key)))
193
 
                return NULL;
194
 
 
195
 
        cn->parent = parent;
196
 
        cn->sib = NULL;
197
 
        cn->v = NULL;
198
 
        cn->child = NULL;
199
 
 
200
 
        if (parent && parent->child && !pre_sib) { /* find the last one */
201
 
                pre_sib = parent->child;
202
 
                while (pre_sib && pre_sib->sib)
203
 
                        pre_sib = pre_sib->sib;
204
 
        }
205
 
 
206
 
        if (parent && !parent->child)
207
 
                parent->child = cn;
208
 
        if (pre_sib)
209
 
                pre_sib->sib = cn;
210
 
 
211
 
        return cn;
212
 
}
213
 
 
214
 
static struct dm_config_node *make_text_node(struct dm_config_tree *cft,
215
 
                                             const char *key,
216
 
                                             const char *value,
217
 
                                             struct dm_config_node *parent,
218
 
                                             struct dm_config_node *pre_sib)
219
 
{
220
 
        struct dm_config_node *cn;
221
 
 
222
 
        if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
223
 
            !(cn->v = dm_config_create_value(cft)))
224
 
                return NULL;
225
 
 
226
 
        cn->v->type = DM_CFG_STRING;
227
 
        cn->v->v.str = value;
228
 
        return cn;
229
 
}
230
 
 
231
 
#if 0
232
 
static struct dm_config_node *make_int_node(struct dm_config_tree *cft,
233
 
                                            const char *key,
234
 
                                            int64_t value,
235
 
                                            struct dm_config_node *parent,
236
 
                                            struct dm_config_node *pre_sib)
237
 
{
238
 
        struct dm_config_node *cn;
239
 
 
240
 
        if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
241
 
            !(cn->v = dm_config_create_value(cft)))
242
 
                return NULL;
243
 
 
244
 
        cn->v->type = DM_CFG_INT;
245
 
        cn->v->v.i = value;
246
 
        return cn;
247
 
}
248
 
#endif
249
 
 
250
171
static void filter_metadata(struct dm_config_node *vg) {
251
172
        struct dm_config_node *pv = pvs(vg);
252
173
        while (pv) {
367
288
        struct dm_config_node *cn = NULL, *cn_pvs;
368
289
        struct dm_hash_node *n;
369
290
        const char *id;
370
 
        response res = { .buffer = NULL };
 
291
        response res;
 
292
 
 
293
        buffer_init( &res.buffer );
371
294
 
372
295
        if (!(res.cft = dm_config_create()))
373
296
                return res; /* FIXME error reporting */
393
316
{
394
317
        const char *pvid = daemon_request_str(r, "uuid", NULL);
395
318
        int64_t devt = daemon_request_int(r, "device", 0);
396
 
        response res = { .buffer = NULL };
 
319
        response res;
397
320
        struct dm_config_node *pv;
398
321
 
 
322
        buffer_init( &res.buffer );
 
323
 
399
324
        if (!pvid && !devt)
400
 
                return daemon_reply_simple("failed", "reason = %s", "need PVID or device", NULL);
 
325
                return reply_fail("need PVID or device");
401
326
 
402
327
        if (!(res.cft = dm_config_create()))
403
 
                return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
 
328
                return reply_fail("out of memory");
404
329
 
405
330
        if (!(res.cft->root = make_text_node(res.cft, "response", "OK", NULL, NULL)))
406
 
                return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
 
331
                return reply_fail("out of memory");
407
332
 
408
333
        lock_pvid_to_pvmeta(s);
409
334
        if (!pvid && devt)
410
335
                pvid = dm_hash_lookup_binary(s->device_to_pvid, &devt, sizeof(devt));
411
336
 
412
337
        if (!pvid) {
413
 
                debug("pv_lookup: could not find device %" PRIu64 "\n", devt);
 
338
                WARN(s, "pv_lookup: could not find device %" PRIu64, devt);
414
339
                unlock_pvid_to_pvmeta(s);
415
340
                dm_config_destroy(res.cft);
416
 
                return daemon_reply_simple("unknown", "reason = %s", "device not found", NULL);
 
341
                return reply_unknown("device not found");
417
342
        }
418
343
 
419
344
        pv = make_pv_node(s, pvid, res.cft, NULL, res.cft->root);
420
345
        if (!pv) {
421
346
                unlock_pvid_to_pvmeta(s);
422
347
                dm_config_destroy(res.cft);
423
 
                return daemon_reply_simple("unknown", "reason = %s", "PV not found", NULL);
 
348
                return reply_unknown("PV not found");
424
349
        }
425
350
 
426
351
        pv->key = "physical_volume";
435
360
        struct dm_hash_node *n;
436
361
        const char *id;
437
362
        const char *name;
438
 
        response res = { .buffer = NULL };
 
363
        response res;
 
364
 
 
365
        buffer_init( &res.buffer );
 
366
 
439
367
        if (!(res.cft = dm_config_create()))
440
368
                goto bad; /* FIXME: better error reporting */
441
369
 
502
430
{
503
431
        struct dm_config_tree *cft;
504
432
        struct dm_config_node *metadata, *n;
505
 
        response res = { .buffer = NULL };
 
433
        response res;
506
434
 
507
435
        const char *uuid = daemon_request_str(r, "uuid", NULL);
508
436
        const char *name = daemon_request_str(r, "name", NULL);
509
437
 
510
 
        debug("vg_lookup: uuid = %s, name = %s\n", uuid, name);
 
438
        buffer_init( &res.buffer );
 
439
 
 
440
        DEBUGLOG(s, "vg_lookup: uuid = %s, name = %s", uuid, name);
511
441
 
512
442
        if (!uuid || !name) {
513
443
                lock_vgid_to_metadata(s);
518
448
                unlock_vgid_to_metadata(s);
519
449
        }
520
450
 
521
 
        debug("vg_lookup: updated uuid = %s, name = %s\n", uuid, name);
 
451
        DEBUGLOG(s, "vg_lookup: updated uuid = %s, name = %s", uuid, name);
522
452
 
523
453
        if (!uuid)
524
 
                return daemon_reply_simple("unknown", "reason = %s", "VG not found", NULL);
 
454
                return reply_unknown("VG not found");
525
455
 
526
456
        cft = lock_vg(s, uuid);
527
457
        if (!cft || !cft->root) {
528
458
                unlock_vg(s, uuid);
529
 
                return daemon_reply_simple("unknown", "reason = %s", "UUID not found", NULL);
 
459
                return reply_unknown("UUID not found");
530
460
        }
531
461
 
532
462
        metadata = cft->root;
537
467
        if (!(res.cft->root = n = dm_config_create_node(res.cft, "response")))
538
468
                goto bad;
539
469
 
 
470
        if (!(n->v = dm_config_create_value(cft)))
 
471
                goto bad;
 
472
 
540
473
        n->parent = res.cft->root;
541
474
        n->v->type = DM_CFG_STRING;
542
475
        n->v->v.str = "OK";
543
476
 
544
477
        if (!(n = n->sib = dm_config_create_node(res.cft, "name")))
545
478
                goto bad;
 
479
 
 
480
        if (!(n->v = dm_config_create_value(res.cft)))
 
481
                goto bad;
 
482
 
546
483
        n->parent = res.cft->root;
547
484
        n->v->type = DM_CFG_STRING;
548
485
        n->v->v.str = name;
559
496
        return res;
560
497
bad:
561
498
        unlock_vg(s, uuid);
562
 
        return daemon_reply_simple("failed", "reason = %s", "Out of memory", NULL);
 
499
        return reply_fail("out of memory");
563
500
}
564
501
 
565
502
static int compare_value(struct dm_config_value *a, struct dm_config_value *b)
596
533
                result = compare_config(a->child, b->child);
597
534
 
598
535
        if (result) {
599
 
                debug("config inequality at %s / %s\n", a->key, b->key);
 
536
                // DEBUGLOG("config inequality at %s / %s", a->key, b->key);
600
537
                return result;
601
538
        }
602
539
 
622
559
        const char *pvid;
623
560
        const char *vgid_old;
624
561
        const char *check_vgid;
 
562
        int r = 0;
625
563
 
626
564
        if (!vgid)
627
565
                return 0;
636
574
                if (nuke_empty &&
637
575
                    (vgid_old = dm_hash_lookup(s->pvid_to_vgid, pvid)) &&
638
576
                    !dm_hash_insert(to_check, vgid_old, (void*) 1))
639
 
                        return 0;
 
577
                        goto out;
640
578
 
641
579
                if (!dm_hash_insert(s->pvid_to_vgid, pvid, (void*) vgid))
642
 
                        return 0;
 
580
                        goto out;
643
581
 
644
 
                debug("remap PV %s to VG %s\n", pvid, vgid);
 
582
                DEBUGLOG(s, "moving PV %s to VG %s", pvid, vgid);
645
583
        }
646
584
 
647
585
        for (n = dm_hash_get_first(to_check); n;
652
590
                unlock_vg(s, check_vgid);
653
591
        }
654
592
 
 
593
        r = 1;
 
594
    out:
655
595
        dm_hash_destroy(to_check);
656
596
 
657
 
        return 1;
 
597
        return r;
658
598
}
659
599
 
660
600
/* A pvid map lock needs to be held if update_pvids = 1. */
672
612
        assert(oldname);
673
613
 
674
614
        if (update_pvids)
 
615
                /* FIXME: What should happen when update fails */
675
616
                update_pvid_to_vgid(s, old, "#orphan", 0);
676
617
        /* need to update what we have since we found a newer version */
677
618
        dm_hash_remove(s->vgid_to_metadata, vgid);
708
649
        }
709
650
 
710
651
        if (missing) {
711
 
                debug("nuking VG %s\n", vgid);
 
652
                DEBUGLOG(s, "removing empty VG %s", vgid);
712
653
                remove_metadata(s, vgid, 0);
713
654
        }
714
655
 
721
662
 * this function, so they can be safely destroyed after update_metadata returns
722
663
 * (anything that might have been retained is copied). */
723
664
static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid,
724
 
                           struct dm_config_node *metadata)
 
665
                           struct dm_config_node *metadata, int64_t *oldseq)
725
666
{
726
 
        struct dm_config_tree *cft;
 
667
        struct dm_config_tree *cft = NULL;
727
668
        struct dm_config_tree *old;
728
669
        int retval = 0;
729
670
        int seq;
750
691
 
751
692
        filter_metadata(metadata); /* sanitize */
752
693
 
 
694
        if (oldseq) {
 
695
                if (old)
 
696
                        *oldseq = haveseq;
 
697
                else
 
698
                        *oldseq = seq;
 
699
        }
 
700
 
753
701
        if (seq == haveseq) {
754
702
                retval = 1;
755
703
                if (compare_config(metadata, old->root))
756
704
                        retval = 0;
757
 
                debug("Not updating metadata for %s at %d (%s)\n", _vgid, haveseq,
 
705
                DEBUGLOG(s, "Not updating metadata for %s at %d (%s)", _vgid, haveseq,
758
706
                      retval ? "ok" : "MISMATCH");
759
707
                if (!retval) {
760
 
                        debug_cft("OLD: ", old->root);
761
 
                        debug_cft("NEW: ", metadata);
 
708
                        DEBUGLOG_cft(s, "OLD: ", old->root);
 
709
                        DEBUGLOG_cft(s, "NEW: ", metadata);
762
710
                }
763
711
                goto out;
764
712
        }
765
713
 
766
714
        if (seq < haveseq) {
767
 
                debug("Refusing to update metadata for %s at %d to %d\n", _vgid, haveseq, seq);
 
715
                DEBUGLOG(s, "Refusing to update metadata for %s (at %d) to %d", _vgid, haveseq, seq);
768
716
                /* TODO: notify the client that their metadata is out of date? */
769
717
                retval = 1;
770
718
                goto out;
772
720
 
773
721
        if (!(cft = dm_config_create()) ||
774
722
            !(cft->root = dm_config_clone_node(cft, metadata, 0))) {
775
 
                debug("Out of memory\n");
 
723
                ERROR(s, "Out of memory");
776
724
                goto out;
777
725
        }
778
726
 
779
727
        vgid = dm_config_find_str(cft->root, "metadata/id", NULL);
780
728
 
781
729
        if (!vgid || !name) {
782
 
                debug("Name '%s' or uuid '%s' missing!\n", name, vgid);
 
730
                DEBUGLOG(s, "Name '%s' or uuid '%s' missing!", name, vgid);
783
731
                goto out;
784
732
        }
785
733
 
786
734
        lock_pvid_to_vgid(s);
787
735
 
788
736
        if (haveseq >= 0 && haveseq < seq) {
789
 
                debug("Updating metadata for %s at %d to %d\n", _vgid, haveseq, seq);
 
737
                INFO(s, "Updating metadata for %s at %d to %d", _vgid, haveseq, seq);
790
738
                /* temporarily orphan all of our PVs */
791
739
                remove_metadata(s, vgid, 1);
792
740
        }
793
741
 
794
742
        lock_vgid_to_metadata(s);
795
 
        debug("Mapping %s to %s\n", vgid, name);
 
743
        DEBUGLOG(s, "Mapping %s to %s", vgid, name);
796
744
 
797
745
        retval = ((cfgname = dm_pool_strdup(dm_config_memory(cft), name)) &&
798
746
                  dm_hash_insert(s->vgid_to_metadata, vgid, cft) &&
801
749
        unlock_vgid_to_metadata(s);
802
750
 
803
751
        if (retval)
804
 
                update_pvid_to_vgid(s, cft, vgid, 1);
 
752
                /* FIXME: What should happen when update fails */
 
753
                retval = update_pvid_to_vgid(s, cft, vgid, 1);
805
754
 
806
755
        unlock_pvid_to_vgid(s);
807
756
out:
 
757
        if (!retval && cft)
 
758
                dm_config_destroy(cft);
808
759
        unlock_vg(s, _vgid);
809
760
        return retval;
810
761
}
814
765
        const char *pvid = daemon_request_str(r, "uuid", NULL);
815
766
        int64_t device = daemon_request_int(r, "device", 0);
816
767
        struct dm_config_tree *pvmeta;
 
768
        char *pvid_old;
817
769
 
818
 
        debug("pv_gone: %s / %" PRIu64 "\n", pvid, device);
 
770
        DEBUGLOG(s, "pv_gone: %s / %" PRIu64, pvid, device);
819
771
 
820
772
        lock_pvid_to_pvmeta(s);
821
773
        if (!pvid && device > 0)
822
774
                pvid = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device));
823
775
        if (!pvid) {
824
776
                unlock_pvid_to_pvmeta(s);
825
 
                return daemon_reply_simple("unknown", "reason = %s", "device not in cache", NULL);
 
777
                return reply_unknown("device not in cache");
826
778
        }
827
779
 
828
 
        debug("pv_gone (updated): %s / %" PRIu64 "\n", pvid, device);
 
780
        DEBUGLOG(s, "pv_gone (updated): %s / %" PRIu64, pvid, device);
829
781
 
830
782
        pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, pvid);
 
783
        pvid_old = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device));
831
784
        dm_hash_remove_binary(s->device_to_pvid, &device, sizeof(device));
832
785
        dm_hash_remove(s->pvid_to_pvmeta, pvid);
833
786
        vg_remove_if_missing(s, dm_hash_lookup(s->pvid_to_vgid, pvid));
834
787
        unlock_pvid_to_pvmeta(s);
835
788
 
 
789
        if (pvid_old)
 
790
                dm_free(pvid_old);
 
791
 
836
792
        if (pvmeta) {
837
793
                dm_config_destroy(pvmeta);
838
794
                return daemon_reply_simple("OK", NULL);
839
795
        } else
840
 
                return daemon_reply_simple("unknown", "reason = %s", "PVID does not exist", NULL);
 
796
                return reply_unknown("PVID does not exist");
 
797
}
 
798
 
 
799
static response pv_clear_all(lvmetad_state *s, request r)
 
800
{
 
801
        DEBUGLOG(s, "pv_clear_all");
 
802
 
 
803
        lock_pvid_to_pvmeta(s);
 
804
        lock_vgid_to_metadata(s);
 
805
        lock_pvid_to_vgid(s);
 
806
 
 
807
        destroy_metadata_hashes(s);
 
808
        create_metadata_hashes(s);
 
809
 
 
810
        unlock_pvid_to_vgid(s);
 
811
        unlock_vgid_to_metadata(s);
 
812
        unlock_pvid_to_pvmeta(s);
 
813
 
 
814
        return daemon_reply_simple("OK", NULL);
841
815
}
842
816
 
843
817
static response pv_found(lvmetad_state *s, request r)
848
822
        const char *vgid = daemon_request_str(r, "metadata/id", NULL);
849
823
        struct dm_config_node *pvmeta = dm_config_find_node(r.cft->root, "pvmeta");
850
824
        uint64_t device;
851
 
        struct dm_config_tree *cft, *pvmeta_old = NULL;
852
 
        const char *old;
 
825
        struct dm_config_tree *cft, *pvmeta_old_dev = NULL, *pvmeta_old_pvid = NULL;
 
826
        char *old;
853
827
        const char *pvid_dup;
854
828
        int complete = 0, orphan = 0;
 
829
        int64_t seqno = -1, seqno_old = -1;
855
830
 
856
831
        if (!pvid)
857
 
                return daemon_reply_simple("failed", "reason = %s", "need PV UUID", NULL);
 
832
                return reply_fail("need PV UUID");
858
833
        if (!pvmeta)
859
 
                return daemon_reply_simple("failed", "reason = %s", "need PV metadata", NULL);
 
834
                return reply_fail("need PV metadata");
860
835
 
861
836
        if (!dm_config_get_uint64(pvmeta, "pvmeta/device", &device))
862
 
                return daemon_reply_simple("failed", "reason = %s", "need PV device number", NULL);
863
 
 
864
 
        debug("pv_found %s, vgid = %s, device = %" PRIu64 "\n", pvid, vgid, device);
 
837
                return reply_fail("need PV device number");
865
838
 
866
839
        lock_pvid_to_pvmeta(s);
867
840
 
868
841
        if ((old = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device)))) {
869
 
                pvmeta_old = dm_hash_lookup(s->pvid_to_pvmeta, old);
 
842
                pvmeta_old_dev = dm_hash_lookup(s->pvid_to_pvmeta, old);
870
843
                dm_hash_remove(s->pvid_to_pvmeta, old);
871
844
        }
 
845
        pvmeta_old_pvid = dm_hash_lookup(s->pvid_to_pvmeta, pvid);
 
846
 
 
847
        DEBUGLOG(s, "pv_found %s, vgid = %s, device = %" PRIu64 ", old = %s", pvid, vgid, device, old);
 
848
 
 
849
        dm_free(old);
872
850
 
873
851
        if (!(cft = dm_config_create()) ||
874
852
            !(cft->root = dm_config_clone_node(cft, pvmeta, 0))) {
875
853
                unlock_pvid_to_pvmeta(s);
876
 
                return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
 
854
                return reply_fail("out of memory");
877
855
        }
878
856
 
879
 
        pvid_dup = dm_config_find_str(cft->root, "pvmeta/id", NULL);
 
857
        pvid_dup = dm_strdup(pvid);
880
858
        if (!dm_hash_insert(s->pvid_to_pvmeta, pvid, cft) ||
881
859
            !dm_hash_insert_binary(s->device_to_pvid, &device, sizeof(device), (void*)pvid_dup)) {
882
860
                unlock_pvid_to_pvmeta(s);
883
 
                return daemon_reply_simple("failed", "reason = %s", "out of memory", NULL);
 
861
                return reply_fail("out of memory");
884
862
        }
885
 
        if (pvmeta_old)
886
 
                dm_config_destroy(pvmeta_old);
 
863
        if (pvmeta_old_pvid)
 
864
                dm_config_destroy(pvmeta_old_pvid);
 
865
        if (pvmeta_old_dev && pvmeta_old_dev != pvmeta_old_pvid)
 
866
                dm_config_destroy(pvmeta_old_dev);
887
867
 
888
868
        unlock_pvid_to_pvmeta(s);
889
869
 
890
870
        if (metadata) {
891
871
                if (!vgid)
892
 
                        return daemon_reply_simple("failed", "reason = %s", "need VG UUID", NULL);
893
 
                debug("obtained vgid = %s, vgname = %s\n", vgid, vgname);
 
872
                        return reply_fail("need VG UUID");
 
873
                DEBUGLOG(s, "obtained vgid = %s, vgname = %s", vgid, vgname);
894
874
                if (!vgname)
895
 
                        return daemon_reply_simple("failed", "reason = %s", "need VG name", NULL);
 
875
                        return reply_fail("need VG name");
896
876
                if (daemon_request_int(r, "metadata/seqno", -1) < 0)
897
 
                        return daemon_reply_simple("failed", "reason = %s", "need VG seqno", NULL);
 
877
                        return reply_fail("need VG seqno");
898
878
 
899
 
                if (!update_metadata(s, vgname, vgid, metadata))
900
 
                        return daemon_reply_simple("failed", "reason = %s",
901
 
                                                   "metadata update failed", NULL);
 
879
                if (!update_metadata(s, vgname, vgid, metadata, &seqno_old))
 
880
                        return reply_fail("metadata update failed");
902
881
        } else {
903
882
                lock_pvid_to_vgid(s);
904
883
                vgid = dm_hash_lookup(s->pvid_to_vgid, pvid);
906
885
        }
907
886
 
908
887
        if (vgid) {
909
 
                if ((cft = lock_vg(s, vgid)))
 
888
                if ((cft = lock_vg(s, vgid))) {
910
889
                        complete = update_pv_status(s, cft, cft->root, 0);
911
 
                else if (!strcmp(vgid, "#orphan"))
 
890
                        seqno = dm_config_find_int(cft->root, "metadata/seqno", -1);
 
891
                } else if (!strcmp(vgid, "#orphan"))
912
892
                        orphan = 1;
913
893
                else {
914
894
                        unlock_vg(s, vgid);
915
 
                        return daemon_reply_simple("failed", "reason = %s",
916
 
// FIXME provide meaningful-to-user error message
917
 
                                                   "internal treason!", NULL);
 
895
                        return reply_fail("non-orphan VG without metadata encountered");
918
896
                }
919
897
                unlock_vg(s, vgid);
920
898
        }
923
901
                                   "status = %s", orphan ? "orphan" :
924
902
                                                     (complete ? "complete" : "partial"),
925
903
                                   "vgid = %s", vgid ? vgid : "#orphan",
 
904
                                   "seqno_before = %"PRId64, seqno_old,
 
905
                                   "seqno_after = %"PRId64, seqno,
926
906
                                   NULL);
927
907
}
928
908
 
933
913
        const char *vgname = daemon_request_str(r, "vgname", NULL);
934
914
        if (metadata) {
935
915
                if (!vgid)
936
 
                        return daemon_reply_simple("failed", "reason = %s", "need VG UUID", NULL);
 
916
                        return reply_fail("need VG UUID");
937
917
                if (!vgname)
938
 
                        return daemon_reply_simple("failed", "reason = %s", "need VG name", NULL);
 
918
                        return reply_fail("need VG name");
939
919
                if (daemon_request_int(r, "metadata/seqno", -1) < 0)
940
 
                        return daemon_reply_simple("failed", "reason = %s", "need VG seqno", NULL);
 
920
                        return reply_fail("need VG seqno");
941
921
 
942
922
                /* TODO defer metadata update here; add a separate vg_commit
943
923
                 * call; if client does not commit, die */
944
 
                if (!update_metadata(s, vgname, vgid, metadata))
945
 
                        return daemon_reply_simple("failed", "reason = %s",
946
 
                                                   "metadata update failed", NULL);
 
924
                if (!update_metadata(s, vgname, vgid, metadata, NULL))
 
925
                        return reply_fail("metadata update failed");
947
926
        }
948
927
        return daemon_reply_simple("OK", NULL);
949
928
}
953
932
        const char *vgid = daemon_request_str(r, "uuid", NULL);
954
933
 
955
934
        if (!vgid)
956
 
                return daemon_reply_simple("failed", "reason = %s", "need VG UUID", NULL);
 
935
                return reply_fail("need VG UUID");
957
936
 
958
 
        fprintf(stderr, "vg_remove: %s\n", vgid);
 
937
        DEBUGLOG(s, "vg_remove: %s", vgid);
959
938
 
960
939
        lock_pvid_to_vgid(s);
961
940
        remove_metadata(s, vgid, 1);
964
943
        return daemon_reply_simple("OK", NULL);
965
944
}
966
945
 
 
946
static void _dump_cft(struct buffer *buf, struct dm_hash_table *ht, const char *key_addr)
 
947
{
 
948
        struct dm_hash_node *n = dm_hash_get_first(ht);
 
949
        while (n) {
 
950
                struct dm_config_tree *cft = dm_hash_get_data(ht, n);
 
951
                const char *key_backup = cft->root->key;
 
952
                cft->root->key = dm_config_find_str(cft->root, key_addr, "unknown");
 
953
                dm_config_write_node(cft->root, buffer_line, buf);
 
954
                cft->root->key = key_backup;
 
955
                n = dm_hash_get_next(ht, n);
 
956
        }
 
957
}
 
958
 
 
959
static void _dump_pairs(struct buffer *buf, struct dm_hash_table *ht, const char *name, int int_key)
 
960
{
 
961
        char *append;
 
962
        struct dm_hash_node *n = dm_hash_get_first(ht);
 
963
 
 
964
        buffer_append(buf, name);
 
965
        buffer_append(buf, " {\n");
 
966
 
 
967
        while (n) {
 
968
                const char *key = dm_hash_get_key(ht, n),
 
969
                           *val = dm_hash_get_data(ht, n);
 
970
                buffer_append(buf, "    ");
 
971
                if (int_key)
 
972
                        dm_asprintf(&append, "%d = \"%s\"", *(int*)key, val);
 
973
                else
 
974
                        dm_asprintf(&append, "%s = \"%s\"", key, val);
 
975
                if (append)
 
976
                        buffer_append(buf, append);
 
977
                buffer_append(buf, "\n");
 
978
                dm_free(append);
 
979
                n = dm_hash_get_next(ht, n);
 
980
        }
 
981
        buffer_append(buf, "}\n");
 
982
}
 
983
 
 
984
static response dump(lvmetad_state *s)
 
985
{
 
986
        response res;
 
987
        struct buffer *b = &res.buffer;
 
988
 
 
989
        buffer_init(b);
 
990
 
 
991
        /* Lock everything so that we get a consistent dump. */
 
992
 
 
993
        lock_vgid_to_metadata(s);
 
994
        lock_pvid_to_pvmeta(s);
 
995
        lock_pvid_to_vgid(s);
 
996
 
 
997
        buffer_append(b, "# VG METADATA\n\n");
 
998
        _dump_cft(b, s->vgid_to_metadata, "metadata/id");
 
999
 
 
1000
        buffer_append(b, "\n# PV METADATA\n\n");
 
1001
        _dump_cft(b, s->pvid_to_pvmeta, "pvmeta/id");
 
1002
 
 
1003
        buffer_append(b, "\n# VGID to VGNAME mapping\n\n");
 
1004
        _dump_pairs(b, s->vgid_to_vgname, "vgid_to_vgname", 0);
 
1005
 
 
1006
        buffer_append(b, "\n# VGNAME to VGID mapping\n\n");
 
1007
        _dump_pairs(b, s->vgname_to_vgid, "vgname_to_vgid", 0);
 
1008
 
 
1009
        buffer_append(b, "\n# PVID to VGID mapping\n\n");
 
1010
        _dump_pairs(b, s->pvid_to_vgid, "pvid_to_vgid", 0);
 
1011
 
 
1012
        buffer_append(b, "\n# DEVICE to PVID mapping\n\n");
 
1013
        _dump_pairs(b, s->device_to_pvid, "device_to_pvid", 1);
 
1014
 
 
1015
        unlock_pvid_to_vgid(s);
 
1016
        unlock_pvid_to_pvmeta(s);
 
1017
        unlock_vgid_to_metadata(s);
 
1018
 
 
1019
        return res;
 
1020
}
 
1021
 
967
1022
static response handler(daemon_state s, client_handle h, request r)
968
1023
{
969
1024
        lvmetad_state *state = s.private;
970
1025
        const char *rq = daemon_request_str(r, "request", "NONE");
 
1026
        const char *token = daemon_request_str(r, "token", "NONE");
 
1027
 
 
1028
        pthread_mutex_lock(&state->token_lock);
 
1029
        if (!strcmp(rq, "token_update")) {
 
1030
                strncpy(state->token, token, 128);
 
1031
                state->token[127] = 0;
 
1032
                pthread_mutex_unlock(&state->token_lock);
 
1033
                return daemon_reply_simple("OK", NULL);
 
1034
        }
 
1035
 
 
1036
        if (strcmp(token, state->token) && strcmp(rq, "dump")) {
 
1037
                pthread_mutex_unlock(&state->token_lock);
 
1038
                return daemon_reply_simple("token_mismatch",
 
1039
                                           "expected = %s", state->token,
 
1040
                                           "received = %s", token,
 
1041
                                           "reason = %s", "token mismatch", NULL);
 
1042
        }
 
1043
        pthread_mutex_unlock(&state->token_lock);
971
1044
 
972
1045
        /*
973
1046
         * TODO Add a stats call, with transaction count/rate, time since last
979
1052
        if (!strcmp(rq, "pv_gone"))
980
1053
                return pv_gone(state, r);
981
1054
 
 
1055
        if (!strcmp(rq, "pv_clear_all"))
 
1056
                return pv_clear_all(state, r);
 
1057
 
982
1058
        if (!strcmp(rq, "pv_lookup"))
983
1059
                return pv_lookup(state, r);
984
1060
 
991
1067
        if (!strcmp(rq, "vg_lookup"))
992
1068
                return vg_lookup(state, r);
993
1069
 
994
 
        if (!strcmp(rq, "pv_list")) {
 
1070
        if (!strcmp(rq, "pv_list"))
995
1071
                return pv_list(state, r);
996
 
        }
997
1072
 
998
1073
        if (!strcmp(rq, "vg_list"))
999
1074
                return vg_list(state, r);
1000
1075
 
1001
 
        return daemon_reply_simple("failed", "reason = %s", "no such request", NULL);
 
1076
        if (!strcmp(rq, "dump"))
 
1077
                return dump(state);
 
1078
 
 
1079
        return reply_fail("request not implemented");
1002
1080
}
1003
1081
 
1004
1082
static int init(daemon_state *s)
1005
1083
{
1006
1084
        pthread_mutexattr_t rec;
1007
1085
        lvmetad_state *ls = s->private;
 
1086
        ls->log = s->log;
1008
1087
 
1009
 
        ls->pvid_to_pvmeta = dm_hash_create(32);
1010
 
        ls->device_to_pvid = dm_hash_create(32);
1011
 
        ls->vgid_to_metadata = dm_hash_create(32);
1012
 
        ls->vgid_to_vgname = dm_hash_create(32);
1013
 
        ls->pvid_to_vgid = dm_hash_create(32);
1014
 
        ls->vgname_to_vgid = dm_hash_create(32);
1015
 
        ls->lock.vg = dm_hash_create(32);
1016
1088
        pthread_mutexattr_init(&rec);
1017
1089
        pthread_mutexattr_settype(&rec, PTHREAD_MUTEX_RECURSIVE_NP);
1018
1090
        pthread_mutex_init(&ls->lock.pvid_to_pvmeta, &rec);
1019
1091
        pthread_mutex_init(&ls->lock.vgid_to_metadata, &rec);
1020
1092
        pthread_mutex_init(&ls->lock.pvid_to_vgid, NULL);
1021
 
 
1022
 
        debug("initialised state: vgid_to_metadata = %p\n", ls->vgid_to_metadata);
 
1093
        pthread_mutex_init(&ls->lock.vg_lock_map, NULL);
 
1094
        pthread_mutex_init(&ls->token_lock, NULL);
 
1095
        create_metadata_hashes(ls);
 
1096
 
 
1097
        ls->lock.vg = dm_hash_create(32);
 
1098
        ls->token[0] = 0;
 
1099
 
 
1100
        /* Set up stderr logging depending on the -l option. */
 
1101
        if (!daemon_log_parse(ls->log, DAEMON_LOG_OUTLET_STDERR, ls->log_config, 1))
 
1102
                return 0;
 
1103
 
 
1104
        DEBUGLOG(s, "initialised state: vgid_to_metadata = %p", ls->vgid_to_metadata);
1023
1105
        if (!ls->pvid_to_vgid || !ls->vgid_to_metadata)
1024
1106
                return 0;
1025
1107
 
1032
1114
static int fini(daemon_state *s)
1033
1115
{
1034
1116
        lvmetad_state *ls = s->private;
1035
 
        struct dm_hash_node *n = dm_hash_get_first(ls->vgid_to_metadata);
1036
 
 
1037
 
        debug("fini\n");
1038
 
        while (n) {
1039
 
                dm_config_destroy(dm_hash_get_data(ls->vgid_to_metadata, n));
1040
 
                n = dm_hash_get_next(ls->vgid_to_metadata, n);
1041
 
        }
1042
 
 
1043
 
        n = dm_hash_get_first(ls->pvid_to_pvmeta);
1044
 
        while (n) {
1045
 
                dm_config_destroy(dm_hash_get_data(ls->pvid_to_pvmeta, n));
1046
 
                n = dm_hash_get_next(ls->pvid_to_pvmeta, n);
1047
 
        }
1048
 
 
 
1117
        struct dm_hash_node *n;
 
1118
 
 
1119
        DEBUGLOG(s, "fini");
 
1120
 
 
1121
        destroy_metadata_hashes(ls);
 
1122
 
 
1123
        /* Destroy the lock hashes now. */
1049
1124
        n = dm_hash_get_first(ls->lock.vg);
1050
1125
        while (n) {
1051
1126
                pthread_mutex_destroy(dm_hash_get_data(ls->lock.vg, n));
1054
1129
        }
1055
1130
 
1056
1131
        dm_hash_destroy(ls->lock.vg);
1057
 
        dm_hash_destroy(ls->pvid_to_pvmeta);
1058
 
        dm_hash_destroy(ls->device_to_pvid);
1059
 
        dm_hash_destroy(ls->vgid_to_metadata);
1060
 
        dm_hash_destroy(ls->vgid_to_vgname);
1061
 
        dm_hash_destroy(ls->vgname_to_vgid);
1062
 
        dm_hash_destroy(ls->pvid_to_vgid);
1063
1132
        return 1;
1064
1133
}
1065
1134
 
1066
1135
static void usage(char *prog, FILE *file)
1067
1136
{
1068
1137
        fprintf(file, "Usage:\n"
1069
 
                "%s [-V] [-h] [-d] [-d] [-d] [-f]\n\n"
 
1138
                "%s [-V] [-h] [-f] [-l {all|wire|debug}] [-s path]\n\n"
1070
1139
                "   -V       Show version of lvmetad\n"
1071
1140
                "   -h       Show this help information\n"
1072
 
                "   -d       Log debug messages to syslog (-d, -dd, -ddd)\n"
1073
 
                "   -R       Replace a running lvmetad instance, loading its data\n"
1074
 
                "   -f       Don't fork, run in the foreground\n\n", prog);
 
1141
                "   -f       Don't fork, run in the foreground\n"
 
1142
                "   -l       Logging message level (-l {all|wire|debug})\n"
 
1143
                "   -s       Set path to the socket to listen on\n\n", prog);
1075
1144
}
1076
1145
 
1077
1146
int main(int argc, char *argv[])
1079
1148
        signed char opt;
1080
1149
        daemon_state s = { .private = NULL };
1081
1150
        lvmetad_state ls;
1082
 
        int _restart = 0;
 
1151
        int _socket_override = 1;
1083
1152
 
1084
1153
        s.name = "lvmetad";
1085
1154
        s.private = &ls;
1087
1156
        s.daemon_fini = fini;
1088
1157
        s.handler = handler;
1089
1158
        s.socket_path = getenv("LVM_LVMETAD_SOCKET");
1090
 
        if (!s.socket_path)
 
1159
        if (!s.socket_path) {
 
1160
                _socket_override = 0;
1091
1161
                s.socket_path = DEFAULT_RUN_DIR "/lvmetad.socket";
1092
 
        s.pidfile = DEFAULT_RUN_DIR "/lvmetad.pid";
1093
 
        s.log_level = 0;
 
1162
        }
 
1163
        s.pidfile = LVMETAD_PIDFILE;
1094
1164
        s.protocol = "lvmetad";
1095
1165
        s.protocol_version = 1;
 
1166
        ls.log_config = "";
1096
1167
 
1097
1168
        // use getopt_long
1098
 
        while ((opt = getopt(argc, argv, "?fhVdRs:")) != EOF) {
 
1169
        while ((opt = getopt(argc, argv, "?fhVl:s:")) != EOF) {
1099
1170
                switch (opt) {
1100
1171
                case 'h':
1101
1172
                        usage(argv[0], stdout);
1103
1174
                case '?':
1104
1175
                        usage(argv[0], stderr);
1105
1176
                        exit(0);
1106
 
                case 'R':
1107
 
                        _restart++;
1108
 
                        break;
1109
1177
                case 'f':
1110
1178
                        s.foreground = 1;
1111
1179
                        break;
1112
 
                case 'd':
1113
 
                        s.log_level++;
 
1180
                case 'l':
 
1181
                        ls.log_config = optarg;
1114
1182
                        break;
1115
1183
                case 's': // --socket
1116
1184
                        s.socket_path = optarg;
 
1185
                        _socket_override = 1;
1117
1186
                        break;
1118
1187
                case 'V':
1119
 
                        printf("lvmetad version 0\n");
 
1188
                        printf("lvmetad version: " LVM_VERSION "\n");
1120
1189
                        exit(1);
1121
1190
                }
1122
1191
        }
1123
1192
 
 
1193
        if (s.foreground) {
 
1194
                if (!_socket_override) {
 
1195
                        fprintf(stderr, "A socket path (-s) is required in foreground mode.");
 
1196
                        exit(2);
 
1197
                } else {
 
1198
                        s.pidfile = NULL;
 
1199
                }
 
1200
        }
 
1201
 
1124
1202
        daemon_start(s);
1125
1203
        return 0;
1126
1204
}