2 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/sbin/hammer/cmd_mirror.c,v 1.1 2008/06/26 04:07:57 dillon Exp $
39 #define SERIALBUF_SIZE (512 * 1024)
41 static int read_mrecords(int fd, char *buf, u_int size,
42 hammer_ioc_mrecord_t pickup);
43 static void mirror_usage(int code);
46 hammer_cmd_mirror_read(char **av, int ac)
48 struct hammer_ioc_mirror_rw mirror;
49 const char *filesystem;
50 char *buf = malloc(SERIALBUF_SIZE);
59 tid = strtoull(av[1], NULL, 0);
61 bzero(&mirror, sizeof(mirror));
62 hammer_key_beg_init(&mirror.key_beg);
63 hammer_key_end_init(&mirror.key_end);
65 fd = open(filesystem, O_RDONLY);
67 err(1, "Unable to open %s", filesystem);
69 hammer_get_cycle(&mirror.key_beg);
72 mirror.size = SERIALBUF_SIZE;
74 mirror.tid_end = HAMMER_MAX_TID;
78 if (ioctl(fd, HAMMERIOC_MIRROR_READ, &mirror) < 0) {
79 fprintf(stderr, "Mirror-read %s failed: %s\n",
80 filesystem, strerror(errno));
83 if (mirror.head.flags & HAMMER_IOC_HEAD_INTR) {
85 "Mirror-read %s interrupted by timer at"
88 mirror.key_cur.obj_id,
89 mirror.key_cur.localization);
91 hammer_set_cycle(&mirror.key_cur);
94 mirror.key_beg = mirror.key_cur;
96 write(1, mirror.ubuf, mirror.count);
97 } while (mirror.count != 0);
100 hammer_reset_cycle();
101 fprintf(stderr, "Mirror-read %s succeeded\n", filesystem);
105 hammer_cmd_mirror_write(char **av, int ac)
107 struct hammer_ioc_mirror_rw mirror;
108 const char *filesystem;
109 char *buf = malloc(SERIALBUF_SIZE);
111 struct hammer_ioc_mrecord pickup;
119 tid = strtoull(av[1], NULL, 0);
121 bzero(&mirror, sizeof(mirror));
122 hammer_key_beg_init(&mirror.key_beg);
123 hammer_key_end_init(&mirror.key_end);
125 fd = open(filesystem, O_RDONLY);
127 err(1, "Unable to open %s", filesystem);
130 mirror.size = SERIALBUF_SIZE;
131 mirror.tid_beg = tid;
132 mirror.tid_end = HAMMER_MAX_TID;
134 pickup.signature = 0;
138 mirror.size = read_mrecords(0, buf, SERIALBUF_SIZE, &pickup);
139 if (mirror.size <= 0)
141 if (ioctl(fd, HAMMERIOC_MIRROR_WRITE, &mirror) < 0) {
142 fprintf(stderr, "Mirror-write %s failed: %s\n",
143 filesystem, strerror(errno));
146 if (mirror.head.flags & HAMMER_IOC_HEAD_INTR) {
148 "Mirror-write %s interrupted by timer at"
151 mirror.key_cur.obj_id,
152 mirror.key_cur.localization);
155 mirror.key_beg = mirror.key_cur;
157 fprintf(stderr, "Mirror-write %s succeeded\n", filesystem);
161 hammer_cmd_mirror_copy(char **av, int ac)
166 read_mrecords(int fd, char *buf, u_int size, hammer_ioc_mrecord_t pickup)
173 while (size - count >= HAMMER_MREC_HEADSIZE) {
175 * Cached the record header in case we run out of buffer
178 if (pickup->signature == 0) {
179 for (n = 0; n < HAMMER_MREC_HEADSIZE; n += i) {
180 i = read(fd, (char *)pickup + n,
181 HAMMER_MREC_HEADSIZE - n);
187 if (n != HAMMER_MREC_HEADSIZE) {
188 fprintf(stderr, "read_mrecords: short read on pipe\n");
192 if (pickup->signature != HAMMER_IOC_MIRROR_SIGNATURE) {
193 fprintf(stderr, "read_mrecords: malformed record on pipe, bad signature\n");
196 if (pickup->rec_crc != crc32((char *)pickup + HAMMER_MREC_CRCOFF, HAMMER_MREC_HEADSIZE - HAMMER_MREC_CRCOFF)) {
197 fprintf(stderr, "read_mrecords: malformed record on pipe, bad crc\n");
201 if (pickup->rec_size < HAMMER_MREC_HEADSIZE ||
202 pickup->rec_size > HAMMER_MREC_HEADSIZE + HAMMER_XBUFSIZE) {
203 fprintf(stderr, "read_mrecords: malformed record on pipe, illegal rec_size\n");
206 if (HAMMER_MREC_HEADSIZE + pickup->leaf.data_len > pickup->rec_size) {
207 fprintf(stderr, "read_mrecords: malformed record on pipe, illegal element data_len\n");
212 * Stop if we have insufficient space for the record and data.
214 if (size - count < pickup->rec_size)
218 * Read the remainder and clear the pickup signature.
220 bcopy(pickup, buf + count, HAMMER_MREC_HEADSIZE);
221 pickup->signature = 0;
222 for (n = HAMMER_MREC_HEADSIZE; n < pickup->rec_size; n += i) {
223 i = read(fd, buf + count + n, pickup->rec_size - n);
227 if (n != pickup->rec_size) {
228 fprintf(stderr, "read_mrecords: short read on pipe\n");
231 if (pickup->leaf.data_len && pickup->leaf.data_offset) {
232 if (hammer_crc_test_leaf(buf + count + HAMMER_MREC_HEADSIZE, &pickup->leaf) == 0) {
233 fprintf(stderr, "read_mrecords: data_crc did not match data! obj=%016llx key=%016llx\n", pickup->leaf.base.obj_id, pickup->leaf.base.key);
234 fprintf(stderr, "continuing, but there are problems\n");
238 count += pickup->rec_size;
244 mirror_usage(int code)
247 "hammer mirror-read <filesystem>\n"
248 "hammer mirror-write <filesystem>\n"
249 "hammer mirror-copy [[user@]host:]fs [[user@]host:]fs\n"