]> git.neil.brown.name Git - lafs-utils.git/commitdiff
add mount command
authorNeilBrown <neilb@suse.de>
Sat, 19 Mar 2011 07:51:40 +0000 (18:51 +1100)
committerNeilBrown <neilb@suse.de>
Sat, 19 Mar 2011 07:51:40 +0000 (18:51 +1100)
new command for 'lafs' and lafs_mount in library.

Doesn't load the root inode yet, just locates it.

Signed-off-by: NeilBrown <neilb@suse.de>
include/lafs/lafs.h
lib/lafs_mount.c [new file with mode: 0644]
tools/lafs.c

index b43a44eb096d53588385cfd22ed083f7f9a6e84f..eab54829a9daa96c31a9b468ef3f439d9d18d8a8 100644 (file)
@@ -67,6 +67,7 @@ void lafs_segment_count(struct lafs *fs, loff_t addr, int diff);
 
 void lafs_print_device(struct lafs_device *dev);
 void lafs_print_devblock(struct lafs_dev *dev);
+char *lafs_mount(struct lafs *fs, int force);
 
 static inline struct lafs_dblk *dblk(struct lafs_blk *b)
 {
diff --git a/lib/lafs_mount.c b/lib/lafs_mount.c
new file mode 100644 (file)
index 0000000..71c2e24
--- /dev/null
@@ -0,0 +1,112 @@
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <talloc.h>
+#include <lafs/lafs.h>
+#include "internal.h"
+
+static int csum_ok(struct lafs_state *st, int size)
+{
+       u32 crc, crc2;
+       crc = st->checksum;
+       st->checksum = 0;
+       crc2 = crc32(0, (uint32_t*)st, size);
+       st->checksum = crc;
+       return crc == crc2;
+}
+
+char *lafs_mount(struct lafs *fs, int force)
+{
+       char *err = NULL;
+       struct lafs_device *dv;
+       struct lafs_state *st;
+       struct lafs_snapshot **ssp;
+       int s;
+
+       if (fs->blocksize == 0)
+               return strdup("mount: no devices loaded");
+
+       if (fs->loaded_devs != fs->devices) {
+               asprintf(&err, 
+                        "need %d devices, only %d loaded",
+                        fs->devices, fs->loaded_devs);
+               return err;
+       }
+       /* - check that the loaded devices don't overlap.
+        * - Choose and load a state block
+        * - fill in data in 'lafs': e..g ss, max_segment, checkpoint_cluster,
+        *   youth
+        */
+
+       if (fs->ss.root || fs->ss.root_addr) {
+               asprintf(&err, "LaFS is already mounted");
+               return err;
+       }
+
+       /* FIXME check seq number is OK. */
+       for (dv = fs->devs; dv; dv = dv->next) {
+               struct lafs_device *dv2;
+               for (dv2 = dv->next; dv2; dv2= dv->next) {
+                       if (dv->start < dv2->start + dv2->size &&
+                           dv->start + dv->size <= dv2->start)
+                               continue;
+                       if (dv2->start < dv->start + dv->size &&
+                           dv2->start + dv2->size <= dv->start)
+                               continue;
+                       asprintf(&err, "devices %s and %s overlap",
+                                dv->name, dv2->name);
+                       return err;
+               }
+       }
+       st = malloc(fs->statesize);
+       for (dv = fs->devs; dv; dv = dv->next)
+               if (lseek64(dv->fd, dv->stateaddr[dv->recent_state], 0)
+                   == dv->stateaddr[dv->recent_state]
+                   && read(dv->fd, st, fs->statesize) == fs->statesize)
+                       break;
+       if (!dv) {
+               asprintf(&err, "Couldn't load a state block from any device");
+               free(st);
+               return err;
+       }
+       /* The state block has already been checked by lafs_load, but just
+        * to be sure...
+        */
+       if (memcmp(st->idtag, "LaFS-State-Block", 16) != 0 ||
+           memcmp(st->uuid, fs->uuid, 16) != 0 ||
+           !csum_ok(st, fs->statesize)) {
+               asprintf(&err, "state block nolonger looks correct");
+               free(st);
+               return err;
+       }
+       /* OK, let-her-rip. */
+       fs->seq = __le32_to_cpu(st->seq);
+//     fs->levels = __le32_to_cpu(st->levels);
+       fs->checkpoint_cluster = __le64_to_cpu(st->checkpointcluster);
+       fs->youth_next = __le16_to_cpu(st->nextyouth);
+       fs->ss.root_addr = __le64_to_cpu(st->root_inodes[0]);
+       fs->ss.next = NULL;
+
+       ssp = &fs->ss.next;
+       for (s = 1; s < __le32_to_cpu(st->maxsnapshot); s++) {
+               struct lafs_snapshot *ss = talloc(fs, struct lafs_snapshot);
+               ss->next = NULL;
+               ss->root_addr = __le64_to_cpu(st->root_inodes[s]);
+               ss->root = NULL;
+               ss->rootdir = NULL;
+               *ssp = ss;
+               ssp = &ss->next;
+       }
+
+       fs->max_segment = 0;
+       for (dv = fs->devs ; dv; dv=dv->next)
+               if (fs->max_segment < dv->segment_size)
+                       fs->max_segment = dv->segment_size;
+
+       fs->checkpointing = 0;
+       free(st);
+       return NULL;
+}
index bb942c98679a4848dc7253d512e618e824819b51..32e5de7f457daf9c70c55f587d1ace037805f4fc 100644 (file)
@@ -1094,6 +1094,57 @@ static void c_load_dev(struct state *st, void **args)
        }
 }
 
+/****** MOUNT ******/
+static char help_mount[] = "Coalesce loaded devices into a filesystem";
+static struct args args_mount[] = {
+       { "DEVNAME", external, -1, {NULL}, "Device to load and mount"},
+       { "-file", external, 0, {NULL}, "File to load and mount"},
+       { "-force", flag, -1, {NULL}, "Try to mount even if there are problems"},
+       TERMINAL_ARG
+};
+static void c_mount(struct state *st, void **args)
+{
+       char *err;
+       if (args[1]) {
+               /* Load the device first, then mount */
+               char *devname = args[1];
+               long long device_bytes = 0;
+               int fd;
+               struct lafs_device *dev;
+               if (st->lafs->blocksize) {
+                       printf("mount: lafs already initialised - cannot load %s\n",
+                              devname);
+                       return;
+               }
+               fd = open_device(devname, &device_bytes, args[2] != NULL, &err);
+               if (fd < 0) {
+                       printf("mount: %s\n", err);
+                       free(err);
+                       return;
+               }
+               dev = lafs_load(fd, device_bytes, &err);
+               if (err) {
+                       printf("mount: Cannot load %s: %s\n", devname, err);
+                       if (dev)
+                               talloc_free(dev);
+                       close(fd);
+                       return;
+               }
+               dev->name = talloc_strdup(dev, devname);
+               if (lafs_include_dev(st->lafs, dev, &err) != 0) {
+                       printf("mount: Cannot use %s: %s\n", devname, err);
+                       talloc_free(dev);
+                       return;
+               }
+               printf("loaded device %s\n", devname);
+       }
+       err = lafs_mount(st->lafs, args[3] != NULL);
+       if (err) {
+               printf("mount: cannot mount filesystem: %s\n", err);
+               free(err);
+       }
+}
+
 /****** SHOW *****/
 static struct cmd show_cmds[];
 
@@ -1231,6 +1282,7 @@ static struct cmd lafs_cmds[] = {
        CMD(exit),
        CMD(help),
        CMD(load_dev),
+       CMD(mount),
        CMD(newfs),
        CMD(quit),
        CMD(reset),