diff --git a/include/.symlinks b/include/.symlinks index 28f967e75..4ec61b862 100644 --- a/include/.symlinks +++ b/include/.symlinks @@ -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 diff --git a/lib/Makefile.in b/lib/Makefile.in index a13396043..4602288a0 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -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 \ diff --git a/lib/format_text/backup.c b/lib/format_text/backup.c index eafbc2259..d33a470a7 100644 --- a/lib/format_text/backup.c +++ b/lib/format_text/backup.c @@ -10,6 +10,12 @@ #include "pool.h" #include "config.h" #include "hash.h" +#include "import-export.h" +#include "lvm-string.h" + +#include +#include + /* * 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 _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; } diff --git a/lib/format_text/export.c b/lib/format_text/export.c index 4876aea4a..bdb055b91 100644 --- a/lib/format_text/export.c +++ b/lib/format_text/export.c @@ -9,8 +9,11 @@ #include "log.h" #include "hash.h" #include "pool.h" +#include "dbg_malloc.h" #include +#include +#include /* @@ -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; } diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c index a994535a6..8fd0ed7ba 100644 --- a/lib/format_text/flags.c +++ b/lib/format_text/flags.c @@ -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; } diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h index 8576a8ee1..07279b086 100644 --- a/lib/format_text/format-text.h +++ b/lib/format_text/format-text.h @@ -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); diff --git a/lib/format_text/import-export.h b/lib/format_text/import-export.h index 8de853ecf..3a0b90e84 100644 --- a/lib/format_text/import-export.h +++ b/lib/format_text/import-export.h @@ -8,6 +8,10 @@ #define _LVM_TEXT_IMPORT_EXPORT_H #include "config.h" +#include "lvm-types.h" +#include "metadata.h" + +#include enum { VG_FLAGS, diff --git a/lib/format_text/import.c b/lib/format_text/import.c index 2dfe8c0fb..f299fd1a8 100644 --- a/lib/format_text/import.c +++ b/lib/format_text/import.c @@ -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 diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index b9457efad..79b29ac85 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -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 */ diff --git a/lib/misc/lvm-string.h b/lib/misc/lvm-string.h index a502ce475..cee1e99f2 100644 --- a/lib/misc/lvm-string.h +++ b/lib/misc/lvm-string.h @@ -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; diff --git a/lib/mm/pool-fast.c b/lib/mm/pool-fast.c index f15e8fdd0..8027458b3 100644 --- a/lib/mm/pool-fast.c +++ b/lib/mm/pool-fast.c @@ -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) diff --git a/lib/mm/pool.h b/lib/mm/pool.h index c0ba5a459..af0da1508 100644 --- a/lib/mm/pool.h +++ b/lib/mm/pool.h @@ -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); diff --git a/lib/uuid/uuid.c b/lib/uuid/uuid.c index 96b2a6756..2904e0b49 100644 --- a/lib/uuid/uuid.c +++ b/lib/uuid/uuid.c @@ -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; diff --git a/old-tests/mm/Makefile.in b/old-tests/mm/Makefile.in index fc1e06ca3..e8d4b9e85 100644 --- a/old-tests/mm/Makefile.in +++ b/old-tests/mm/Makefile.in @@ -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 diff --git a/tools/lvchange.c b/tools/lvchange.c index 44305d158..551202c07 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -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; } diff --git a/tools/lvm.c b/tools/lvm.c index 413935e20..334fda5ae 100644 --- a/tools/lvm.c +++ b/tools/lvm.c @@ -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; diff --git a/tools/toollib.c b/tools/toollib.c index d6b5f7ca2..bf9c562ae 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -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 +#include 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)) { diff --git a/tools/toollib.h b/tools/toollib.h index 31ecdc8a3..ce81dcbaf 100644 --- a/tools/toollib.h +++ b/tools/toollib.h @@ -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));