12eccaef5STomohiro Kusumi /* 22eccaef5STomohiro Kusumi * Copyright (c) 2007-2016 The DragonFly Project. All rights reserved. 32eccaef5STomohiro Kusumi * 42eccaef5STomohiro Kusumi * This code is derived from software contributed to The DragonFly Project 52eccaef5STomohiro Kusumi * by Matthew Dillon <dillon@backplane.com> 62eccaef5STomohiro Kusumi * 72eccaef5STomohiro Kusumi * Redistribution and use in source and binary forms, with or without 82eccaef5STomohiro Kusumi * modification, are permitted provided that the following conditions 92eccaef5STomohiro Kusumi * are met: 102eccaef5STomohiro Kusumi * 112eccaef5STomohiro Kusumi * 1. Redistributions of source code must retain the above copyright 122eccaef5STomohiro Kusumi * notice, this list of conditions and the following disclaimer. 132eccaef5STomohiro Kusumi * 2. Redistributions in binary form must reproduce the above copyright 142eccaef5STomohiro Kusumi * notice, this list of conditions and the following disclaimer in 152eccaef5STomohiro Kusumi * the documentation and/or other materials provided with the 162eccaef5STomohiro Kusumi * distribution. 172eccaef5STomohiro Kusumi * 3. Neither the name of The DragonFly Project nor the names of its 182eccaef5STomohiro Kusumi * contributors may be used to endorse or promote products derived 192eccaef5STomohiro Kusumi * from this software without specific, prior written permission. 202eccaef5STomohiro Kusumi * 212eccaef5STomohiro Kusumi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 222eccaef5STomohiro Kusumi * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 232eccaef5STomohiro Kusumi * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 242eccaef5STomohiro Kusumi * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 252eccaef5STomohiro Kusumi * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 262eccaef5STomohiro Kusumi * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 272eccaef5STomohiro Kusumi * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 282eccaef5STomohiro Kusumi * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 292eccaef5STomohiro Kusumi * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 302eccaef5STomohiro Kusumi * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 312eccaef5STomohiro Kusumi * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 322eccaef5STomohiro Kusumi * SUCH DAMAGE. 332eccaef5STomohiro Kusumi */ 342eccaef5STomohiro Kusumi 352eccaef5STomohiro Kusumi #include "hammer.h" 362eccaef5STomohiro Kusumi 372eccaef5STomohiro Kusumi static void hammer_strip_bigblock(int zone, hammer_off_t offset); 382eccaef5STomohiro Kusumi static void hammer_ask_yn(void); 392eccaef5STomohiro Kusumi 402eccaef5STomohiro Kusumi void 412eccaef5STomohiro Kusumi hammer_cmd_strip(void) 422eccaef5STomohiro Kusumi { 43*5ebff42aSTomohiro Kusumi struct volume_info *volume; 442eccaef5STomohiro Kusumi hammer_blockmap_t rootmap; 452eccaef5STomohiro Kusumi hammer_blockmap_layer1_t layer1; 462eccaef5STomohiro Kusumi hammer_blockmap_layer2_t layer2; 472eccaef5STomohiro Kusumi struct buffer_info *buffer1 = NULL; 482eccaef5STomohiro Kusumi struct buffer_info *buffer2 = NULL; 492eccaef5STomohiro Kusumi hammer_off_t layer1_offset; 502eccaef5STomohiro Kusumi hammer_off_t layer2_offset; 512eccaef5STomohiro Kusumi hammer_off_t phys_offset; 522eccaef5STomohiro Kusumi hammer_off_t block_offset; 532eccaef5STomohiro Kusumi hammer_off_t offset; 542eccaef5STomohiro Kusumi int i, zone = HAMMER_ZONE_FREEMAP_INDEX; 552eccaef5STomohiro Kusumi 562eccaef5STomohiro Kusumi hammer_ask_yn(); 572eccaef5STomohiro Kusumi 58*5ebff42aSTomohiro Kusumi volume = get_root_volume(); 59*5ebff42aSTomohiro Kusumi rootmap = &volume->ondisk->vol0_blockmap[zone]; 602eccaef5STomohiro Kusumi assert(rootmap->phys_offset != 0); 612eccaef5STomohiro Kusumi 622eccaef5STomohiro Kusumi for (phys_offset = HAMMER_ZONE_ENCODE(zone, 0); 632eccaef5STomohiro Kusumi phys_offset < HAMMER_ZONE_ENCODE(zone, HAMMER_OFF_LONG_MASK); 642eccaef5STomohiro Kusumi phys_offset += HAMMER_BLOCKMAP_LAYER2) { 652eccaef5STomohiro Kusumi /* 662eccaef5STomohiro Kusumi * Dive layer 1. 672eccaef5STomohiro Kusumi */ 682eccaef5STomohiro Kusumi layer1_offset = rootmap->phys_offset + 692eccaef5STomohiro Kusumi HAMMER_BLOCKMAP_LAYER1_OFFSET(phys_offset); 702eccaef5STomohiro Kusumi layer1 = get_buffer_data(layer1_offset, &buffer1, 0); 712eccaef5STomohiro Kusumi 722eccaef5STomohiro Kusumi if (layer1->phys_offset == HAMMER_BLOCKMAP_UNAVAIL) 732eccaef5STomohiro Kusumi continue; 742eccaef5STomohiro Kusumi 752eccaef5STomohiro Kusumi for (block_offset = 0; 762eccaef5STomohiro Kusumi block_offset < HAMMER_BLOCKMAP_LAYER2; 772eccaef5STomohiro Kusumi block_offset += HAMMER_BIGBLOCK_SIZE) { 782eccaef5STomohiro Kusumi offset = phys_offset + block_offset; 792eccaef5STomohiro Kusumi /* 802eccaef5STomohiro Kusumi * Dive layer 2, each entry represents a big-block. 812eccaef5STomohiro Kusumi */ 822eccaef5STomohiro Kusumi layer2_offset = layer1->phys_offset + 832eccaef5STomohiro Kusumi HAMMER_BLOCKMAP_LAYER2_OFFSET(block_offset); 842eccaef5STomohiro Kusumi layer2 = get_buffer_data(layer2_offset, &buffer2, 0); 852eccaef5STomohiro Kusumi 862eccaef5STomohiro Kusumi if (layer2->zone == HAMMER_ZONE_BTREE_INDEX || 872eccaef5STomohiro Kusumi layer2->zone == HAMMER_ZONE_META_INDEX) { 882eccaef5STomohiro Kusumi hammer_strip_bigblock(layer2->zone, offset); 892eccaef5STomohiro Kusumi layer2->zone = HAMMER_ZONE_UNAVAIL_INDEX; 902eccaef5STomohiro Kusumi layer2->append_off = HAMMER_BIGBLOCK_SIZE; 912eccaef5STomohiro Kusumi layer2->bytes_free = 0; 922eccaef5STomohiro Kusumi hammer_crc_set_layer2(layer2); 932eccaef5STomohiro Kusumi buffer2->cache.modified = 1; 942eccaef5STomohiro Kusumi } else if (layer2->zone == HAMMER_ZONE_UNAVAIL_INDEX) { 952eccaef5STomohiro Kusumi break; 962eccaef5STomohiro Kusumi } 972eccaef5STomohiro Kusumi } 982eccaef5STomohiro Kusumi } 992eccaef5STomohiro Kusumi rel_buffer(buffer1); 1002eccaef5STomohiro Kusumi rel_buffer(buffer2); 1012eccaef5STomohiro Kusumi 1022eccaef5STomohiro Kusumi for (i = 0; i < HAMMER_MAX_VOLUMES; i++) { 103*5ebff42aSTomohiro Kusumi volume = get_volume(i); 104*5ebff42aSTomohiro Kusumi if (volume) { 105*5ebff42aSTomohiro Kusumi printf("%s\n", volume->name); 106*5ebff42aSTomohiro Kusumi bzero(volume->ondisk, sizeof(*volume->ondisk)); 107*5ebff42aSTomohiro Kusumi memcpy(&volume->ondisk->vol_signature, "STRIPPED", 8); 1082eccaef5STomohiro Kusumi } 1092eccaef5STomohiro Kusumi } 1102eccaef5STomohiro Kusumi 1112eccaef5STomohiro Kusumi flush_all_volumes(); 1122eccaef5STomohiro Kusumi } 1132eccaef5STomohiro Kusumi 1142eccaef5STomohiro Kusumi static void 1152eccaef5STomohiro Kusumi hammer_strip_bigblock(int zone, hammer_off_t offset) 1162eccaef5STomohiro Kusumi { 1172eccaef5STomohiro Kusumi struct buffer_info *buffer = NULL; 1182eccaef5STomohiro Kusumi int i; 1192eccaef5STomohiro Kusumi 120f6d29b27STomohiro Kusumi assert(hammer_is_index_record(zone)); 1212eccaef5STomohiro Kusumi assert((offset & HAMMER_BIGBLOCK_MASK64) == 0); 1222eccaef5STomohiro Kusumi assert((offset & HAMMER_BUFMASK) == 0); 1232eccaef5STomohiro Kusumi offset = hammer_xlate_to_zoneX(zone, offset); 1242eccaef5STomohiro Kusumi 1252eccaef5STomohiro Kusumi /* 1262eccaef5STomohiro Kusumi * This format is taken from hammer blockmap. 1272eccaef5STomohiro Kusumi */ 1282eccaef5STomohiro Kusumi if (VerboseOpt) { 1292eccaef5STomohiro Kusumi printf("%016jx zone=%-2d vol=%-3d L1#=%-6d L2#=%-6d L1=%-7lu L2=%-7lu\n", 1302eccaef5STomohiro Kusumi offset, 1312eccaef5STomohiro Kusumi zone, 1322eccaef5STomohiro Kusumi HAMMER_VOL_DECODE(offset), 1332eccaef5STomohiro Kusumi HAMMER_BLOCKMAP_LAYER1_INDEX(offset), 1342eccaef5STomohiro Kusumi HAMMER_BLOCKMAP_LAYER2_INDEX(offset), 1352eccaef5STomohiro Kusumi HAMMER_BLOCKMAP_LAYER1_OFFSET(offset), 1362eccaef5STomohiro Kusumi HAMMER_BLOCKMAP_LAYER2_OFFSET(offset)); 1372eccaef5STomohiro Kusumi } else { 1382eccaef5STomohiro Kusumi printf("%016jx\n", offset); 1392eccaef5STomohiro Kusumi } 1402eccaef5STomohiro Kusumi 1412eccaef5STomohiro Kusumi for (i = 0; i < HAMMER_BIGBLOCK_SIZE; i += HAMMER_BUFSIZE) { 1422eccaef5STomohiro Kusumi get_buffer_data(offset + i, &buffer, 1); 1432eccaef5STomohiro Kusumi assert(buffer); 1442eccaef5STomohiro Kusumi } 1452eccaef5STomohiro Kusumi } 1462eccaef5STomohiro Kusumi 1472eccaef5STomohiro Kusumi static void 1482eccaef5STomohiro Kusumi hammer_ask_yn(void) 1492eccaef5STomohiro Kusumi { 150*5ebff42aSTomohiro Kusumi struct volume_info *volume; 1512eccaef5STomohiro Kusumi int i; 1522eccaef5STomohiro Kusumi 153*5ebff42aSTomohiro Kusumi volume = get_root_volume(); 1542eccaef5STomohiro Kusumi 1552eccaef5STomohiro Kusumi /* 1562eccaef5STomohiro Kusumi * This format is taken from hammer pfs-destroy. 1572eccaef5STomohiro Kusumi */ 1582eccaef5STomohiro Kusumi printf("You have requested that HAMMER filesystem (%s) be stripped\n", 159*5ebff42aSTomohiro Kusumi volume->ondisk->vol_label); 1602eccaef5STomohiro Kusumi printf("Do you really want to do this? [y/n] "); 1612eccaef5STomohiro Kusumi fflush(stdout); 1622eccaef5STomohiro Kusumi 16302318f07STomohiro Kusumi if (getyn() == 0) 16402318f07STomohiro Kusumi errx(1, "No action taken"); 1652eccaef5STomohiro Kusumi 166*5ebff42aSTomohiro Kusumi printf("Stripping HAMMER filesystem (%s)", volume->ondisk->vol_label); 1672eccaef5STomohiro Kusumi 1682eccaef5STomohiro Kusumi if (DebugOpt) { 1692eccaef5STomohiro Kusumi printf("\n"); 1702eccaef5STomohiro Kusumi } else { 1712eccaef5STomohiro Kusumi printf(" in"); 1722eccaef5STomohiro Kusumi for (i = 5; i; --i) { 1732eccaef5STomohiro Kusumi printf(" %d", i); 1742eccaef5STomohiro Kusumi fflush(stdout); 1752eccaef5STomohiro Kusumi sleep(1); 1762eccaef5STomohiro Kusumi } 1772eccaef5STomohiro Kusumi printf(".. starting destruction pass\n"); 1782eccaef5STomohiro Kusumi } 1792eccaef5STomohiro Kusumi } 180