HAMMER Utilities: Sync with 59A
[dragonfly.git] / sbin / hammer / cmd_mirror.c
blob5c3e5d224a1af5b80154ef2c509d9ab3d2ec7613
1 /*
2 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
16 * distribution.
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
32 * SUCH DAMAGE.
34 * $DragonFly: src/sbin/hammer/cmd_mirror.c,v 1.1 2008/06/26 04:07:57 dillon Exp $
37 #include "hammer.h"
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);
45 void
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);
51 int fd;
52 hammer_tid_t tid;
54 if (ac > 2)
55 mirror_usage(1);
56 filesystem = av[0];
57 tid = 0;
58 if (ac == 2)
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);
66 if (fd < 0)
67 err(1, "Unable to open %s", filesystem);
69 hammer_get_cycle(&mirror.key_beg);
71 mirror.ubuf = buf;
72 mirror.size = SERIALBUF_SIZE;
73 mirror.tid_beg = tid;
74 mirror.tid_end = HAMMER_MAX_TID;
76 do {
77 mirror.count = 0;
78 if (ioctl(fd, HAMMERIOC_MIRROR_READ, &mirror) < 0) {
79 fprintf(stderr, "Mirror-read %s failed: %s\n",
80 filesystem, strerror(errno));
81 exit(1);
83 if (mirror.head.flags & HAMMER_IOC_HEAD_INTR) {
84 fprintf(stderr,
85 "Mirror-read %s interrupted by timer at"
86 " %016llx %08x\n",
87 filesystem,
88 mirror.key_cur.obj_id,
89 mirror.key_cur.localization);
90 if (CyclePath)
91 hammer_set_cycle(&mirror.key_cur);
92 exit(0);
94 mirror.key_beg = mirror.key_cur;
95 if (mirror.count)
96 write(1, mirror.ubuf, mirror.count);
97 } while (mirror.count != 0);
99 if (CyclePath)
100 hammer_reset_cycle();
101 fprintf(stderr, "Mirror-read %s succeeded\n", filesystem);
104 void
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);
110 int fd;
111 struct hammer_ioc_mrecord pickup;
112 hammer_tid_t tid;
114 if (ac > 2)
115 mirror_usage(1);
116 filesystem = av[0];
117 tid = 0;
118 if (ac == 2)
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);
126 if (fd < 0)
127 err(1, "Unable to open %s", filesystem);
129 mirror.ubuf = buf;
130 mirror.size = SERIALBUF_SIZE;
131 mirror.tid_beg = tid;
132 mirror.tid_end = HAMMER_MAX_TID;
134 pickup.signature = 0;
136 for (;;) {
137 mirror.count = 0;
138 mirror.size = read_mrecords(0, buf, SERIALBUF_SIZE, &pickup);
139 if (mirror.size <= 0)
140 break;
141 if (ioctl(fd, HAMMERIOC_MIRROR_WRITE, &mirror) < 0) {
142 fprintf(stderr, "Mirror-write %s failed: %s\n",
143 filesystem, strerror(errno));
144 exit(1);
146 if (mirror.head.flags & HAMMER_IOC_HEAD_INTR) {
147 fprintf(stderr,
148 "Mirror-write %s interrupted by timer at"
149 " %016llx %08x\n",
150 filesystem,
151 mirror.key_cur.obj_id,
152 mirror.key_cur.localization);
153 exit(0);
155 mirror.key_beg = mirror.key_cur;
157 fprintf(stderr, "Mirror-write %s succeeded\n", filesystem);
160 void
161 hammer_cmd_mirror_copy(char **av, int ac)
165 static int
166 read_mrecords(int fd, char *buf, u_int size, hammer_ioc_mrecord_t pickup)
168 u_int count;
169 size_t n;
170 size_t i;
172 count = 0;
173 while (size - count >= HAMMER_MREC_HEADSIZE) {
175 * Cached the record header in case we run out of buffer
176 * space.
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);
182 if (i <= 0)
183 break;
185 if (n == 0)
186 break;
187 if (n != HAMMER_MREC_HEADSIZE) {
188 fprintf(stderr, "read_mrecords: short read on pipe\n");
189 exit(1);
192 if (pickup->signature != HAMMER_IOC_MIRROR_SIGNATURE) {
193 fprintf(stderr, "read_mrecords: malformed record on pipe, bad signature\n");
194 exit(1);
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");
198 exit(1);
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");
204 exit(1);
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");
208 exit(1);
212 * Stop if we have insufficient space for the record and data.
214 if (size - count < pickup->rec_size)
215 break;
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);
224 if (i <= 0)
225 break;
227 if (n != pickup->rec_size) {
228 fprintf(stderr, "read_mrecords: short read on pipe\n");
229 exit(1);
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;
240 return(count);
243 static void
244 mirror_usage(int code)
246 fprintf(stderr,
247 "hammer mirror-read <filesystem>\n"
248 "hammer mirror-write <filesystem>\n"
249 "hammer mirror-copy [[user@]host:]fs [[user@]host:]fs\n"
251 exit(code);