~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/blktap2/lvm/lvm-util.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * Copyright (c) 2008, XenSource Inc.
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 *     * Redistributions of source code must retain the above copyright
 
8
 *       notice, this list of conditions and the following disclaimer.
 
9
 *     * Redistributions in binary form must reproduce the above copyright
 
10
 *       notice, this list of conditions and the following disclaimer in the
 
11
 *       documentation and/or other materials provided with the distribution.
 
12
 *     * Neither the name of XenSource Inc. nor the names of its contributors
 
13
 *       may be used to endorse or promote products derived from this software
 
14
 *       without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
17
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
18
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
19
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 
20
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
21
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
22
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
23
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 
24
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 
25
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
26
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
#include <stdio.h>
 
29
#include <errno.h>
 
30
#include <stdlib.h>
 
31
#include <string.h>
 
32
 
 
33
#include "lvm-util.h"
 
34
 
 
35
#define _NAME "%255s"
 
36
static char line[1024];
 
37
 
 
38
static inline int
 
39
lvm_read_line(FILE *scan)
 
40
{
 
41
        memset(line, 0, sizeof(line));
 
42
        return (fscanf(scan, "%1023[^\n]", line) != 1);
 
43
}
 
44
 
 
45
static inline int
 
46
lvm_next_line(FILE *scan)
 
47
{
 
48
        return (fscanf(scan, "%1023[\n]", line) != 1);
 
49
}
 
50
 
 
51
static int
 
52
lvm_copy_name(char *dst, const char *src, size_t size)
 
53
{
 
54
        if (strnlen(src, size) == size)
 
55
                return -ENAMETOOLONG;
 
56
 
 
57
        strcpy(dst, src);
 
58
        return 0;
 
59
}
 
60
 
 
61
static int
 
62
lvm_parse_pv(struct vg *vg, const char *name, int pvs, uint64_t start)
 
63
{
 
64
        int i, err;
 
65
        struct pv *pv;
 
66
 
 
67
        pv = NULL;
 
68
 
 
69
        if (!vg->pvs) {
 
70
                vg->pvs = calloc(pvs, sizeof(struct pv));
 
71
                if (!vg->pvs)
 
72
                        return -ENOMEM;
 
73
        }
 
74
 
 
75
        for (i = 0; i < pvs; i++) {
 
76
                pv = vg->pvs + i;
 
77
 
 
78
                if (!pv->name[0])
 
79
                        break;
 
80
 
 
81
                if (!strcmp(pv->name, name))
 
82
                        return -EEXIST;
 
83
        }
 
84
 
 
85
        if (!pv)
 
86
                return -ENOENT;
 
87
 
 
88
        if (i == pvs)
 
89
                return -ENOMEM;
 
90
 
 
91
        err = lvm_copy_name(pv->name, name, sizeof(pv->name) - 1);
 
92
        if (err)
 
93
                return err;
 
94
 
 
95
        pv->start = start;
 
96
        return 0;
 
97
}
 
98
 
 
99
static int
 
100
lvm_open_vg(const char *vgname, struct vg *vg)
 
101
{
 
102
        FILE *scan;
 
103
        int i, err, pvs, lvs;
 
104
        char *cmd, pvname[256];
 
105
        uint64_t size, pv_start;
 
106
 
 
107
        memset(vg, 0, sizeof(*vg));
 
108
 
 
109
        err = asprintf(&cmd, "/usr/sbin/vgs %s --noheadings --nosuffix --units=b "
 
110
                       "--options=vg_name,vg_extent_size,lv_count,pv_count,"
 
111
                       "pv_name,pe_start --unbuffered 2> /dev/null", vgname);
 
112
        if (err == -1)
 
113
                return -ENOMEM;
 
114
 
 
115
        errno = 0;
 
116
        scan  = popen(cmd, "r");
 
117
        if (!scan) {
 
118
                err = (errno ? -errno : ENOMEM);
 
119
                goto out;
 
120
        }
 
121
 
 
122
        for (;;) {
 
123
                if (lvm_read_line(scan))
 
124
                        break;
 
125
 
 
126
                err = -EINVAL;
 
127
                if (sscanf(line, _NAME" %"SCNu64" %d %d "_NAME" %"SCNu64,
 
128
                           vg->name, &size, &lvs, &pvs, pvname, &pv_start) != 6)
 
129
                        goto out;
 
130
 
 
131
                if (strcmp(vg->name, vgname))
 
132
                        goto out;
 
133
 
 
134
                err = lvm_parse_pv(vg, pvname, pvs, pv_start);
 
135
                if (err)
 
136
                        goto out;
 
137
 
 
138
                if (lvm_next_line(scan))
 
139
                        break;
 
140
        }
 
141
 
 
142
        err = -EINVAL;
 
143
        if (strcmp(vg->name, vgname))
 
144
                goto out;
 
145
 
 
146
        for (i = 0; i < pvs; i++)
 
147
                if (!vg->pvs[i].name[0])
 
148
                        goto out;
 
149
 
 
150
        err = -ENOMEM;
 
151
        vg->lvs = calloc(lvs, sizeof(struct lv));
 
152
        if (!vg->lvs)
 
153
                goto out;
 
154
 
 
155
        err             = 0;
 
156
        vg->lv_cnt      = lvs;
 
157
        vg->pv_cnt      = pvs;
 
158
        vg->extent_size = size;
 
159
 
 
160
out:
 
161
        if (scan)
 
162
                pclose(scan);
 
163
        if (err)
 
164
                lvm_free_vg(vg);
 
165
        free(cmd);
 
166
        return err;
 
167
}
 
168
 
 
169
static int
 
170
lvm_parse_lv_devices(struct vg *vg, struct lv_segment *seg, char *devices)
 
171
{
 
172
        int i;
 
173
        uint64_t start, pe_start;
 
174
 
 
175
        for (i = 0; i < strlen(devices); i++)
 
176
                if (strchr(",()", devices[i]))
 
177
                        devices[i] = ' ';
 
178
 
 
179
        if (sscanf(devices, _NAME" %"SCNu64, seg->device, &start) != 2)
 
180
                return -EINVAL;
 
181
 
 
182
        pe_start = -1;
 
183
        for (i = 0; i < vg->pv_cnt; i++)
 
184
                if (!strcmp(vg->pvs[i].name, seg->device)) {
 
185
                        pe_start = vg->pvs[i].start;
 
186
                        break;
 
187
                }
 
188
 
 
189
        if (pe_start == -1)
 
190
                return -EINVAL;
 
191
 
 
192
        seg->pe_start = (start * vg->extent_size) + pe_start;
 
193
        return 0;
 
194
}
 
195
 
 
196
static int
 
197
lvm_scan_lvs(struct vg *vg)
 
198
{
 
199
        char *cmd;
 
200
        FILE *scan;
 
201
        int i, err;
 
202
 
 
203
        err = asprintf(&cmd, "/usr/sbin/lvs %s --noheadings --nosuffix --units=b "
 
204
                       "--options=lv_name,lv_size,segtype,seg_count,seg_start,"
 
205
                       "seg_size,devices --unbuffered 2> /dev/null", vg->name);
 
206
        if (err == -1)
 
207
                return -ENOMEM;
 
208
 
 
209
        errno = 0;
 
210
        scan  = popen(cmd, "r");
 
211
        if (!scan) {
 
212
                err = (errno ? -errno : -ENOMEM);
 
213
                goto out;
 
214
        }
 
215
 
 
216
        for (i = 0;;) {
 
217
                int segs;
 
218
                struct lv *lv;
 
219
                struct lv_segment seg;
 
220
                uint64_t size, seg_start;
 
221
                char type[32], name[256], dev[256], devices[1024];
 
222
 
 
223
                if (i >= vg->lv_cnt)
 
224
                        break;
 
225
 
 
226
                if (lvm_read_line(scan)) {
 
227
                        vg->lv_cnt = i;
 
228
                        break;
 
229
                }
 
230
 
 
231
                err = -EINVAL;
 
232
                lv  = vg->lvs + i;
 
233
 
 
234
                if (sscanf(line, _NAME" %"SCNu64" %31s %u %"SCNu64" %"SCNu64" %1023s",
 
235
                           name, &size, type, &segs, &seg_start,
 
236
                           &seg.pe_size, devices) != 7)
 
237
                        goto out;
 
238
 
 
239
                if (seg_start)
 
240
                        goto next;
 
241
 
 
242
                if (!strcmp(type, "linear"))
 
243
                        seg.type = LVM_SEG_TYPE_LINEAR;
 
244
                else
 
245
                        seg.type = LVM_SEG_TYPE_UNKNOWN;
 
246
 
 
247
                if (lvm_parse_lv_devices(vg, &seg, devices))
 
248
                        goto out;
 
249
 
 
250
                i++;
 
251
                lv->size          = size;
 
252
                lv->segments      = segs;
 
253
                lv->first_segment = seg;
 
254
 
 
255
                err = lvm_copy_name(lv->name, name, sizeof(lv->name) - 1);
 
256
                if (err)
 
257
                        goto out;
 
258
                err = -EINVAL;
 
259
 
 
260
        next:
 
261
                if (lvm_next_line(scan))
 
262
                        goto out;
 
263
        }
 
264
 
 
265
        err = 0;
 
266
 
 
267
out:
 
268
        if (scan)
 
269
                pclose(scan);
 
270
        free(cmd);
 
271
        return err;
 
272
}
 
273
 
 
274
void
 
275
lvm_free_vg(struct vg *vg)
 
276
{
 
277
        free(vg->lvs);
 
278
        free(vg->pvs);
 
279
        memset(vg, 0, sizeof(*vg));
 
280
}
 
281
 
 
282
int
 
283
lvm_scan_vg(const char *vg_name, struct vg *vg)
 
284
{
 
285
        int err;
 
286
 
 
287
        memset(vg, 0, sizeof(*vg));
 
288
 
 
289
        err = lvm_open_vg(vg_name, vg);
 
290
        if (err)
 
291
                return err;
 
292
 
 
293
        err = lvm_scan_lvs(vg);
 
294
        if (err) {
 
295
                lvm_free_vg(vg);
 
296
                return err;
 
297
        }
 
298
 
 
299
        return 0;
 
300
}
 
301
 
 
302
#ifdef LVM_UTIL
 
303
static int
 
304
usage(void)
 
305
{
 
306
        printf("usage: lvm-util <vgname>\n");
 
307
        exit(EINVAL);
 
308
}
 
309
 
 
310
int
 
311
main(int argc, char **argv)
 
312
{
 
313
        int i, err;
 
314
        struct vg vg;
 
315
        struct pv *pv;
 
316
        struct lv *lv;
 
317
        struct lv_segment *seg;
 
318
 
 
319
        if (argc != 2)
 
320
                usage();
 
321
 
 
322
        err = lvm_scan_vg(argv[1], &vg);
 
323
        if (err) {
 
324
                printf("scan failed: %d\n", err);
 
325
                return (err >= 0 ? err : -err);
 
326
        }
 
327
 
 
328
        
 
329
        printf("vg %s: extent_size: %"PRIu64", pvs: %d, lvs: %d\n",
 
330
               vg.name, vg.extent_size, vg.pv_cnt, vg.lv_cnt);
 
331
 
 
332
        for (i = 0; i < vg.pv_cnt; i++) {
 
333
                pv = vg.pvs + i;
 
334
                printf("pv %s: start %"PRIu64"\n", pv->name, pv->start);
 
335
        }
 
336
 
 
337
        for (i = 0; i < vg.lv_cnt; i++) {
 
338
                lv  = vg.lvs + i;
 
339
                seg = &lv->first_segment;                
 
340
                printf("lv %s: size: %"PRIu64", segments: %u, type: %u, "
 
341
                       "dev: %s, pe_start: %"PRIu64", pe_size: %"PRIu64"\n",
 
342
                       lv->name, lv->size, lv->segments, seg->type,
 
343
                       seg->device, seg->pe_start, seg->pe_size);
 
344
        }
 
345
 
 
346
        lvm_free_vg(&vg);
 
347
        return 0;
 
348
}
 
349
#endif