1 /* 2 * Copyright (c) 2007-2016 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: 10 * 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. 20 * 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. 33 */ 34 35 #include "hammer.h" 36 37 static void hammer_strip_bigblock(int zone, hammer_off_t offset); 38 static void hammer_ask_yn(void); 39 40 void 41 hammer_cmd_strip(void) 42 { 43 struct volume_info *volume; 44 hammer_blockmap_t rootmap; 45 hammer_blockmap_layer1_t layer1; 46 hammer_blockmap_layer2_t layer2; 47 struct buffer_info *buffer1 = NULL; 48 struct buffer_info *buffer2 = NULL; 49 hammer_off_t layer1_offset; 50 hammer_off_t layer2_offset; 51 hammer_off_t phys_offset; 52 hammer_off_t block_offset; 53 hammer_off_t offset; 54 int i, zone = HAMMER_ZONE_FREEMAP_INDEX; 55 56 hammer_ask_yn(); 57 58 volume = get_root_volume(); 59 rootmap = &volume->ondisk->vol0_blockmap[zone]; 60 assert(rootmap->phys_offset != 0); 61 62 for (phys_offset = HAMMER_ZONE_ENCODE(zone, 0); 63 phys_offset < HAMMER_ZONE_ENCODE(zone, HAMMER_OFF_LONG_MASK); 64 phys_offset += HAMMER_BLOCKMAP_LAYER2) { 65 /* 66 * Dive layer 1. 67 */ 68 layer1_offset = rootmap->phys_offset + 69 HAMMER_BLOCKMAP_LAYER1_OFFSET(phys_offset); 70 layer1 = get_buffer_data(layer1_offset, &buffer1, 0); 71 72 if (layer1->phys_offset == HAMMER_BLOCKMAP_UNAVAIL) 73 continue; 74 75 for (block_offset = 0; 76 block_offset < HAMMER_BLOCKMAP_LAYER2; 77 block_offset += HAMMER_BIGBLOCK_SIZE) { 78 offset = phys_offset + block_offset; 79 /* 80 * Dive layer 2, each entry represents a big-block. 81 */ 82 layer2_offset = layer1->phys_offset + 83 HAMMER_BLOCKMAP_LAYER2_OFFSET(block_offset); 84 layer2 = get_buffer_data(layer2_offset, &buffer2, 0); 85 86 if (layer2->zone == HAMMER_ZONE_BTREE_INDEX || 87 layer2->zone == HAMMER_ZONE_META_INDEX) { 88 hammer_strip_bigblock(layer2->zone, offset); 89 layer2->zone = HAMMER_ZONE_UNAVAIL_INDEX; 90 layer2->append_off = HAMMER_BIGBLOCK_SIZE; 91 layer2->bytes_free = 0; 92 hammer_crc_set_layer2(layer2); 93 buffer2->cache.modified = 1; 94 } else if (layer2->zone == HAMMER_ZONE_UNAVAIL_INDEX) { 95 break; 96 } 97 } 98 } 99 rel_buffer(buffer1); 100 rel_buffer(buffer2); 101 102 for (i = 0; i < HAMMER_MAX_VOLUMES; i++) { 103 volume = get_volume(i); 104 if (volume) { 105 printf("%s\n", volume->name); 106 bzero(volume->ondisk, sizeof(*volume->ondisk)); 107 memcpy(&volume->ondisk->vol_signature, "STRIPPED", 8); 108 } 109 } 110 111 flush_all_volumes(); 112 } 113 114 static void 115 hammer_strip_bigblock(int zone, hammer_off_t offset) 116 { 117 struct buffer_info *buffer = NULL; 118 int i; 119 120 assert(hammer_is_index_record(zone)); 121 assert((offset & HAMMER_BIGBLOCK_MASK64) == 0); 122 assert((offset & HAMMER_BUFMASK) == 0); 123 offset = hammer_xlate_to_zoneX(zone, offset); 124 125 /* 126 * This format is taken from hammer blockmap. 127 */ 128 if (VerboseOpt) { 129 printf("%016jx zone=%-2d vol=%-3d L1#=%-6d L2#=%-6d L1=%-7lu L2=%-7lu\n", 130 offset, 131 zone, 132 HAMMER_VOL_DECODE(offset), 133 HAMMER_BLOCKMAP_LAYER1_INDEX(offset), 134 HAMMER_BLOCKMAP_LAYER2_INDEX(offset), 135 HAMMER_BLOCKMAP_LAYER1_OFFSET(offset), 136 HAMMER_BLOCKMAP_LAYER2_OFFSET(offset)); 137 } else { 138 printf("%016jx\n", offset); 139 } 140 141 for (i = 0; i < HAMMER_BIGBLOCK_SIZE; i += HAMMER_BUFSIZE) { 142 get_buffer_data(offset + i, &buffer, 1); 143 assert(buffer); 144 } 145 } 146 147 static void 148 hammer_ask_yn(void) 149 { 150 struct volume_info *volume; 151 int i; 152 153 volume = get_root_volume(); 154 155 /* 156 * This format is taken from hammer pfs-destroy. 157 */ 158 printf("You have requested that HAMMER filesystem (%s) be stripped\n", 159 volume->ondisk->vol_label); 160 printf("Do you really want to do this? [y/n] "); 161 fflush(stdout); 162 163 if (getyn() == 0) 164 errx(1, "No action taken"); 165 166 printf("Stripping HAMMER filesystem (%s)", volume->ondisk->vol_label); 167 168 if (DebugOpt) { 169 printf("\n"); 170 } else { 171 printf(" in"); 172 for (i = 5; i; --i) { 173 printf(" %d", i); 174 fflush(stdout); 175 sleep(1); 176 } 177 printf(".. starting destruction pass\n"); 178 } 179 } 180