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"