4 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "format-text.h"
28 static int _text_can_handle(struct labeller
*l
__attribute((unused
)),
30 uint64_t sector
__attribute((unused
)))
32 struct label_header
*lh
= (struct label_header
*) buf
;
34 if (!strncmp((char *)lh
->type
, LVM2_LABEL
, sizeof(lh
->type
)))
40 static int _text_write(struct label
*label
, void *buf
)
42 struct label_header
*lh
= (struct label_header
*) buf
;
43 struct pv_header
*pvhdr
;
44 struct lvmcache_info
*info
;
45 struct disk_locn
*pvh_dlocn_xl
;
46 struct metadata_area
*mda
;
47 struct mda_context
*mdac
;
48 struct data_area_list
*da
;
49 char buffer
[64] __attribute((aligned(8)));
52 /* FIXME Move to where label is created */
53 strncpy(label
->type
, LVM2_LABEL
, sizeof(label
->type
));
55 strncpy((char *)lh
->type
, label
->type
, sizeof(label
->type
));
57 pvhdr
= (struct pv_header
*) ((void *) buf
+ xlate32(lh
->offset_xl
));
58 info
= (struct lvmcache_info
*) label
->info
;
59 pvhdr
->device_size_xl
= xlate64(info
->device_size
);
60 memcpy(pvhdr
->pv_uuid
, &info
->dev
->pvid
, sizeof(struct id
));
61 if (!id_write_format((const struct id
*)pvhdr
->pv_uuid
, buffer
,
67 pvh_dlocn_xl
= &pvhdr
->disk_areas_xl
[0];
69 /* List of data areas (holding PEs) */
70 dm_list_iterate_items(da
, &info
->das
) {
71 pvh_dlocn_xl
->offset
= xlate64(da
->disk_locn
.offset
);
72 pvh_dlocn_xl
->size
= xlate64(da
->disk_locn
.size
);
76 /* NULL-termination */
77 pvh_dlocn_xl
->offset
= xlate64(UINT64_C(0));
78 pvh_dlocn_xl
->size
= xlate64(UINT64_C(0));
81 /* List of metadata area header locations */
82 dm_list_iterate_items(mda
, &info
->mdas
) {
83 mdac
= (struct mda_context
*) mda
->metadata_locn
;
85 if (mdac
->area
.dev
!= info
->dev
)
88 pvh_dlocn_xl
->offset
= xlate64(mdac
->area
.start
);
89 pvh_dlocn_xl
->size
= xlate64(mdac
->area
.size
);
93 /* NULL-termination */
94 pvh_dlocn_xl
->offset
= xlate64(UINT64_C(0));
95 pvh_dlocn_xl
->size
= xlate64(UINT64_C(0));
97 /* Create debug message with da and mda locations */
98 if (xlate64(pvhdr
->disk_areas_xl
[0].offset
) ||
99 xlate64(pvhdr
->disk_areas_xl
[0].size
))
107 if (!xlate64(pvhdr
->disk_areas_xl
[mda1
].offset
) &&
108 !xlate64(pvhdr
->disk_areas_xl
[mda1
].size
))
110 else if (!xlate64(pvhdr
->disk_areas_xl
[mda2
].offset
) &&
111 !xlate64(pvhdr
->disk_areas_xl
[mda2
].size
))
114 log_debug("%s: Preparing PV label header %s size %" PRIu64
" with"
115 "%s%.*" PRIu64
"%s%.*" PRIu64
"%s"
116 "%s%.*" PRIu64
"%s%.*" PRIu64
"%s"
117 "%s%.*" PRIu64
"%s%.*" PRIu64
"%s",
118 dev_name(info
->dev
), buffer
, info
->device_size
,
119 (da1
> -1) ? " da1 (" : "",
121 (da1
> -1) ? xlate64(pvhdr
->disk_areas_xl
[da1
].offset
) >> SECTOR_SHIFT
: 0,
122 (da1
> -1) ? "s, " : "",
124 (da1
> -1) ? xlate64(pvhdr
->disk_areas_xl
[da1
].size
) >> SECTOR_SHIFT
: 0,
125 (da1
> -1) ? "s)" : "",
126 mda1
? " mda1 (" : "",
128 mda1
? xlate64(pvhdr
->disk_areas_xl
[mda1
].offset
) >> SECTOR_SHIFT
: 0,
131 mda1
? xlate64(pvhdr
->disk_areas_xl
[mda1
].size
) >> SECTOR_SHIFT
: 0,
133 mda2
? " mda2 (" : "",
135 mda2
? xlate64(pvhdr
->disk_areas_xl
[mda2
].offset
) >> SECTOR_SHIFT
: 0,
138 mda2
? xlate64(pvhdr
->disk_areas_xl
[mda2
].size
) >> SECTOR_SHIFT
: 0,
142 log_error("Internal error: %s label header currently requires "
143 "a data area.", dev_name(info
->dev
));
150 int add_da(struct dm_pool
*mem
, struct dm_list
*das
,
151 uint64_t start
, uint64_t size
)
153 struct data_area_list
*dal
;
156 if (!(dal
= dm_malloc(sizeof(*dal
)))) {
157 log_error("struct data_area_list allocation failed");
161 if (!(dal
= dm_pool_alloc(mem
, sizeof(*dal
)))) {
162 log_error("struct data_area_list allocation failed");
167 dal
->disk_locn
.offset
= start
;
168 dal
->disk_locn
.size
= size
;
170 dm_list_add(das
, &dal
->list
);
175 void del_das(struct dm_list
*das
)
177 struct dm_list
*dah
, *tmp
;
178 struct data_area_list
*da
;
180 dm_list_iterate_safe(dah
, tmp
, das
) {
181 da
= dm_list_item(dah
, struct data_area_list
);
182 dm_list_del(&da
->list
);
187 int add_mda(const struct format_type
*fmt
, struct dm_pool
*mem
, struct dm_list
*mdas
,
188 struct device
*dev
, uint64_t start
, uint64_t size
)
190 /* FIXME List size restricted by pv_header SECTOR_SIZE */
191 struct metadata_area
*mdal
;
192 struct mda_lists
*mda_lists
= (struct mda_lists
*) fmt
->private;
193 struct mda_context
*mdac
;
196 if (!(mdal
= dm_malloc(sizeof(struct metadata_area
)))) {
197 log_error("struct mda_list allocation failed");
201 if (!(mdac
= dm_malloc(sizeof(struct mda_context
)))) {
202 log_error("struct mda_context allocation failed");
207 if (!(mdal
= dm_pool_alloc(mem
, sizeof(struct metadata_area
)))) {
208 log_error("struct mda_list allocation failed");
212 if (!(mdac
= dm_pool_alloc(mem
, sizeof(struct mda_context
)))) {
213 log_error("struct mda_context allocation failed");
218 mdal
->ops
= mda_lists
->raw_ops
;
219 mdal
->metadata_locn
= mdac
;
221 mdac
->area
.dev
= dev
;
222 mdac
->area
.start
= start
;
223 mdac
->area
.size
= size
;
224 mdac
->free_sectors
= UINT64_C(0);
225 memset(&mdac
->rlocn
, 0, sizeof(mdac
->rlocn
));
227 dm_list_add(mdas
, &mdal
->list
);
231 void del_mdas(struct dm_list
*mdas
)
233 struct dm_list
*mdah
, *tmp
;
234 struct metadata_area
*mda
;
236 dm_list_iterate_safe(mdah
, tmp
, mdas
) {
237 mda
= dm_list_item(mdah
, struct metadata_area
);
238 dm_free(mda
->metadata_locn
);
239 dm_list_del(&mda
->list
);
244 static int _text_initialise_label(struct labeller
*l
__attribute((unused
)),
247 strncpy(label
->type
, LVM2_LABEL
, sizeof(label
->type
));
252 static int _text_read(struct labeller
*l
, struct device
*dev
, void *buf
,
253 struct label
**label
)
255 struct label_header
*lh
= (struct label_header
*) buf
;
256 struct pv_header
*pvhdr
;
257 struct lvmcache_info
*info
;
258 struct disk_locn
*dlocn_xl
;
260 struct metadata_area
*mda
;
262 struct mda_context
*mdac
;
267 pvhdr
= (struct pv_header
*) ((void *) buf
+ xlate32(lh
->offset_xl
));
269 if (!(info
= lvmcache_add(l
, (char *)pvhdr
->pv_uuid
, dev
,
270 FMT_TEXT_ORPHAN_VG_NAME
,
271 FMT_TEXT_ORPHAN_VG_NAME
, 0)))
273 *label
= info
->label
;
275 info
->device_size
= xlate64(pvhdr
->device_size_xl
);
279 dm_list_init(&info
->das
);
282 del_mdas(&info
->mdas
);
283 dm_list_init(&info
->mdas
);
285 /* Data areas holding the PEs */
286 dlocn_xl
= pvhdr
->disk_areas_xl
;
287 while ((offset
= xlate64(dlocn_xl
->offset
))) {
288 add_da(NULL
, &info
->das
, offset
,
289 xlate64(dlocn_xl
->size
));
293 /* Metadata area headers */
295 while ((offset
= xlate64(dlocn_xl
->offset
))) {
296 add_mda(info
->fmt
, NULL
, &info
->mdas
, dev
, offset
,
297 xlate64(dlocn_xl
->size
));
301 dm_list_iterate_items(mda
, &info
->mdas
) {
302 mdac
= (struct mda_context
*) mda
->metadata_locn
;
303 if ((vgname
= vgname_from_mda(info
->fmt
, &mdac
->area
,
304 &vgid
, &vgstatus
, &creation_host
,
305 &mdac
->free_sectors
)) &&
306 !lvmcache_update_vgname_and_id(info
, vgname
,
307 (char *) &vgid
, vgstatus
,
312 info
->status
&= ~CACHE_INVALID
;
317 static void _text_destroy_label(struct labeller
*l
__attribute((unused
)),
320 struct lvmcache_info
*info
= (struct lvmcache_info
*) label
->info
;
323 del_mdas(&info
->mdas
);
328 static void _fmt_text_destroy(struct labeller
*l
)
333 struct label_ops _text_ops
= {
334 .can_handle
= _text_can_handle
,
335 .write
= _text_write
,
337 .verify
= _text_can_handle
,
338 .initialise_label
= _text_initialise_label
,
339 .destroy_label
= _text_destroy_label
,
340 .destroy
= _fmt_text_destroy
,
343 struct labeller
*text_labeller_create(const struct format_type
*fmt
)
347 if (!(l
= dm_malloc(sizeof(*l
)))) {
348 log_error("Couldn't allocate labeller object.");
353 l
->private = (const void *) fmt
;