~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to libblkid/src/superblocks/lvm.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1999 by Andries Brouwer
 
3
 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
 
4
 * Copyright (C) 2001 by Andreas Dilger
 
5
 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
 
6
 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
 
7
 *
 
8
 * This file may be redistributed under the terms of the
 
9
 * GNU Lesser General Public License.
 
10
 */
 
11
#include <stdio.h>
 
12
#include <stdlib.h>
 
13
#include <unistd.h>
 
14
#include <string.h>
 
15
#include <stdint.h>
 
16
 
 
17
#include "superblocks.h"
 
18
 
 
19
#define LVM1_ID_LEN 128
 
20
#define LVM2_ID_LEN 32
 
21
 
 
22
struct lvm2_pv_label_header {
 
23
        /* label_header */
 
24
        uint8_t         id[8];          /* LABELONE */
 
25
        uint64_t        sector_xl;      /* Sector number of this label */
 
26
        uint32_t        crc_xl;         /* From next field to end of sector */
 
27
        uint32_t        offset_xl;      /* Offset from start of struct to contents */
 
28
        uint8_t         type[8];        /* LVM2 001 */
 
29
        /* pv_header */
 
30
        uint8_t         pv_uuid[LVM2_ID_LEN];
 
31
} __attribute__ ((packed));
 
32
 
 
33
struct lvm1_pv_label_header {
 
34
        uint8_t id[2];                  /* HM */
 
35
        uint16_t version;               /* version 1 or 2 */
 
36
        uint32_t _notused[10];          /* lvm1 internals */
 
37
        uint8_t pv_uuid[LVM1_ID_LEN];
 
38
} __attribute__ ((packed));
 
39
 
 
40
#define LVM2_LABEL_SIZE 512
 
41
static unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
 
42
{
 
43
        static const unsigned int crctab[] = {
 
44
                0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
 
45
                0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
 
46
                0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
 
47
                0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
 
48
        };
 
49
        unsigned int i, crc = 0xf597a6cf;
 
50
        const uint8_t *data = (const uint8_t *) buf;
 
51
 
 
52
        for (i = 0; i < size; i++) {
 
53
                crc ^= *data++;
 
54
                crc = (crc >> 4) ^ crctab[crc & 0xf];
 
55
                crc = (crc >> 4) ^ crctab[crc & 0xf];
 
56
        }
 
57
        return crc;
 
58
}
 
59
 
 
60
/* Length of real UUID is always LVM2_ID_LEN */
 
61
static void format_lvm_uuid(char *dst_uuid, char *src_uuid)
 
62
{
 
63
        unsigned int i, b;
 
64
 
 
65
        for (i = 0, b = 1; i < LVM2_ID_LEN; i++, b <<= 1) {
 
66
                if (b & 0x4444440)
 
67
                        *dst_uuid++ = '-';
 
68
                *dst_uuid++ = *src_uuid++;
 
69
        }
 
70
        *dst_uuid = '\0';
 
71
}
 
72
 
 
73
static int probe_lvm2(blkid_probe pr, const struct blkid_idmag *mag)
 
74
{
 
75
        int sector = mag->kboff << 1;
 
76
        struct lvm2_pv_label_header *label;
 
77
        char uuid[LVM2_ID_LEN + 7];
 
78
        unsigned char *buf;
 
79
 
 
80
        buf = blkid_probe_get_buffer(pr,
 
81
                        mag->kboff << 10,
 
82
                        512 + sizeof(struct lvm2_pv_label_header));
 
83
        if (!buf)
 
84
                return -1;
 
85
 
 
86
        /* buf is at 0k or 1k offset; find label inside */
 
87
        if (memcmp(buf, "LABELONE", 8) == 0) {
 
88
                label = (struct lvm2_pv_label_header *) buf;
 
89
        } else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
 
90
                label = (struct lvm2_pv_label_header *)(buf + 512);
 
91
                sector++;
 
92
        } else {
 
93
                return 1;
 
94
        }
 
95
 
 
96
        if (le64_to_cpu(label->sector_xl) != (unsigned) sector)
 
97
                return 1;
 
98
 
 
99
        if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE -
 
100
                        ((char *) &label->offset_xl - (char *) label)) !=
 
101
                        le32_to_cpu(label->crc_xl)) {
 
102
                DBG(DEBUG_PROBE,
 
103
                    printf("LVM2: label checksum incorrect at sector %d\n",
 
104
                           sector));
 
105
                return 1;
 
106
        }
 
107
 
 
108
        format_lvm_uuid(uuid, (char *) label->pv_uuid);
 
109
        blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
 
110
                        "%s", uuid);
 
111
 
 
112
        /* the mag->magic is the same string as label->type,
 
113
         * but zero terminated */
 
114
        blkid_probe_set_version(pr, mag->magic);
 
115
 
 
116
        /* LVM (pvcreate) wipes begin of the device -- let's remember this
 
117
         * to resolve conflicts bettween LVM and partition tables, ...
 
118
         */
 
119
        blkid_probe_set_wiper(pr, 0, 8 * 1024);
 
120
 
 
121
        return 0;
 
122
}
 
123
 
 
124
static int probe_lvm1(blkid_probe pr, const struct blkid_idmag *mag)
 
125
{
 
126
        struct lvm1_pv_label_header *label;
 
127
        char uuid[LVM2_ID_LEN + 7];
 
128
        unsigned int version;
 
129
 
 
130
        label = blkid_probe_get_sb(pr, mag, struct lvm1_pv_label_header);
 
131
        if (!label)
 
132
                return -1;
 
133
 
 
134
        version = le16_to_cpu(label->version);
 
135
        if (version != 1 && version != 2)
 
136
                return 1;
 
137
 
 
138
        format_lvm_uuid(uuid, (char *) label->pv_uuid);
 
139
        blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
 
140
                        "%s", uuid);
 
141
 
 
142
        return 0;
 
143
}
 
144
 
 
145
/* NOTE: the original libblkid uses "lvm2pv" as a name */
 
146
const struct blkid_idinfo lvm2_idinfo =
 
147
{
 
148
        .name           = "LVM2_member",
 
149
        .usage          = BLKID_USAGE_RAID,
 
150
        .probefunc      = probe_lvm2,
 
151
        .magics         =
 
152
        {
 
153
                { .magic = "LVM2 001", .len = 8, .sboff = 0x218 },
 
154
                { .magic = "LVM2 001", .len = 8, .sboff = 0x018 },
 
155
                { .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x018 },
 
156
                { .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x218 },
 
157
                { NULL }
 
158
        }
 
159
};
 
160
 
 
161
const struct blkid_idinfo lvm1_idinfo =
 
162
{
 
163
        .name           = "LVM1_member",
 
164
        .usage          = BLKID_USAGE_RAID,
 
165
        .probefunc      = probe_lvm1,
 
166
        .magics         =
 
167
        {
 
168
                { .magic = "HM", .len = 2 },
 
169
                { NULL }
 
170
        }
 
171
};
 
172
 
 
173
const struct blkid_idinfo snapcow_idinfo =
 
174
{
 
175
        .name           = "DM_snapshot_cow",
 
176
        .usage          = BLKID_USAGE_OTHER,
 
177
        .magics         =
 
178
        {
 
179
                { .magic = "SnAp", .len = 4 },
 
180
                { NULL }
 
181
        }
 
182
};