Side-project feature request for 'hammer mirror-*' functions

Michael Neumann mneumann at ntecs.de
Fri Oct 10 08:54:37 PDT 2008


Michael Neumann wrote:
Matthew Dillon wrote:
    If someone has the time, this is a really simple feature request.
    Ok, yah, I could do it myself, but I'm going to offer it to others
    first and that might save me a little time :-)
    It's simple.  If you do a hammer mirror-copy or hammer mirror-stream
    to a target HAMMER filesystem the code checks that the target is a 
PFS
    slave with the same shared UUID as the master's UUID.

    I want a feature that asks the user whether he wants to create a
    conforming PFS on the target at that point, if the target directory
    does not exist, instead of exiting with an error.
    i.e. this would take away all the effort of having to create a 
pfs-slave
    and assign the correct UUID to it.  It takes about 60 seconds and 
some
    cutting and pasting to do that manually now... not long, but we can
    make it ultra convenient.

    You would simply run the command and it would ask if you wanted to 
create
    a new PFS on the target instead of exiting.  You would say 'yes', and
    poof, new mirror slave target :-).
Appended is a first patch. I'm unsure if this is the correct way to do
it, as the protocol is modified, and I think it's not easily possible to
read "yes" or "no" from the keyboard in mirror-write (when run via ssh).
Funny, when I run mirror-copy several times I get a panic (screenshot 
appended). I don't think this can be related to my changes...
This appended patch is even easier.

Regards,

  Michael

Index: cmd_mirror.c
===================================================================
RCS file: /home/dcvs/src/sbin/hammer/cmd_mirror.c,v
retrieving revision 1.15
diff -u -r1.15 cmd_mirror.c
--- cmd_mirror.c	9 Sep 2008 23:34:21 -0000	1.15
+++ cmd_mirror.c	10 Oct 2008 15:49:43 -0000
@@ -106,6 +106,11 @@
 	bwcount = 0;
 
 	/*
+	 * Send initial header for the purpose of determining shared-uuid.
+	 */
+	generate_mrec_header(fd, 1, pfs.pfs_id, NULL, NULL);
+
+	/*
 	 * 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.
@@ -298,6 +303,33 @@
 	fprintf(stderr, "Mirror-read %s succeeded\n", filesystem);
 }
 
+static void
+create_pfs(const char *filesystem, uuid_t *s_uuid)
+{
+	fprintf(stderr, "PFS slave %s does not exist. Do you want" 
+			" to create id? (yes|no) ", filesystem);
+	fflush(stderr);
+	/* XXX: How to read from keyboard? */
+
+	u_int32_t status;
+	char *shared_uuid = NULL;
+	uuid_to_string(s_uuid, &shared_uuid, &status);
+
+	char *cmd = NULL;
+	asprintf(&cmd, "/sbin/hammer pfs-slave '%s' shared-uuid=%s 1>&2",
+		 filesystem, shared_uuid); 
+	free(shared_uuid);
+
+	if (cmd == NULL) {
+		fprintf(stderr, "Failed to alloc memory\n");
+		exit(1);
+	}
+	if (system(cmd) != 0) {
+		fprintf(stderr, "Failed to create PFS\n");
+	}
+	free(cmd);
+}
+
 /*
  * Pipe the mirroring data stream on stdin to the HAMMER VFS, adding
  * some additional packet types to negotiate TID ranges and to verify
@@ -334,6 +366,7 @@
 	struct hammer_ioc_synctid synctid;
 	union hammer_ioc_mrecord_any mrec_tmp;
 	hammer_ioc_mrecord_any_t mrec;
+	struct stat st;
 	int error;
 	int fd;
 	int n;
@@ -351,6 +384,40 @@
 	hammer_key_end_init(&mirror.key_end);
 	mirror.key_end = mirror.key_beg;
 
+	/*
+	 * Read initial packet
+	 */
+	mrec = read_mrecord(0, &error, &pickup);
+	if (mrec == NULL) {
+		if (error == 0)
+			fprintf(stderr, "validate_mrec_header: short read\n");
+		exit(1);
+	}
+	/*
+	 * Validate packet
+	 */
+	if (mrec->head.type == HAMMER_MREC_TYPE_TERM) {
+		return;
+	}
+	if (mrec->head.type != HAMMER_MREC_TYPE_PFSD) {
+		fprintf(stderr, "validate_mrec_header: did not get expected "
+				"PFSD record type\n");
+		exit(1);
+	}
+	if (mrec->head.rec_size != sizeof(mrec->pfs)) {
+		fprintf(stderr, "validate_mrec_header: unexpected payload "
+				"size\n");
+		exit(1);
+	}
+
+	/*
+	 * Create slave PFS if it doesn't yet exist
+	 */
+	if (lstat(filesystem, &st) != 0) {
+		create_pfs(filesystem, &mrec->pfs.pfsd.shared_uuid);
+	}
+	free(mrec); mrec = NULL;
+
 	fd = getpfs(&pfs, filesystem);
 
 	/*




More information about the Kernel mailing list