4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 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
20 #include "format-text.h"
22 #include "lvm-string.h"
24 #include "toolcontext.h"
29 struct archive_params
{
32 unsigned int keep_days
;
33 unsigned int keep_number
;
36 struct backup_params
{
41 int archive_init(struct cmd_context
*cmd
, const char *dir
,
42 unsigned int keep_days
, unsigned int keep_min
,
45 if (!(cmd
->archive_params
= dm_pool_zalloc(cmd
->libmem
,
46 sizeof(*cmd
->archive_params
)))) {
47 log_error("archive_params alloc failed");
51 cmd
->archive_params
->dir
= NULL
;
56 if (!(cmd
->archive_params
->dir
= dm_strdup(dir
))) {
57 log_error("Couldn't copy archive directory name.");
61 cmd
->archive_params
->keep_days
= keep_days
;
62 cmd
->archive_params
->keep_number
= keep_min
;
63 archive_enable(cmd
, enabled
);
68 void archive_exit(struct cmd_context
*cmd
)
70 if (!cmd
->archive_params
)
72 if (cmd
->archive_params
->dir
)
73 dm_free(cmd
->archive_params
->dir
);
74 memset(cmd
->archive_params
, 0, sizeof(*cmd
->archive_params
));
77 void archive_enable(struct cmd_context
*cmd
, int flag
)
79 cmd
->archive_params
->enabled
= flag
;
82 static char *_build_desc(struct dm_pool
*mem
, const char *line
, int before
)
84 size_t len
= strlen(line
) + 32;
87 if (!(buffer
= dm_pool_zalloc(mem
, strlen(line
) + 32)))
90 if (snprintf(buffer
, len
,
91 "Created %s executing '%s'",
92 before
? "*before*" : "*after*", line
) < 0)
98 static int __archive(struct volume_group
*vg
)
102 if (!(desc
= _build_desc(vg
->cmd
->mem
, vg
->cmd
->cmd_line
, 1)))
105 return archive_vg(vg
, vg
->cmd
->archive_params
->dir
, desc
,
106 vg
->cmd
->archive_params
->keep_days
,
107 vg
->cmd
->archive_params
->keep_number
);
110 int archive(struct volume_group
*vg
)
112 if (!vg
->cmd
->archive_params
->enabled
|| !vg
->cmd
->archive_params
->dir
)
116 log_verbose("Test mode: Skipping archiving of volume group.");
120 if (!dm_create_dir(vg
->cmd
->archive_params
->dir
))
123 /* Trap a read-only file system */
124 if ((access(vg
->cmd
->archive_params
->dir
, R_OK
| W_OK
| X_OK
) == -1) &&
128 log_verbose("Archiving volume group \"%s\" metadata (seqno %u).", vg
->name
,
130 if (!__archive(vg
)) {
131 log_error("Volume group \"%s\" metadata archive failed.",
139 int archive_display(struct cmd_context
*cmd
, const char *vg_name
)
143 r1
= archive_list(cmd
, cmd
->archive_params
->dir
, vg_name
);
144 r2
= backup_list(cmd
, cmd
->backup_params
->dir
, vg_name
);
149 int archive_display_file(struct cmd_context
*cmd
, const char *file
)
153 r
= archive_list_file(cmd
, file
);
158 int backup_init(struct cmd_context
*cmd
, const char *dir
,
161 if (!(cmd
->backup_params
= dm_pool_zalloc(cmd
->libmem
,
162 sizeof(*cmd
->backup_params
)))) {
163 log_error("backup_params alloc failed");
167 cmd
->backup_params
->dir
= NULL
;
171 if (!(cmd
->backup_params
->dir
= dm_strdup(dir
))) {
172 log_error("Couldn't copy backup directory name.");
175 backup_enable(cmd
, enabled
);
180 void backup_exit(struct cmd_context
*cmd
)
182 if (!cmd
->backup_params
)
184 if (cmd
->backup_params
->dir
)
185 dm_free(cmd
->backup_params
->dir
);
186 memset(cmd
->backup_params
, 0, sizeof(*cmd
->backup_params
));
189 void backup_enable(struct cmd_context
*cmd
, int flag
)
191 cmd
->backup_params
->enabled
= flag
;
194 static int __backup(struct volume_group
*vg
)
199 if (!(desc
= _build_desc(vg
->cmd
->mem
, vg
->cmd
->cmd_line
, 0)))
202 if (dm_snprintf(name
, sizeof(name
), "%s/%s",
203 vg
->cmd
->backup_params
->dir
, vg
->name
) < 0) {
204 log_error("Failed to generate volume group metadata backup "
209 return backup_to_file(name
, desc
, vg
);
212 int backup_locally(struct volume_group
*vg
)
214 if (!vg
->cmd
->backup_params
->enabled
|| !vg
->cmd
->backup_params
->dir
) {
215 log_warn("WARNING: This metadata update is NOT backed up");
220 log_verbose("Test mode: Skipping volume group backup.");
224 if (!dm_create_dir(vg
->cmd
->backup_params
->dir
))
227 /* Trap a read-only file system */
228 if ((access(vg
->cmd
->backup_params
->dir
, R_OK
| W_OK
| X_OK
) == -1) &&
233 log_error("Backup of volume group %s metadata failed.",
241 int backup(struct volume_group
*vg
)
243 if (vg_is_clustered(vg
))
244 remote_backup_metadata(vg
);
246 return backup_locally(vg
);
249 int backup_remove(struct cmd_context
*cmd
, const char *vg_name
)
253 if (dm_snprintf(path
, sizeof(path
), "%s/%s",
254 cmd
->backup_params
->dir
, vg_name
) < 0) {
255 log_error("Failed to generate backup filename (for removal).");
260 * Let this fail silently.
266 struct volume_group
*backup_read_vg(struct cmd_context
*cmd
,
267 const char *vg_name
, const char *file
)
269 struct volume_group
*vg
= NULL
;
270 struct format_instance
*tf
;
271 struct metadata_area
*mda
;
274 if (!(context
= create_text_context(cmd
, file
,
276 !(tf
= cmd
->fmt_backup
->ops
->create_instance(cmd
->fmt_backup
, NULL
,
278 log_error("Couldn't create text format object.");
282 dm_list_iterate_items(mda
, &tf
->metadata_areas
) {
283 if (!(vg
= mda
->ops
->vg_read(tf
, vg_name
, mda
)))
288 tf
->fmt
->ops
->destroy_instance(tf
);
292 /* ORPHAN and VG locks held before calling this */
293 int backup_restore_vg(struct cmd_context
*cmd
, struct volume_group
*vg
)
296 struct physical_volume
*pv
;
297 struct lvmcache_info
*info
;
300 * FIXME: Check that the PVs referenced in the backup are
301 * not members of other existing VGs.
304 /* Attempt to write out using currently active format */
305 if (!(vg
->fid
= cmd
->fmt
->ops
->create_instance(cmd
->fmt
, vg
->name
,
307 log_error("Failed to allocate format instance");
311 /* Add any metadata areas on the PVs */
312 dm_list_iterate_items(pvl
, &vg
->pvs
) {
314 if (!(info
= info_from_pvid(pv
->dev
->pvid
, 0))) {
315 log_error("PV %s missing from cache",
319 if (cmd
->fmt
!= info
->fmt
) {
320 log_error("PV %s is a different format (seqno %s)",
321 pv_dev_name(pv
), info
->fmt
->name
);
324 if (!vg
->fid
->fmt
->ops
->
325 pv_setup(vg
->fid
->fmt
, UINT64_C(0), 0, 0, 0, 0, 0UL,
326 UINT64_C(0), &vg
->fid
->metadata_areas
, pv
, vg
)) {
327 log_error("Format-specific setup for %s failed",
333 if (!vg_write(vg
) || !vg_commit(vg
))
339 /* ORPHAN and VG locks held before calling this */
340 int backup_restore_from_file(struct cmd_context
*cmd
, const char *vg_name
,
343 struct volume_group
*vg
;
344 int missing_pvs
, r
= 0;
347 * Read in the volume group from the text file.
349 if (!(vg
= backup_read_vg(cmd
, vg_name
, file
)))
352 missing_pvs
= vg_missing_pv_count(vg
);
353 if (missing_pvs
== 0)
354 r
= backup_restore_vg(cmd
, vg
);
356 log_error("Cannot restore Volume Group %s with %i PVs "
357 "marked as missing.", vg
->name
, missing_pvs
);
363 int backup_restore(struct cmd_context
*cmd
, const char *vg_name
)
367 if (dm_snprintf(path
, sizeof(path
), "%s/%s",
368 cmd
->backup_params
->dir
, vg_name
) < 0) {
369 log_error("Failed to generate backup filename (for restore).");
373 return backup_restore_from_file(cmd
, vg_name
, path
);
376 int backup_to_file(const char *file
, const char *desc
, struct volume_group
*vg
)
379 struct format_instance
*tf
;
380 struct metadata_area
*mda
;
382 struct cmd_context
*cmd
;
386 log_verbose("Creating volume group backup \"%s\" (seqno %u).", file
, vg
->seqno
);
388 if (!(context
= create_text_context(cmd
, file
, desc
)) ||
389 !(tf
= cmd
->fmt_backup
->ops
->create_instance(cmd
->fmt_backup
, NULL
,
391 log_error("Couldn't create backup object.");
395 /* Write and commit the metadata area */
396 dm_list_iterate_items(mda
, &tf
->metadata_areas
) {
397 if (!(r
= mda
->ops
->vg_write(tf
, vg
, mda
))) {
401 if (mda
->ops
->vg_commit
&&
402 !(r
= mda
->ops
->vg_commit(tf
, vg
, mda
))) {
407 tf
->fmt
->ops
->destroy_instance(tf
);
412 * Update backup (and archive) if they're out-of-date or don't exist.
414 void check_current_backup(struct volume_group
*vg
)
417 struct volume_group
*vg_backup
;
420 if (vg_is_exported(vg
))
423 if (dm_snprintf(path
, sizeof(path
), "%s/%s",
424 vg
->cmd
->backup_params
->dir
, vg
->name
) < 0) {
425 log_debug("Failed to generate backup filename.");
429 old_suppress
= log_suppress(1);
430 /* Up-to-date backup exists? */
431 if ((vg_backup
= backup_read_vg(vg
->cmd
, vg
->name
, path
)) &&
432 (vg
->seqno
== vg_backup
->seqno
) &&
433 (id_equal(&vg
->id
, &vg_backup
->id
))) {
434 log_suppress(old_suppress
);
435 vg_release(vg_backup
);
438 log_suppress(old_suppress
);
442 vg_release(vg_backup
);