2 * Copyright (c) 2007-2016 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
37 static int hammer_test_offset(const char *msg
, hammer_off_t offset
);
38 static void hammer_strip_bigblock(int zone
, hammer_off_t offset
);
39 static void hammer_ask_yn(void);
42 hammer_cmd_strip(void)
45 hammer_blockmap_t rootmap
;
46 hammer_blockmap_layer1_t layer1
;
47 hammer_blockmap_layer2_t layer2
;
48 buffer_info_t buffer1
= NULL
;
49 buffer_info_t buffer2
= NULL
;
50 hammer_off_t layer1_offset
;
51 hammer_off_t layer2_offset
;
52 hammer_off_t phys_offset
;
53 hammer_off_t block_offset
;
55 int i
, zone
= HAMMER_ZONE_FREEMAP_INDEX
;
59 volume
= get_root_volume();
61 printf("No root volume found\n");
65 rootmap
= &volume
->ondisk
->vol0_blockmap
[zone
];
66 if (!hammer_test_offset("layer1 physical", rootmap
->phys_offset
))
69 for (phys_offset
= HAMMER_ZONE_ENCODE(zone
, 0);
70 phys_offset
< HAMMER_ZONE_ENCODE(zone
, HAMMER_OFF_LONG_MASK
);
71 phys_offset
+= HAMMER_BLOCKMAP_LAYER2
) {
75 layer1_offset
= rootmap
->phys_offset
+
76 HAMMER_BLOCKMAP_LAYER1_OFFSET(phys_offset
);
77 if (!hammer_test_offset("layer1", layer1_offset
))
79 layer1
= get_buffer_data(layer1_offset
, &buffer1
, 0);
81 if (layer1
->phys_offset
== HAMMER_BLOCKMAP_UNAVAIL
)
84 for (block_offset
= 0;
85 block_offset
< HAMMER_BLOCKMAP_LAYER2
;
86 block_offset
+= HAMMER_BIGBLOCK_SIZE
) {
87 offset
= phys_offset
+ block_offset
;
89 * Dive layer 2, each entry represents a big-block.
91 layer2_offset
= layer1
->phys_offset
+
92 HAMMER_BLOCKMAP_LAYER2_OFFSET(block_offset
);
93 if (!hammer_test_offset("layer2", layer2_offset
))
95 layer2
= get_buffer_data(layer2_offset
, &buffer2
, 0);
97 if (layer2
->zone
== HAMMER_ZONE_BTREE_INDEX
||
98 layer2
->zone
== HAMMER_ZONE_META_INDEX
) {
99 hammer_strip_bigblock(layer2
->zone
, offset
);
100 layer2
->zone
= HAMMER_ZONE_UNAVAIL_INDEX
;
101 layer2
->append_off
= HAMMER_BIGBLOCK_SIZE
;
102 layer2
->bytes_free
= 0;
103 hammer_crc_set_layer2(HammerVersion
, layer2
);
104 buffer2
->cache
.modified
= 1;
105 } else if (layer2
->zone
== HAMMER_ZONE_UNAVAIL_INDEX
) {
114 for (i
= 0; i
< HAMMER_MAX_VOLUMES
; i
++) {
115 volume
= get_volume(i
);
117 bzero(volume
->ondisk
, sizeof(*volume
->ondisk
));
118 memcpy(&volume
->ondisk
->vol_signature
, "STRIPPED", 8);
119 printf("Stripped volume header %s\n", volume
->name
);
128 hammer_test_offset(const char *msg
, hammer_off_t offset
)
130 if (get_volume(HAMMER_VOL_DECODE(offset
)) == NULL
) {
131 printf("Invalid volume# %d\n", HAMMER_VOL_DECODE(offset
));
134 if (!hammer_is_zone_raw_buffer(offset
)) {
135 printf("Invalid %s offset 0x%jx\n", msg
, offset
);
144 hammer_strip_bigblock(int zone
, hammer_off_t offset
)
146 buffer_info_t buffer
= NULL
;
149 assert(hammer_is_index_record(zone
));
150 assert((offset
& HAMMER_BIGBLOCK_MASK64
) == 0);
151 assert((offset
& HAMMER_BUFMASK
) == 0);
152 offset
= hammer_xlate_to_zoneX(zone
, offset
);
155 * This format is taken from hammer blockmap.
157 printf("Stripped big-block ");
159 printf("%016jx zone=%-2d vol=%-3d L1#=%-6d L2#=%-6d L1=%-7lu L2=%-7lu\n",
162 HAMMER_VOL_DECODE(offset
),
163 HAMMER_BLOCKMAP_LAYER1_INDEX(offset
),
164 HAMMER_BLOCKMAP_LAYER2_INDEX(offset
),
165 HAMMER_BLOCKMAP_LAYER1_OFFSET(offset
),
166 HAMMER_BLOCKMAP_LAYER2_OFFSET(offset
));
168 printf("%016jx\n", offset
);
171 for (i
= 0; i
< HAMMER_BIGBLOCK_SIZE
; i
+= HAMMER_BUFSIZE
) {
172 get_buffer_data(offset
+ i
, &buffer
, 1);
181 volume_info_t volume
;
182 #define _HAMMER "HAMMER filesystem"
187 volume
= get_root_volume();
189 if (volume
&& volume
->ondisk
->vol_signature
== HAMMER_FSBUF_VOLUME
)
190 strcpy(type
, _HAMMER
);
192 strcpy(type
, "devices");
194 if (volume
&& volume
->ondisk
->vol_label
[0]) {
195 snprintf(label
, sizeof(label
), " (%s)",
196 volume
->ondisk
->vol_label
);
202 * This format is taken from hammer pfs-destroy.
204 printf("You have requested that %s%s be stripped", type
, label
);
205 if (strcmp(type
, _HAMMER
))
206 printf(", but %s may not be %s volumes\n", type
, _HAMMER
);
210 printf("Do you really want to do this? [y/n] ");
213 errx(1, "No action taken");
217 if (strcmp(type
, _HAMMER
)) {
218 printf("Are you absolutely sure you want to do this? [y/n] ");
221 errx(1, "No action taken");
226 printf("Stripping %s%s", type
, label
);
232 for (i
= 5; i
; --i
) {
237 printf(".. starting destruction pass\n");