HAMMER Utilities: Sync with 60I
authorMatthew Dillon <dillon@dragonflybsd.org>
Wed, 9 Jul 2008 10:32:30 +0000 (10:32 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Wed, 9 Jul 2008 10:32:30 +0000 (10:32 +0000)
* Changes in the way PFS's are created and managed.

* Replace the pfs-create directive with pfs-master and pfs-slave.

* Add more checks against stupid user errors.

* A cycle file is no longer needed when using mirror-copy.  Mirror-copy
  now uses a two-way protocol and figures out what TID ranges need to
  be copied.

sbin/hammer/cmd_mirror.c
sbin/hammer/cmd_pseudofs.c
sbin/hammer/cmd_status.c
sbin/hammer/hammer.8
sbin/hammer/hammer.c
sbin/hammer/hammer.h

index 1b98c4b..efd7e82 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sbin/hammer/cmd_mirror.c,v 1.5 2008/07/07 03:51:28 dillon Exp $
+ * $DragonFly: src/sbin/hammer/cmd_mirror.c,v 1.6 2008/07/09 10:32:30 dillon Exp $
  */
 
 #include "hammer.h"
@@ -48,17 +48,18 @@ static int read_mrecords(int fd, char *buf, u_int size,
 static struct hammer_ioc_mrecord *read_mrecord(int fdin, int *errorp,
                         hammer_ioc_mrecord_t pickup);
 static void write_mrecord(int fdout, u_int32_t type, void *payload, int bytes);
-static void generate_mrec_header(int fd, int fdout,
+static void generate_mrec_header(int fd, int fdout, int pfs_id,
                         hammer_tid_t *tid_begp, hammer_tid_t *tid_endp);
-static void validate_mrec_header(int fd, int fdin,
+static void validate_mrec_header(int fd, int fdin, int is_target, int pfs_id,
                         hammer_tid_t *tid_begp, hammer_tid_t *tid_endp);
-static void update_pfs_snapshot(int fd, hammer_tid_t snapshot_tid);
+static void update_pfs_snapshot(int fd, hammer_tid_t snapshot_tid, int pfs_id);
 static void mirror_usage(int code);
 
 void
 hammer_cmd_mirror_read(char **av, int ac)
 {
        struct hammer_ioc_mirror_rw mirror;
+       struct hammer_ioc_pseudofs_rw pfs;
        hammer_ioc_mrecord_t mrec;
        hammer_tid_t sync_tid;
        const char *filesystem;
@@ -77,14 +78,29 @@ hammer_cmd_mirror_read(char **av, int ac)
        hammer_key_beg_init(&mirror.key_beg);
        hammer_key_end_init(&mirror.key_end);
 
-       fd = open(filesystem, O_RDONLY);
-       if (fd < 0)
-               err(1, "Unable to open %s", filesystem);
+       fd = getpfs(&pfs, filesystem);
+
+       /*
+        * In 2-way mode the target will send us a PFS info packet
+        * first.  Use the target's current snapshot TID as our default
+        * begin TID.
+        */
+       mirror.tid_beg = 0;
+       if (TwoWayPipeOpt)
+               validate_mrec_header(fd, 0, 0, pfs.pfs_id,
+                                    NULL, &mirror.tid_beg);
+
+       /*
+        * Write out the PFS header, tid_beg will be updated if our PFS
+        * has a larger begin sync.  tid_end is set to the latest source
+        * TID whos flush cycle has completed.
+        */
+       generate_mrec_header(fd, 1, pfs.pfs_id,
+                            &mirror.tid_beg, &mirror.tid_end);
 
        /*
-        * Write out the PFS header
+        * A cycle file overrides the beginning TID
         */
-       generate_mrec_header(fd, 1, &mirror.tid_beg, &mirror.tid_end);
        hammer_get_cycle(&mirror.key_beg, &mirror.tid_beg);
 
        fprintf(stderr, "mirror-read: Mirror from %016llx to %016llx\n",
@@ -104,6 +120,8 @@ hammer_cmd_mirror_read(char **av, int ac)
 
        do {
                mirror.count = 0;
+               mirror.pfs_id = pfs.pfs_id;
+               mirror.shared_uuid = pfs.ondisk->shared_uuid;
                if (ioctl(fd, HAMMERIOC_MIRROR_READ, &mirror) < 0) {
                        fprintf(stderr, "Mirror-read %s failed: %s\n",
                                filesystem, strerror(errno));
@@ -181,6 +199,7 @@ hammer_cmd_mirror_write(char **av, int ac)
        struct hammer_ioc_mirror_rw mirror;
        const char *filesystem;
        char *buf = malloc(SERIALBUF_SIZE);
+       struct hammer_ioc_pseudofs_rw pfs;
        struct hammer_ioc_mrecord pickup;
        struct hammer_ioc_synctid synctid;
        hammer_ioc_mrecord_t mrec;
@@ -195,14 +214,26 @@ hammer_cmd_mirror_write(char **av, int ac)
        hammer_key_beg_init(&mirror.key_beg);
        hammer_key_end_init(&mirror.key_end);
 
-       fd = open(filesystem, O_RDONLY);
-       if (fd < 0)
-               err(1, "Unable to open %s", filesystem);
+       fd = getpfs(&pfs, filesystem);
 
        /*
-        * Read and process the PFS header 
+        * In two-way mode the target writes out a PFS packet first.
+        * The source uses our tid_end as its tid_beg by default,
+        * picking up where it left off.
+        */
+       mirror.tid_beg = 0;
+       if (TwoWayPipeOpt) {
+               generate_mrec_header(fd, 1, pfs.pfs_id,
+                                    &mirror.tid_beg, &mirror.tid_end);
+       }
+
+       /*
+        * Read and process the PFS header.  The source informs of its 
+        * tid_end, which we set ours too upon completion of the operation
+        * without error.
         */
-       validate_mrec_header(fd, 0, &mirror.tid_beg, &mirror.tid_end);
+       validate_mrec_header(fd, 0, 1, pfs.pfs_id,
+                            &mirror.tid_beg, &mirror.tid_end);
 
        mirror.ubuf = buf;
        mirror.size = SERIALBUF_SIZE;
@@ -215,6 +246,8 @@ hammer_cmd_mirror_write(char **av, int ac)
         */
        for (;;) {
                mirror.count = 0;
+               mirror.pfs_id = pfs.pfs_id;
+               mirror.shared_uuid = pfs.ondisk->shared_uuid;
                mirror.size = read_mrecords(0, buf, SERIALBUF_SIZE, &pickup);
                if (mirror.size <= 0)
                        break;
@@ -250,7 +283,7 @@ hammer_cmd_mirror_write(char **av, int ac)
         * Update the PFS info on the target so the user has visibility
         * into the new snapshot.
         */
-       update_pfs_snapshot(fd, mirror.tid_end);
+       update_pfs_snapshot(fd, mirror.tid_end, pfs.pfs_id);
 
        /*
         * Sync the target filesystem
@@ -600,7 +633,7 @@ write_mrecord(int fdout, u_int32_t type, void *payload, int bytes)
  * originating filesytem.
  */
 static void
-generate_mrec_header(int fd, int fdout,
+generate_mrec_header(int fd, int fdout, int pfs_id,
                     hammer_tid_t *tid_begp, hammer_tid_t *tid_endp)
 {
        struct hammer_ioc_pseudofs_rw pfs;
@@ -608,6 +641,7 @@ generate_mrec_header(int fd, int fdout,
 
        bzero(&pfs, sizeof(pfs));
        bzero(&pfs_head, sizeof(pfs_head));
+       pfs.pfs_id = pfs_id;
        pfs.ondisk = &pfs_head.pfsd;
        pfs.bytes = sizeof(pfs_head.pfsd);
        if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) != 0) {
@@ -625,8 +659,10 @@ generate_mrec_header(int fd, int fdout,
         *
         * sync_end_tid - highest fully synchronized TID from source.
         */
-       *tid_begp = pfs_head.pfsd.sync_beg_tid;
-       *tid_endp = pfs_head.pfsd.sync_end_tid;
+       if (tid_begp && *tid_begp < pfs_head.pfsd.sync_beg_tid)
+               *tid_begp = pfs_head.pfsd.sync_beg_tid;
+       if (tid_endp)
+               *tid_endp = pfs_head.pfsd.sync_end_tid;
 
        pfs_head.version = pfs.version;
        write_mrecord(fdout, HAMMER_MREC_TYPE_PFSD,
@@ -638,7 +674,7 @@ generate_mrec_header(int fd, int fdout,
  * against the target filesystem.  shared_uuid must match.
  */
 static void
-validate_mrec_header(int fd, int fdin,
+validate_mrec_header(int fd, int fdin, int is_target, int pfs_id,
                     hammer_tid_t *tid_begp, hammer_tid_t *tid_endp)
 {
        struct hammer_ioc_pseudofs_rw pfs;
@@ -653,6 +689,7 @@ validate_mrec_header(int fd, int fdin,
         */
        bzero(&pfs, sizeof(pfs));
        bzero(&pfsd, sizeof(pfsd));
+       pfs.pfs_id = pfs_id;
        pfs.ondisk = &pfsd;
        pfs.bytes = sizeof(pfsd);
        if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) != 0) {
@@ -694,23 +731,27 @@ validate_mrec_header(int fd, int fdin,
                fprintf(stderr, "mirror-write: source and target have different shared_uuid's!\n");
                exit(1);
        }
-       if ((pfsd.mirror_flags & HAMMER_PFSD_SLAVE) == 0) {
+       if (is_target &&
+           (pfsd.mirror_flags & HAMMER_PFSD_SLAVE) == 0) {
                fprintf(stderr, "mirror-write: target must be in slave mode\n");
                exit(1);
        }
-       *tid_begp = pfs_head->pfsd.sync_beg_tid;
-       *tid_endp = pfs_head->pfsd.sync_end_tid;
+       if (tid_begp)
+               *tid_begp = pfs_head->pfsd.sync_beg_tid;
+       if (tid_endp)
+               *tid_endp = pfs_head->pfsd.sync_end_tid;
        free(mrec);
 }
 
 static void
-update_pfs_snapshot(int fd, hammer_tid_t snapshot_tid)
+update_pfs_snapshot(int fd, hammer_tid_t snapshot_tid, int pfs_id)
 {
        struct hammer_ioc_pseudofs_rw pfs;
        struct hammer_pseudofs_data pfsd;
 
        bzero(&pfs, sizeof(pfs));
        bzero(&pfsd, sizeof(pfsd));
+       pfs.pfs_id = pfs_id;
        pfs.ondisk = &pfsd;
        pfs.bytes = sizeof(pfsd);
        if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) != 0) {
index 3cc88a3..87516f6 100644 (file)
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sbin/hammer/cmd_pseudofs.c,v 1.4 2008/07/07 00:27:22 dillon Exp $
+ * $DragonFly: src/sbin/hammer/cmd_pseudofs.c,v 1.5 2008/07/09 10:32:30 dillon Exp $
  */
 
 #include "hammer.h"
 
 static void parse_pfsd_options(char **av, int ac, hammer_pseudofs_data_t pfsd);
-static void init_pfsd(hammer_pseudofs_data_t pfsd);
+static void init_pfsd(hammer_pseudofs_data_t pfsd, int is_slave);
 static void dump_pfsd(hammer_pseudofs_data_t pfsd);
 static void pseudofs_usage(int code);
 
+/*
+ * Calculate the pfs_id given a path to a directory or a @@PFS or @@%llx:%d
+ * softlink.
+ */
+int
+getpfs(struct hammer_ioc_pseudofs_rw *pfs, const char *path)
+{
+       hammer_tid_t dummy_tid;
+       struct stat st;
+       char *dirpath;
+       char buf[64];
+       int fd;
+       int n;
+
+       bzero(pfs, sizeof(*pfs));
+       pfs->ondisk = malloc(sizeof(*pfs->ondisk));
+       bzero(pfs->ondisk, sizeof(*pfs->ondisk));
+       pfs->bytes = sizeof(*pfs->ondisk);
+
+       /*
+        * Calculate the directory containing the softlink
+        */
+       dirpath = strdup(path);
+       if (strrchr(dirpath, '/'))
+               *strrchr(dirpath, '/') = 0;
+       else
+               dirpath = strdup(".");
+
+       if (lstat(path, &st) == 0 && S_ISLNK(st.st_mode)) {
+               n = readlink(path, buf, sizeof(buf) - 1);
+               if (n < 0)
+                       n = 0;
+               buf[n] = 0;
+               if (sscanf(buf, "@@PFS%d", &pfs->pfs_id) == 1) {
+                       fd = open(dirpath, O_RDONLY);
+                       goto done;
+               }
+               if (sscanf(buf, "@@%llx:%d", &dummy_tid, &pfs->pfs_id) == 2) {
+                       fd = open(dirpath, O_RDONLY);
+                       goto done;
+               }
+       }
+
+       /*
+        * Try to open the path and request the pfs_id that way.
+        */
+       fd = open(path, O_RDONLY);
+       if (fd >= 0) {
+               pfs->pfs_id = -1;
+               ioctl(fd, HAMMERIOC_GET_PSEUDOFS, pfs);
+               if (pfs->pfs_id == -1) {
+                       close(fd);
+                       fd = -1;
+               }
+       }
+
+       /*
+        * Cleanup
+        */
+done:
+       if (fd < 0) {
+               fprintf(stderr, "Cannot access PFS %s: %s\n",
+                       path, strerror(errno));
+               exit(1);
+       }
+       if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, pfs) < 0) {
+               fprintf(stderr, "Cannot access PFS %s: %s\n",
+                       path, strerror(errno));
+               exit(1);
+       }
+       free(dirpath);
+       return(fd);
+}
+
 void
 hammer_cmd_pseudofs_status(char **av, int ac)
 {
        struct hammer_ioc_pseudofs_rw pfs;
-       struct hammer_pseudofs_data pfsd;
        int i;
        int fd;
 
        for (i = 0; i < ac; ++i) {
-               bzero(&pfsd, sizeof(pfsd));
-               bzero(&pfs, sizeof(pfs));
-               pfs.ondisk = &pfsd;
-               pfs.bytes = sizeof(pfsd);
                printf("%s\t", av[i]);
-               fd = open(av[i], O_RDONLY);
+               fd = getpfs(&pfs, av[i]);
                if (fd < 0 || ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) < 0) {
                        printf("Not a HAMMER root\n");
                } else {
-                       printf("Pseudo-fs #0x%08x {\n", pfs.pseudoid);
-                       dump_pfsd(&pfsd);
+                       printf("PFS #%d {\n", pfs.pfs_id);
+                       dump_pfsd(pfs.ondisk);
                        printf("}\n");
                }
+               if (fd >= 0)
+                       close(fd);
+               if (pfs.ondisk)
+                       free(pfs.ondisk);
        }
 }
 
 void
-hammer_cmd_pseudofs_create(char **av, int ac)
+hammer_cmd_pseudofs_create(char **av, int ac, int is_slave)
 {
+       struct hammer_ioc_pseudofs_rw pfs;
+       struct hammer_pseudofs_data pfsd;
+       struct stat st;
+       const char *path;
+       char *dirpath;
+       char *linkpath;
+       int pfs_id;
+       int fd;
+       int error;
+
        if (ac == 0)
                pseudofs_usage(1);
+       path = av[0];
+       if (lstat(path, &st) == 0) {
+               fprintf(stderr, "cannot create %s, file exists!\n", path);
+               exit(1);
+       }
+
+       dirpath = strdup(path);
+       if (strrchr(dirpath, '/') != NULL)
+               *strrchr(dirpath, '/') = 0;
+       else
+               dirpath = strdup(".");
+       fd = open(dirpath, O_RDONLY);
+       if (fd < 0) {
+               fprintf(stderr, "Cannot open directory %s\n", dirpath);
+               exit(1);
+       }
 
-       if (mknod(av[0], S_IFDIR|0777, 0) < 0) {
-               perror("mknod (create pseudofs):");
+       error = 0;
+       for (pfs_id = 0; pfs_id < HAMMER_MAX_PFS; ++pfs_id) {
+               bzero(&pfs, sizeof(pfs));
+               bzero(&pfsd, sizeof(pfsd));
+               pfs.pfs_id = pfs_id;
+               pfs.ondisk = &pfsd;
+               pfs.bytes = sizeof(pfsd);
+               pfs.version = HAMMER_IOC_PSEUDOFS_VERSION;
+               if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) < 0) {
+                       error = errno;
+                       break;
+               }
+       }
+       if (pfs_id == HAMMER_MAX_PFS) {
+               fprintf(stderr, "Cannot create %s, all PFSs in use\n", path);
+               exit(1);
+       }
+       if (error != ENOENT) {
+               fprintf(stderr, "Cannot create %s, got %s during scan\n",
+                       path, strerror(error));
                exit(1);
        }
-       hammer_cmd_pseudofs_update(av, ac, 1);
+
+       /*
+        * Create the new PFS
+        */
+       printf("Creating PFS #%d\t", pfs_id);
+       bzero(&pfsd, sizeof(pfsd));
+       init_pfsd(&pfsd, is_slave);
+       pfs.pfs_id = pfs_id;
+       pfs.ondisk = &pfsd;
+       pfs.bytes = sizeof(pfsd);
+       pfs.version = HAMMER_IOC_PSEUDOFS_VERSION;
+
+       if (ioctl(fd, HAMMERIOC_SET_PSEUDOFS, &pfs) < 0) {
+               printf("failed: %s\n", strerror(errno));
+       } else {
+               /* special symlink, must be exactly 10 characters */
+               asprintf(&linkpath, "@@PFS%05d", pfs_id);
+               if (symlink(linkpath, path) < 0) {
+                       printf("failed: cannot create symlink: %s\n",
+                               strerror(errno));
+               } else {
+                       printf("succeeded!\n");
+                       hammer_cmd_pseudofs_update(av, ac);
+               }
+       }
+       close(fd);
 }
 
 void
@@ -86,36 +228,30 @@ hammer_cmd_pseudofs_destroy(char **av, int ac)
 }
 
 void
-hammer_cmd_pseudofs_update(char **av, int ac, int doinit)
+hammer_cmd_pseudofs_update(char **av, int ac)
 {
        struct hammer_ioc_pseudofs_rw pfs;
-       struct hammer_pseudofs_data pfsd;
        int fd;
 
        if (ac == 0)
                pseudofs_usage(1);
        bzero(&pfs, sizeof(pfs));
-       bzero(&pfsd, sizeof(pfsd));
-       pfs.ondisk = &pfsd;
-       pfs.bytes = sizeof(pfsd);
-       pfs.version = HAMMER_IOC_PSEUDOFS_VERSION;
+       fd = getpfs(&pfs, av[0]);
 
-       printf("%s\t", av[0]);
+       printf("%s\n", av[0]);
        fflush(stdout);
-       fd = open(av[0], O_RDONLY);
 
        if (fd >= 0 && ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) == 0) {
-               if (doinit) {
-                       printf("Pseudo-fs #0x%08x created\n", pfs.pseudoid);
-                       init_pfsd(&pfsd);
-               } else {
-                       printf("\n");
+               parse_pfsd_options(av + 1, ac - 1, pfs.ondisk);
+               if ((pfs.ondisk->mirror_flags & HAMMER_PFSD_SLAVE) &&
+                   pfs.pfs_id == 0) {
+                       fprintf(stderr, "The real mount point cannot be made a PFS slave, only PFS sub-directories can be made slaves\n");
+                       exit(1);
                }
-               parse_pfsd_options(av + 1, ac - 1, &pfsd);
-               pfs.bytes = sizeof(pfsd);
+               pfs.bytes = sizeof(*pfs.ondisk);
                if (ioctl(fd, HAMMERIOC_SET_PSEUDOFS, &pfs) == 0) {
                        if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) == 0) {
-                               dump_pfsd(&pfsd);
+                               dump_pfsd(pfs.ondisk);
                        } else {
                                printf("Unable to retrieve pfs configuration after successful update: %s\n", strerror(errno));
                                exit(1);
@@ -131,7 +267,7 @@ hammer_cmd_pseudofs_update(char **av, int ac, int doinit)
 }
 
 static void
-init_pfsd(hammer_pseudofs_data_t pfsd)
+init_pfsd(hammer_pseudofs_data_t pfsd, int is_slave)
 {
        uint32_t status;
 
@@ -141,7 +277,12 @@ init_pfsd(hammer_pseudofs_data_t pfsd)
        pfsd->sync_end_ts = 0;
        uuid_create(&pfsd->shared_uuid, &status);
        uuid_create(&pfsd->unique_uuid, &status);
-       pfsd->master_id = 0;
+       if (is_slave) {
+               pfsd->master_id = -1;
+               pfsd->mirror_flags |= HAMMER_PFSD_SLAVE;
+       } else {
+               pfsd->master_id = 0;
+       }
 }
 
 static
@@ -211,12 +352,24 @@ parse_pfsd_options(char **av, int ac, hammer_pseudofs_data_t pfsd)
                } else if (strcmp(cmd, "unique-uuid") == 0) {
                        uuid_from_string(ptr, &pfsd->unique_uuid, &status);
                } else if (strcmp(cmd, "master") == 0) {
+                       if (pfsd->mirror_flags & HAMMER_PFSD_SLAVE) {
+                               fprintf(stderr, "master mode cannot be set on a slave PFS\n");
+                               exit(1);
+                       }
                        pfsd->master_id = strtol(ptr, NULL, 0);
                        pfsd->mirror_flags &= ~HAMMER_PFSD_SLAVE;
                } else if (strcmp(cmd, "slave") == 0) {
+                       if ((pfsd->mirror_flags & HAMMER_PFSD_SLAVE) == 0) {
+                               fprintf(stderr, "slave mode cannot be set on a master PFS\n");
+                               exit(1);
+                       }
                        pfsd->master_id = -1;
                        pfsd->mirror_flags |= HAMMER_PFSD_SLAVE;
                } else if (strcmp(cmd, "no-mirror") == 0) {
+                       if (pfsd->mirror_flags & HAMMER_PFSD_SLAVE) {
+                               fprintf(stderr, "no-mirror master mode cannot be set on a slave PFS\n");
+                               exit(1);
+                       }
                        pfsd->master_id = -1;
                        pfsd->mirror_flags &= ~HAMMER_PFSD_SLAVE;
                } else if (strcmp(cmd, "label") == 0) {
@@ -251,7 +404,9 @@ pseudofs_usage(int code)
 {
        fprintf(stderr, 
                "hammer pfs-status <dirpath1>...<dirpathN>\n"
-               "hammer pfs-create <dirpath> [options]\n"
+               "hammer pfs-master <dirpath> [options]\n"
+               "hammer pfs-slave <dirpath> [options]\n"
+               "hammer pfs-destroy <dirpath>\n"
                "hammer pfs-update <dirpath> [options]\n"
                "\n"
                "    sync-beg-tid=0x16llx\n"
index c09c5e7..cb2658d 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sbin/hammer/cmd_status.c,v 1.2 2008/07/02 22:05:59 dillon Exp $
+ * $DragonFly: src/sbin/hammer/cmd_status.c,v 1.3 2008/07/09 10:32:30 dillon Exp $
  */
 
 #include "hammer.h"
@@ -49,7 +49,7 @@ hammer_cmd_status(char **av, int ac)
                if (fd < 0 || ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) < 0) {
                        printf("HAMMER ioctl failed\n");
                } else {
-                       printf("Pseudo-fs #0x%08x\n", pfs.pseudoid);
+                       printf("PFS #%d\n", pfs.pfs_id);
                }
        }
 }
index fbdf979..e4c8479 100644 (file)
@@ -30,7 +30,7 @@
 .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\" 
-.\" $DragonFly: src/sbin/hammer/hammer.8,v 1.32 2008/07/07 03:51:28 dillon Exp $
+.\" $DragonFly: src/sbin/hammer/hammer.8,v 1.33 2008/07/09 10:32:30 dillon Exp $
 .Dd June 26, 2008
 .Dt HAMMER 8
 .Os
@@ -39,7 +39,7 @@
 .Nd HAMMER file system utility
 .Sh SYNOPSIS
 .Nm
-.Op Fl hrv
+.Op Fl hrv2
 .Op Fl c Ar cyclefile
 .Op Fl f Ar blkdev[:blkdev]*
 .Op Fl s Ar linkpath
@@ -56,6 +56,12 @@ The options are as follows:
 .Bl -tag -width indent
 .It Fl h
 Get help
+.It Fl 2
+Tell the mirror commands to use a 2-way protocol, which allows
+automatic negotiation of transaction id ranges.  This option is
+automatically enabled by the
+.Ar mirror-copy
+command.
 .It Fl r
 Specify recursion for those commands which support it.
 .It Fl c Ar cyclefile
@@ -238,14 +244,39 @@ period of time.
 .It Ar pfs-status Ar dirpath
 Retrieve the mirroring configuration parameters for the specified
 HAMMER filesystem or pseudo-filesystem.
-.It Ar pfs-create Ar dirpath Op options
-Create a pseudo-filesystem inside a HAMMER filesystem.  Up to 65535 such
-filesystems can be created.  Each one uses an independant inode numbering
-space making it suitable for use as a replication source or target.
+.It Ar pfs-master Ar dirpath Op options
+Create a pseudo-filesystem (PFS) inside a HAMMER filesystem.
+Up to 65535 such filesystems can be created.
+Each PFS uses an independant inode numbering space making it suitable
+for use as a replication source or target.
+.Pp
+The
+.Ar pfs-master
+directive creates a PFS that you can read, write, and use as a mirroring
+source.
+.It Ar pfs-slave Ar dirpath Op options
+Create a pseudo-filesystem (PFS) inside a HAMMER filesystem.
+Up to 65535 such filesystems can be created.
+Each PFS uses an independant inode numbering space making it suitable
+for use as a replication source or target.
+.Pp
+The
+.Ar pfs-slave
+directive creates a PFS that you can use as a mirroring target.  
+You will not be able to access a slave PFS until you have completed the
+first mirroring operation with it as the target (its root directory will
+not exist until then).
 .Pp
-Note that rm -rf'ing a pseudo-fs will not allow the pseudo-id to be reused
-until all historical data has been pruned out and the pseudo-fs is truely
-empty.
+Access to the pfs-slave via the special softlink allows Hammer to
+dynamically modify the snapshot TID by returning a dynamic result
+from readlink() calls.
+.Pp
+A PFS can only be truely destroyed with the
+.AR pfs-destroy
+directive.
+Removing the softlink will not destroy the underlying PFS.
+.It Ar pfs-destroy Ar dirpath
+This permanently destroys a PFS.
 .It Ar pfs-update Ar dirpath Op options
 Update the configuration parameters for an existing HAMMER filesystem
 or pseudo-filesystem.  Options that may be specified:
@@ -289,17 +320,23 @@ inclusive may be specified.  All masters sharing the same
 .Ar shared-uuid
 must have different ids.
 Up to 16 masters will eventually be supported.
+.Pp
 Multi-master mirroring is not supported yet and the master id should be
 set to 0 on the single master when mirroring to one or more slaves.
+.Pp
+The master id may only be changed if the PFS is in master mode.  A PFS
+slave cannot be upgraded to a master at this time.
 .It no-mirror
 This disables the ability to use this filesystem as a mirroring source
 or target.  You can still do full scans with mirror-read but incremental
-scans will not work.
+scans will not work.  This option may only be set on masters.
 .It slave
 Sets slave mode, allowing the mirror to be used as a slave.  Except for
 the mirror-write directive all accesses to the mirror will be made read-only
 and will be as-of the
 .Ar sync_beg_tid .
+This option is currently not supported, slave mode must be specified
+when creating the PFS and cannot be changed on the fly.
 .It label=<string>
 Set a descriptive label for this filesystem.
 .El
@@ -316,8 +353,11 @@ A mirror-read can be piped into a mirror-dump to dump an ascii
 representation of the mirroring stream.
 .It Ar mirror-copy Ar [[user@]host:]filesystem Ar [[user@]host:]filesystem
 This is a shortcut which pipes a mirror-read command to a mirror-write
-command.  If a remote host specification is made the program forks an
+command.  If a remote host specification is made the program forks a
 ssh and execs the mirror-read and/or mirror-write on the appropriate host.
+.Pp
+This command also turns on the two-way protocol feature which automatically
+negotiates TID ranges without having to use a cycle file.
 .El
 .\".Sh EXAMPLES
 .Sh DIAGNOSTICS
index 8a685e1..d190ae9 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sbin/hammer/hammer.c,v 1.30 2008/07/07 00:27:22 dillon Exp $
+ * $DragonFly: src/sbin/hammer/hammer.c,v 1.31 2008/07/09 10:32:30 dillon Exp $
  */
 
 #include "hammer.h"
@@ -130,12 +130,16 @@ main(int ac, char **av)
                hammer_cmd_pseudofs_status(av + 1, ac - 1);
                exit(0);
        }
-       if (strcmp(av[0], "pfs-create") == 0) {
-               hammer_cmd_pseudofs_create(av + 1, ac - 1);
+       if (strcmp(av[0], "pfs-master") == 0) {
+               hammer_cmd_pseudofs_create(av + 1, ac - 1, 0);
+               exit(0);
+       }
+       if (strcmp(av[0], "pfs-slave") == 0) {
+               hammer_cmd_pseudofs_create(av + 1, ac - 1, 1);
                exit(0);
        }
        if (strcmp(av[0], "pfs-update") == 0) {
-               hammer_cmd_pseudofs_update(av + 1, ac - 1, 0);
+               hammer_cmd_pseudofs_update(av + 1, ac - 1);
                exit(0);
        }
        if (strcmp(av[0], "pfs-destroy") == 0) {
@@ -272,7 +276,8 @@ usage(int exit_code)
                "hammer reblock[-btree/inodes/dirs/data] "
                        "<filesystem> [pack%%]\n"
                "hammer pfs-status <dirpath>\n"
-               "hammer pfs-create <dirpath> [options]\n"
+               "hammer pfs-master <dirpath> [options]\n"
+               "hammer pfs-slave <dirpath> [options]\n"
                "hammer pfs-update <dirpath> [options]\n"
                "hammer history[@offset[,len]] <file-1>...<file-N>\n"
                "hammer -f blkdevs [-r] show\n"
index 066224c..1bb9f4e 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sbin/hammer/hammer.h,v 1.21 2008/07/07 00:27:22 dillon Exp $
+ * $DragonFly: src/sbin/hammer/hammer.h,v 1.22 2008/07/09 10:32:30 dillon Exp $
  */
 
 #include <sys/types.h>
@@ -82,8 +82,8 @@ void hammer_cmd_history(const char *offset_str, char **av, int ac);
 void hammer_cmd_blockmap(void);
 void hammer_cmd_reblock(char **av, int ac, int flags);
 void hammer_cmd_pseudofs_status(char **av, int ac);
-void hammer_cmd_pseudofs_create(char **av, int ac);
-void hammer_cmd_pseudofs_update(char **av, int ac, int doinit);
+void hammer_cmd_pseudofs_create(char **av, int ac, int is_slave);
+void hammer_cmd_pseudofs_update(char **av, int ac);
 void hammer_cmd_pseudofs_destroy(char **av, int ac);
 void hammer_cmd_status(char **av, int ac);
 void hammer_cmd_snapshot(char **av, int ac);
@@ -92,3 +92,5 @@ void hammer_get_cycle(hammer_base_elm_t base, hammer_tid_t *tidp);
 void hammer_set_cycle(hammer_base_elm_t base, hammer_tid_t tid);
 void hammer_reset_cycle(void);
 
+int getpfs(struct hammer_ioc_pseudofs_rw *pfs, const char *path);
+