1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-31 14:50:37 +03:00

o sync backup changes

This commit is contained in:
Joe Thornber 2001-12-20 11:52:54 +00:00
parent b561f1fa8b
commit a9649e92c9
18 changed files with 355 additions and 160 deletions

View File

@ -13,6 +13,7 @@
../lib/filters/filter-regex.h
../lib/filters/filter.h
../lib/format1/format1.h
../lib/format_text/format-text.h
../lib/label/label.h
../lib/log/log.h
../lib/metadata/metadata.h

View File

@ -29,6 +29,10 @@ SOURCES=\
format1/import-extents.c \
format1/layout.c \
format1/vg_number.c \
format_text/backup.c \
format_text/export.c \
format_text/flags.c \
format_text/import.c \
label/label.c \
log/log.c \
metadata/lv_manip.c \

View File

@ -10,6 +10,12 @@
#include "pool.h"
#include "config.h"
#include "hash.h"
#include "import-export.h"
#include "lvm-string.h"
#include <dirent.h>
#include <unistd.h>
/*
* The format instance is given a directory path
@ -29,11 +35,24 @@ struct backup_c {
uint32_t min_retains;
char *dir;
/*
* An ordered list of previous backups.
* Each list entered against the vg name.
* Most recent first.
*/
struct hash_table *vg_backups;
/*
* Scratch pool. Contents of vg_backups
* come from here.
*/
struct pool *mem;
};
/*
* A list of these is built up for each volume
* group. Ordered with the most recent at the
* group. Ordered with the least recent at the
* head.
*/
struct backup_file {
@ -52,71 +71,70 @@ static void _unsupported(const char *cmd)
log_err("The backup format doesn't support '%s'", cmd);
}
struct list *get_vgs(struct format_instance *fi)
static struct list *_get_vgs(struct format_instance *fi)
{
_unsupported("get_vgs");
return NULL;
}
struct list *get_pvs(struct format_instance *fi)
static struct list *_get_pvs(struct format_instance *fi)
{
_unsupported("get_pvs");
return NULL;
}
struct physical_volume *pv_read(struct format_instance *fi,
const char *pv_name)
static struct physical_volume *_pv_read(struct format_instance *fi,
const char *pv_name)
{
_unsupported("pv_read");
return NULL;
}
int pv_setup(struct format_instance *fi, struct physical_volume *pv,
static int _pv_setup(struct format_instance *fi, struct physical_volume *pv,
struct volume_group *vg)
{
_unsupported("pv_setup");
return 1;
return 0;
}
int pv_write(struct format_instance *fi, struct physical_volume *pv)
static int _pv_write(struct format_instance *fi, struct physical_volume *pv)
{
_unsupported("pv_write");
return 1;
return 0;
}
int vg_setup(struct format_instance *fi, struct volume_group *vg)
static int _vg_setup(struct format_instance *fi, struct volume_group *vg)
{
_unsupported("vg_setup");
return 1;
return 0;
}
struct volume_group *vg_read(struct format_instance *fi, const char *vg_name)
static struct volume_group *_vg_read(struct format_instance *fi,
const char *vg_name)
{
_unsupported("vg_read");
return 1;
return NULL;
}
int vg_write(struct format_instance *fi, struct volume_group *vg)
static void _destroy(struct format_instance *fi)
{
struct backup_c *bc = (struct backup_c *) fi->private;
if (bc->vg_backups)
hash_destroy(bc->vg_backups);
pool_destroy(bc->mem);
}
void destroy(struct format_instance *fi)
{
/*
* We don't need to do anything here since
* everything is allocated from the pool.
*/
}
/*
* vg_write implementation starts here.
*/
static int _split_vg(const char *filename, char *vg, size_t vg_size,
uint32_t *index)
{
char buffer[64];
int n;
snprintf(buffer, sizeof(buffer), "\%%ds_\%u.vg%n", vg, index, &n);
snprintf(buffer, sizeof(buffer), "\%%ds_\%u.vg%n", vg_size, &n);
return (sscanf(filename, buffer, vg, index) == 2) &&
(filename + n == '\0');
}
@ -141,25 +159,24 @@ static void _insert_file(struct list *head, struct backup_file *b)
list_add_h(&bf->list, &b->list);
}
static int _scan_vg(struct pool *mem, struct hash_table *vgs, const char *file)
static int _scan_vg(struct backup_c *bc, const char *file,
const char *vg_name, int index)
{
struct backup_file *b;
struct list *files;
char vg_name[256];
int index;
/*
* Do we need to create a new list of
* backup files for this vg ?
*/
if (!(files = hash_lookup(vgs, vg_name))) {
if (!(files = pool_alloc(mem, sizeof(*files)))) {
if (!(files = hash_lookup(bc->vg_backups, vg_name))) {
if (!(files = pool_alloc(bc->mem, sizeof(*files)))) {
stack;
return 0;
}
list_init(files);
if (!hash_insert(vgs, vg_name, files)) {
if (!hash_insert(bc->vg_backups, vg_name, files)) {
log_err("Couldn't insert backup file "
"into hash table.");
return 0;
@ -169,7 +186,7 @@ static int _scan_vg(struct pool *mem, struct hash_table *vgs, const char *file)
/*
* Create a new backup file.
*/
if (!(b = pool_alloc(mem, sizeof(*b)))) {
if (!(b = pool_alloc(bc->mem, sizeof(*b)))) {
log_err("Couldn't create new backup file.");
return 0;
}
@ -183,26 +200,43 @@ static int _scan_vg(struct pool *mem, struct hash_table *vgs, const char *file)
return 1;
}
static int _scan_dir(struct pool *mem, struct hash_table *vgs, const char *dir)
static char *_join(struct pool *mem, const char *dir, const char *name)
{
int r = 0;
if ((count = scandir(dir, &dirent, NULL, alphasort)) < 0) {
log_err("Couldn't scan backup directory.");
if (!pool_begin_object(mem, 32) ||
!pool_grow_object(mem, dir, strlen(dir)) ||
!pool_grow_object(mem, "/", 1) ||
!pool_grow_object(mem, name, strlen(name)) ||
!pool_grow_object(mem, "\0", 1)) {
stack;
return NULL;
}
return pool_end_object(mem);
}
static int _scan_dir(struct backup_c *bc)
{
int r = 0, i, count, index;
char vg_name[64], *path;
struct dirent **dirent;
if ((count = scandir(bc->dir, &dirent, NULL, alphasort)) < 0) {
log_err("Couldn't scan backup directory.");
return 0;
}
for (i = 0; i < count; i++) {
if ((dirent[i]->d_name[0] == '.') ||
!_split_vg(dirent[i]->d_name))
!_split_vg(dirent[i]->d_name, vg_name,
sizeof(vg_name), &index))
continue;
if (!(path = _join(mem, dir, dirent[i]->d_name))) {
if (!(path = _join(bc->mem, bc->dir, dirent[i]->d_name))) {
stack;
goto out;
}
_scan_vg(path);
_scan_vg(bc, path, vg_name, index);
}
r = 1;
@ -214,32 +248,107 @@ static int _scan_dir(struct pool *mem, struct hash_table *vgs, const char *dir)
return r;
}
struct hash_table *_scan_backups(const char *dir)
static int _scan_backups(struct backup_c *bc)
{
int count;
struct dirent **dirent;
struct hash_table *h = NULL;
pool_empty(bc->mem);
if (!(h = hash_create(128))) {
if (bc->vg_backups)
hash_destroy(bc->vg_backups);
if (!(bc->vg_backups = hash_create(128))) {
log_err("Couldn't create hash table for scanning backups.");
return NULL;
return 0;
}
if (!_scan_vgs(mem, h, dir)) {
if (!_scan_dir(bc)) {
stack;
hash_destroy(h);
return NULL;
return 0;
}
return h;
return 1;
}
static int _vg_write(struct format_instance *fi, struct volume_group *vg)
{
int r = 0, index = 0, i, fd;
struct backup_c *bc = (struct backup_c *) fi->private;
struct backup_file *last;
char *tmp_name;
FILE *fp = NULL;
char backup_name[PATH_MAX];
/*
* Build a format string for mkstemp.
*/
if (lvm_snprintf(backup_name, sizeof(backup_name), "%s/lvm_XXXXXX",
bc->dir) < 0) {
log_err("Couldn't generate template for backup name.");
return 0;
}
/*
* Write the backup, to a temporary file.
*/
if ((fd = mkstemp(backup_name))) {
log_err("Couldn't create temporary file for backup.");
return 0;
}
if (!(fp = fdopen(fd, "w"))) {
log_err("Couldn't create FILE object for backup.");
close(fd);
return 0;
}
if (!text_vg_export(fp, vg)) {
stack;
goto out;
}
/*
* Now we want to rename this file to <vg>_index.vg.
*/
if (!_scan_backups(bc)) {
log_err("Couldn't scan the backup directory (%s).", bc->dir);
goto out;
}
if ((last = (struct backup_file *) hash_lookup(bc->vg_backups,
vg->name))) {
/* move to the last in the list */
last = list_item(last->list.p, struct backup_file);
index = last->index + 1;
}
for (i = 0; i < 10; i++) {
if (lvm_snprintf(backup_name, sizeof(backup_name),
"%s/%s_%d.vg",
bc->dir, vg->name, index) < 0) {
log_err("backup file name too long.");
goto out;
}
if (rename(tmp_name, backup_name) < 0) {
log_err("couldn't rename backup file to %s.",
backup_name);
} else {
r = 1;
break;
}
index++;
}
out:
if (fp)
fclose(fp);
free(tmp_name);
return r;
}
void backup_expire(struct format_instance *fi)
{
struct backup_c *bc = (struct backup_c *) fi->private;
struct hash_table *vgs;
/* FIXME: finish */
}
static struct format_handler _backup_handler = {
@ -254,7 +363,7 @@ static struct format_handler _backup_handler = {
destroy: _destroy
};
struct format_instance *backup_format_create(struct cmd_context,
struct format_instance *backup_format_create(struct cmd_context *cmd,
const char *dir,
uint32_t retain_days,
uint32_t min_retains)
@ -268,6 +377,11 @@ struct format_instance *backup_format_create(struct cmd_context,
return NULL;
}
if (!(bc->mem = pool_create(1024))) {
stack;
goto bad;
}
if (!(bc->dir = pool_strdup(mem, dir))) {
stack;
goto bad;
@ -282,12 +396,15 @@ struct format_instance *backup_format_create(struct cmd_context,
}
fi->cmd = cmd;
fi->ops = _backup_handler;
fi->ops = &_backup_handler;
fi->private = bc;
return fi;
bad:
if (bc->mem)
pool_destroy(bc->mem);
pool_free(mem, bc);
return NULL;
}

View File

@ -9,8 +9,11 @@
#include "log.h"
#include "hash.h"
#include "pool.h"
#include "dbg_malloc.h"
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
/*
@ -88,13 +91,13 @@ static void _out_with_comment(struct formatter *f, const char *comment,
*/
static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
{
static char *_units = [
static char *_units[] = {
"Kilobytes",
"Megabytes",
"Gigabytes",
"Terrabytes",
NULL
];
};
int i;
double d = (double) sectors;
@ -155,11 +158,15 @@ static void _out(struct formatter *f, const char *fmt, ...)
static int _print_header(struct formatter *f, struct volume_group *vg)
{
time_t t;
t = time(NULL);
_out(f,
"# This file was originally generated by the LVM2 library\n"
"# It is inadvisable for people to edit this by hand unless\n"
"# they *really* know what they're doing.\n"
"# Generated: %s\n", ctime(time(NULL)));
"# Generated: %s\n", ctime(&t));
return 1;
}
@ -167,7 +174,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
{
char buffer[256];
if (!id_write_format(&vg.uuid, buffer, sizeof(buffer))) {
if (!id_write_format(&vg->id, buffer, sizeof(buffer))) {
stack;
return 0;
}
@ -175,7 +182,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
_out(f, "id = \"%s\"", buffer);
_nl(f);
if (!_print_flags(vg->status, _vg_flags, buffer, size)) {
if (!print_flags(vg->status, VG_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
}
@ -200,12 +207,12 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
static inline const char *
_get_pv_name(struct formatter *f, struct physical_volume *pv)
{
return (const char *) hash_lookup(f->pv_names, dev_name(pv));
return (const char *) hash_lookup(f->pv_names, dev_name(pv->dev));
}
static int _print_pvs(struct formatter *f, struct volume_group *vg)
{
struct list pvh;
struct list *pvh;
struct physical_volume *pv;
char buffer[256];
const char *name;
@ -226,7 +233,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
pv = &list_item(pvh, struct pv_list)->pv;
if (!id_write_format(&pv->uuid, buffer, sizeof(buffer))) {
if (!id_write_format(&pv->id, buffer, sizeof(buffer))) {
stack;
return 0;
}
@ -235,7 +242,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
_out_hint(f, "device = %s", dev_name(pv->dev));
_nl(f);
if (!print_flags(pv->status, _pv_flags,
if (!print_flags(pv->status, PV_FLAGS,
buffer, sizeof(buffer))) {
stack;
return 0;
@ -270,14 +277,15 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
_out(f, "stripes = %u", seg->stripes);
if (seg->stripes > 1)
_out_size(f, "stripe_size = %u", seg->stripe_size);
_out_size(f, seg->stripe_size,
"stripe_size = %u", seg->stripe_size);
_nl(f);
_out(f, "areas = [");
_inc_indent(f);
for (s = 0; s < seg->stripes; s++) {
if (!(name = _get_pv_name(f, seg->areas[s].pv))) {
if (!(name = _get_pv_name(f, seg->area[s].pv))) {
stack;
return 0;
}
@ -295,6 +303,17 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
return 1;
}
static int _count_segments(struct logical_volume *lv)
{
int r = 0;
struct list *segh;
list_iterate (segh, &lv->segments)
r++;
return r;
}
static int _print_lvs(struct formatter *f, struct volume_group *vg)
{
struct list *lvh, *segh;
@ -313,8 +332,8 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
_out(f, "%s {", lv->name);
_inc_indent(f);
if (!_print_flags(lv->status, _lv_flags,
buffer, sizeof(buffer))) {
if (!print_flags(lv->status, LV_FLAGS,
buffer, sizeof(buffer))) {
stack;
return 0;
}
@ -328,7 +347,8 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
list_iterate (segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
if (!_print_segment(f, seg_count++, seg)) {
if (!_print_segment(f, vg, seg_count++, seg,
(segh->n == &lv->segments))) {
stack;
return 0;
}
@ -404,7 +424,7 @@ int text_vg_export(FILE *fp, struct volume_group *vg)
int r = 0;
struct formatter *f;
if (!f = dbg_malloc(sizeof(*f))) {
if (!(f = dbg_malloc(sizeof(*f)))) {
stack;
return 0;
}
@ -424,7 +444,7 @@ int text_vg_export(FILE *fp, struct volume_group *vg)
fail;
_out(f, "%s {", vg->name);
_inc_indent(f):
_inc_indent(f);
if (!_print_vg(f, vg))
fail;
@ -449,6 +469,6 @@ int text_vg_export(FILE *fp, struct volume_group *vg)
if (f->pv_names)
hash_destroy(f->pv_names);
dbg_free(f):
dbg_free(f);
return r;
}

View File

@ -4,8 +4,10 @@
* This file is released under the LGPL.
*/
#include "log.h"
#include "metadata.h"
#include "import-export.h"
#include "lvm-string.h"
/*
* Bitsets held in the 'status' flags get
@ -33,8 +35,8 @@ static struct flag _pv_flags[] = {
static struct flag _lv_flags[] = {
{ACTIVE, "ACTIVE"},
{READ, "READ"},
{WRITE, "WRITE"},
{LVM_READ, "READ"},
{LVM_WRITE, "WRITE"},
{ALLOC_SIMPLE, "ALLOC_SIMPLE"},
{ALLOC_STRICT, "ALLOC_STRICT"},
{ALLOC_CONTIGUOUS, "ALLOC_CONTIGUOUS"},
@ -43,7 +45,7 @@ static struct flag _lv_flags[] = {
{0, NULL}
};
static struct flags *_get_flags(int type)
static struct flag *_get_flags(int type)
{
switch (type) {
case VG_FLAGS:
@ -75,18 +77,22 @@ int print_flags(uint32_t status, int type, char *buffer, size_t size)
return 0;
}
if ((n = snprintf(buffer, size, "[")))
if ((n = lvm_snprintf(buffer, size, "[")) < 0)
return 0;
size -= n;
for (f = 0; flags[f].mask; f++) {
if (status & flags[f].mask) {
if (!first)
fprintf(fp, ", ");
else
if (!first) {
if ((n = lvm_snprintf(buffer, size, ", ")) < 0)
return 0;
size -= n;
} else
first = 0;
n = snprintf(buffer, size, "\"%s\"", flags[f].name);
n = lvm_snprintf(buffer, size, "\"%s\"",
flags[f].description);
if (n < 0)
return 0;
size -= n;
@ -95,7 +101,7 @@ int print_flags(uint32_t status, int type, char *buffer, size_t size)
}
}
if (snprintf(buffer, size, "]"))
if ((n = lvm_snprintf(buffer, size, "]")) < 0)
return 0;
if (status)
@ -124,8 +130,8 @@ int read_flags(uint32_t *status, int type, struct config_value *cv)
}
for (f = 0; flags[f].description; f++)
if (!strcmp(flags[f].description, cv.v.str)) {
status &= flags[f].mask;
if (!strcmp(flags[f].description, cv->v.str)) {
(*status) &= flags[f].mask;
break;
}

View File

@ -7,7 +7,10 @@
#ifndef _LVM_FORMAT_TEXT_H
#define _LVM_FORMAT_TEXT_H
struct format_instance *backup_format_create(struct cmd_context,
#include "lvm-types.h"
#include "metadata.h"
struct format_instance *backup_format_create(struct cmd_context *cmd,
const char *dir,
uint32_t retain_days,
uint32_t min_backups);

View File

@ -8,6 +8,10 @@
#define _LVM_TEXT_IMPORT_EXPORT_H
#include "config.h"
#include "lvm-types.h"
#include "metadata.h"
#include <stdio.h>
enum {
VG_FLAGS,

View File

@ -7,6 +7,7 @@
#include "import-export.h"
#include "config.h"
#if 0
struct importer {
struct config_file *cf;
struct volume_group *vg;
@ -53,3 +54,4 @@ struct volume_group *text_vg_import(struct cmd_context *cmd,
destroy_config_file(cf);
return vg;
}
#endif

View File

@ -265,7 +265,7 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents);
int lv_extend(struct logical_volume *lv,
uint32_t stripes,
uint32_t stripe_size,
uint32_t extents,
uint32_t extents,
struct list *allocatable_pvs);
/* lv must be part of vg->lvs */

View File

@ -22,7 +22,7 @@ static inline int lvm_snprintf(char *str, size_t size, const char *format, ...)
n = vsnprintf(str, size, format, ap);
va_end(ap);
if (n < 0 || n == size)
if (n < 0 || (n == size))
return -1;
return n;

View File

@ -130,7 +130,7 @@ void pool_free(struct pool *p, void *ptr)
p->chunk = c;
}
void *pool_begin_object(struct pool *p, size_t init_size)
int pool_begin_object(struct pool *p, size_t hint)
{
struct chunk *c = p->chunk;
const size_t align = DEFAULT_ALIGNMENT;
@ -139,23 +139,23 @@ void *pool_begin_object(struct pool *p, size_t init_size)
p->object_alignment = align;
_align_chunk(c, align);
if (c->end - c->begin < init_size) {
if (c->end - c->begin < hint) {
/* allocate a new chunk */
c = _new_chunk(p,
init_size > (p->chunk_size - sizeof(struct chunk)) ?
init_size + sizeof(struct chunk) + align :
hint > (p->chunk_size - sizeof(struct chunk)) ?
hint + sizeof(struct chunk) + align :
p->chunk_size);
if (!c)
return NULL;
return 0;
_align_chunk(c, align);
}
return c->begin;
return 1;
}
void *pool_grow_object(struct pool *p, void *buffer, size_t n)
int pool_grow_object(struct pool *p, const void *extra, size_t n)
{
struct chunk *c = p->chunk, *nc;
@ -167,16 +167,16 @@ void *pool_grow_object(struct pool *p, void *buffer, size_t n)
nc = _new_chunk(p, p->chunk_size);
if (!nc)
return NULL;
return 0;
_align_chunk(p->chunk, p->object_alignment);
memcpy(p->chunk->begin, c->begin, p->object_len);
c = p->chunk;
}
memcpy(c->begin + p->object_len, buffer, n);
memcpy(c->begin + p->object_len, extra, n);
p->object_len += n;
return c->begin;
return 1;
}
void *pool_end_object(struct pool *p)

View File

@ -1,7 +1,7 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
* This file is released under the LGPL.
*/
#ifndef _LVM_POOL_H
@ -66,8 +66,8 @@ void pool_free(struct pool *p, void *ptr);
* a call to pool_end_object.
*
*/
void *pool_begin_object(struct pool *p, size_t hint);
void *pool_grow_object(struct pool *p, void *extra, size_t delta);
int pool_begin_object(struct pool *p, size_t hint);
int pool_grow_object(struct pool *p, const void *extra, size_t delta);
void *pool_end_object(struct pool *p);
void pool_abandon_object(struct pool *p);

View File

@ -79,7 +79,7 @@ int id_cmp(struct id *lhs, struct id *rhs)
}
#define GROUPS (ID_LEN / 4)
int id_format(struct id *id, char *buffer, size_t size)
int id_write_format(struct id *id, char *buffer, size_t size)
{
int i;

View File

@ -16,5 +16,9 @@ TARGETS=dbg_malloc_t
include ../../make.tmpl
dbg_malloc_t: dbg_malloc_t.o
$(CC) -o dbg_malloc_t dbg_malloc_t.o -L$(top_srcdir)/lib -llvm
$(CC) $(CFLAGS) -o dbg_malloc_t dbg_malloc_t.o \
-L$(top_srcdir)/lib -llvm
pool_t: pool_t.o
$(CC) $(CFLAGS) -o pool_t pool_t.o -L$(top_srcdir)/lib -llvm

View File

@ -89,7 +89,7 @@ static int lvchange_single(struct logical_volume *lv)
log_print("Logical volume %s changed", lv->name);
/* FIXME do_autobackup */
//autobackup();
return 0;
}

View File

@ -494,9 +494,11 @@ static struct arg *find_arg(struct command *com, int opt)
return 0;
}
/* FIXME: define CMD_SUCCEEDED, and return this instead of zero. */
static int process_common_commands(struct command *com)
{
int l;
char backup_dir[PATH_MAX];
if (arg_count(suspend_ARG))
kill(getpid(), SIGSTOP);
@ -542,7 +544,13 @@ static int process_common_commands(struct command *com)
/* Set autobackup if command takes this option */
for (l = 0; l < com->num_args; l++)
if (com->valid_args[l] == autobackup_ARG) {
if (init_autobackup())
if (snprintf(backup_dir, sizeof(backup_dir),
"%s/backup", _system_dir) < 0) {
log_err("Backup path too long.");
return ECMD_FAILED;
}
if (autobackup_init("/etc/lvm/backup"))
return EINVALID_CMD_LINE;
else
break;

View File

@ -1,92 +1,118 @@
/*
* Copyright (C) 2001 Sistina Software
*
* This LVM library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This LVM library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this LVM library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
*/
#include "tools.h"
#include "format-text.h"
#include "metadata.h"
#include <ctype.h>
#include <limits.h>
static int _autobackup = 1;
static char _backup_dir[PATH_MAX];
static int _period = 7; /* backups will be kept for at least 7 days */
static int _min_backups = 10; /* always have at least ten backups, even
* if they're old than the period */
int autobackup_set()
{
return _autobackup;
}
int init_autobackup()
/*
* Work out by looking at command line, config
* file and environment variable whether we should
* do an autobackup.
*/
int autobackup_init(const char *dir)
{
char *lvm_autobackup;
if (arg_count(autobackup_ARG)) {
_autobackup = strcmp(arg_str_value(autobackup_ARG, "y"), "n");
if (strlen(dir) > sizeof(_backup_dir) - 1) {
log_err("Backup directory (%s) too long.", dir);
return 0;
}
strcpy(_backup_dir, dir);
if (arg_count(autobackup_ARG)) {
_autobackup = !strcmp(arg_str_value(autobackup_ARG, "y"), "y");
return 1;
}
_autobackup = 1; /* default */
lvm_autobackup = getenv("LVM_AUTOBACKUP");
if (!lvm_autobackup)
return 0;
return 1;
log_print("using environment variable LVM_AUTOBACKUP "
"to set option A");
if (!strcasecmp(lvm_autobackup, "no"))
_autobackup = 0;
else if (strcasecmp(lvm_autobackup, "yes")) {
log_error("environment variable LVM_AUTOBACKUP has "
"invalid value \"%s\"!", lvm_autobackup);
return -1;
}
return 0;
}
int do_autobackup(struct volume_group *vg)
{
/***************
log_verbose("Changing lvmtab");
if ((vg_cfgbackup(vg_name, LVMTAB_DIR, vg))) {
log_error("\"%s\" writing \"%s\"", lvm_error(ret), LVMTAB);
return LVM_E_VG_CFGBACKUP;
}
**************/
if (!autobackup_set()) {
log_print
("WARNING: You don't have an automatic backup of %s",
vg->name);
return 0;
}
/***************
log_print("Creating automatic backup of volume group \"%s\"", vg_name);
if ((vg_cfgbackup(vg_name, VG_BACKUP_DIR, vg))) {
log_error("\"%s\" writing VG backup of \"%s\"", lvm_error(ret),
vg_name);
return LVM_E_VG_CFGBACKUP;
}
***************/
return 0;
return 1;
}
static int __autobackup(struct volume_group *vg)
{
int r;
struct pool *old;
struct format_instance *backer;
old = vg->cmd->mem;
/*
* Create a temprary pool for this, I
* doubt it's used but the backup code has
* the right to expect it.
*/
if (!(vg->cmd->mem = pool_create(1024))) {
stack;
vg->cmd->mem = old;
return 0;
}
if (!(backer = backup_format_create(vg->cmd, _backup_dir,
_period, _min_backups))) {
log_err("Couldn't create backup object.");
return 0;
}
if (!(r = backer->ops->vg_write(backer, vg)))
stack;
pool_destroy(vg->cmd->mem);
vg->cmd->mem = old;
return r;
}
int autobackup(struct volume_group *vg)
{
if (!__autobackup) {
log_print("WARNING: You don't have an automatic backup of %s",
vg->name);
return 1;
}
log_print("Creating automatic backup of volume group \"%s\" ...",
vg->name);
if (!__autobackup(vg)) {
log_err("Autobackup failed.");
return 0;
}
log_err("Autobackup not implemented yet.");
return 1;
}
int process_each_lv_in_vg(struct volume_group *vg,
int (*process_single) (struct logical_volume *lv))
{

View File

@ -22,8 +22,8 @@
#define _LVM_TOOLLIB_H
int autobackup_set(void);
int init_autobackup(void);
int do_autobackup(struct volume_group *vg);
int autobackup_init(const char *dir);
int autobackup(struct volume_group *vg);
int process_each_vg(int argc, char **argv,
int (*process_single) (const char *vg_name));