summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/.symlinks1
-rw-r--r--lib/Makefile.in4
-rw-r--r--lib/format_text/backup.c221
-rw-r--r--lib/format_text/export.c54
-rw-r--r--lib/format_text/flags.c28
-rw-r--r--lib/format_text/format-text.h5
-rw-r--r--lib/format_text/import-export.h4
-rw-r--r--lib/format_text/import.c2
-rw-r--r--lib/metadata/metadata.h2
-rw-r--r--lib/misc/lvm-string.h2
-rw-r--r--lib/mm/pool-fast.c20
-rw-r--r--lib/mm/pool.h6
-rw-r--r--lib/uuid/uuid.c2
-rw-r--r--old-tests/mm/Makefile.in6
-rw-r--r--tools/lvchange.c2
-rw-r--r--tools/lvm.c10
-rw-r--r--tools/toollib.c120
-rw-r--r--tools/toollib.h4
18 files changed, 344 insertions, 149 deletions
diff --git a/include/.symlinks b/include/.symlinks
index 28f967e7..4ec61b86 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 a1339604..4602288a 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 eafbc225..d33a470a 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 <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)
+{
+ 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;
+ int r = 0, i, count, index;
+ char vg_name[64], *path;
+ struct dirent **dirent;
- if ((count = scandir(dir, &dirent, NULL, alphasort)) < 0) {
+ if ((count = scandir(bc->dir, &dirent, NULL, alphasort)) < 0) {
log_err("Couldn't scan backup directory.");
- return NULL;
+ 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 (bc->vg_backups)
+ hash_destroy(bc->vg_backups);
- if (!(h = hash_create(128))) {
+ 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;
}
-void backup_expire(struct format_instance *fi)
+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 hash_table *vgs;
+ 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)
+{
+ /* 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 4876aea4..bdb055b9 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 <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;
}
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index a994535a..8fd0ed7b 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 8576a8ee..07279b08 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 8de853ec..3a0b90e8 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 <stdio.h>
enum {
VG_FLAGS,
diff --git a/lib/format_text/import.c b/lib/format_text/import.c
index 2dfe8c0f..f299fd1a 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 b9457efa..79b29ac8 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 a502ce47..cee1e99f 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 f15e8fdd..8027458b 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 c0ba5a45..af0da150 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 96b2a675..2904e0b4 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 fc1e06ca..e8d4b9e8 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 44305d15..551202c0 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 413935e2..334fda5a 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 d6b5f7ca..bf9c562a 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 <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;
}
- return 0;
+ return 1;
}
-int do_autobackup(struct volume_group *vg)
+static int __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;
+ 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 (!autobackup_set()) {
- log_print
- ("WARNING: You don't have an automatic backup of %s",
- vg->name);
+ if (!(backer = backup_format_create(vg->cmd, _backup_dir,
+ _period, _min_backups))) {
+ log_err("Couldn't create backup object.");
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;
+ 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;
}
-***************/
- return 0;
+ 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 31ecdc8a..ce81dcba 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));