1/* $NetBSD: wapbl.c,v 1.4 2009/09/13 14:25:28 bouyer Exp $ */ 2 3/*- 4 * Copyright (c) 2005,2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* This file contains fsck support for wapbl 33 */ 34#define WAPBL_INTERNAL 35 36#include <sys/cdefs.h> 37__KERNEL_RCSID(0, "$NetBSD: wapbl.c,v 1.4 2009/09/13 14:25:28 bouyer Exp $"); 38 39#include <sys/stat.h> 40#include <sys/time.h> 41#include <sys/uio.h> 42 43#include <assert.h> 44#include <errno.h> 45#include <inttypes.h> 46#include <stdio.h> 47#include <stdbool.h> 48#include <stdlib.h> 49#include <string.h> 50#include <unistd.h> 51 52#include <ufs/ufs/dinode.h> 53#include <ufs/ufs/dir.h> 54#include <ufs/ufs/ufs_bswap.h> 55#include <ufs/ufs/ufs_wapbl.h> 56#include <ufs/ffs/fs.h> 57#include <ufs/ffs/ffs_extern.h> 58 59#include <sys/wapbl.h> 60 61#include "fsck.h" 62#include "fsutil.h" 63#include "extern.h" 64#include "exitvalues.h" 65 66int 67wapbl_write(void *data, size_t len, struct vnode *devvp, daddr_t pbn) 68{ 69 70 WAPBL_PRINTF(WAPBL_PRINT_IO, 71 ("wapbl_write: %zd bytes at block %"PRId64" on fd 0x%x\n", 72 len, pbn, fswritefd)); 73 bwrite(fswritefd, data, pbn, len); 74 return 0; 75} 76 77int 78wapbl_read(void *data, size_t len, struct vnode *devvp, daddr_t pbn) 79{ 80 81 WAPBL_PRINTF(WAPBL_PRINT_IO, 82 ("wapbl_read: %zd bytes at block %"PRId64" on fd 0x%x\n", 83 len, pbn, fsreadfd)); 84 bread(fsreadfd, data, pbn, len); 85 return 0; 86} 87 88struct wapbl_replay *wapbl_replay; 89 90void 91replay_wapbl(void) 92{ 93 int error; 94 95 if (!nflag) { 96 error = wapbl_replay_write(wapbl_replay, 0); 97 if (error) { 98 pfatal("UNABLE TO REPLAY JOURNAL BLOCKS"); 99 if (reply("CONTINUE") == 0) { 100 exit(FSCK_EXIT_CHECK_FAILED); 101 } 102 } else { 103 wapbl_replay_stop(wapbl_replay); 104 } 105 } 106 { 107 int i; 108 for (i = 0; i < wapbl_replay->wr_inodescnt; i++) { 109 WAPBL_PRINTF(WAPBL_PRINT_REPLAY,("wapbl_replay: " 110 "not cleaning inode %"PRIu32" mode %"PRIo32"\n", 111 wapbl_replay->wr_inodes[i].wr_inumber, 112 wapbl_replay->wr_inodes[i].wr_imode)); 113 } 114 } 115} 116 117void 118cleanup_wapbl(void) 119{ 120 121 if (wapbl_replay) { 122 if (wapbl_replay_isopen(wapbl_replay)) 123 wapbl_replay_stop(wapbl_replay); 124 wapbl_replay_free(wapbl_replay); 125 wapbl_replay = 0; 126 } 127} 128 129int 130read_wapbl(char *buf, long size, daddr_t blk) 131{ 132 133 if (!wapbl_replay || !wapbl_replay_isopen(wapbl_replay)) 134 return 0; 135 return wapbl_replay_read(wapbl_replay, buf, blk, size); 136} 137 138int 139is_journal_inode(ino_t ino) 140{ 141 union dinode *dp; 142 143 dp = ginode(ino); 144 if ((iswap32(DIP(dp, flags)) & SF_LOG) != 0 && 145 sblock->fs_journal_version == UFS_WAPBL_VERSION && 146 sblock->fs_journal_location == UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM && 147 sblock->fs_journallocs[UFS_WAPBL_INFS_INO] == ino) 148 return 1; 149 150 return 0; 151} 152 153int 154check_wapbl(void) 155{ 156 uint64_t addr = 0, count = 0, blksize = 0; 157 int error; 158 int ret = 0; 159 if (debug) 160 wapbl_debug_print = WAPBL_PRINT_ERROR | WAPBL_PRINT_REPLAY; 161 if (debug > 1) 162 wapbl_debug_print |= WAPBL_PRINT_IO; 163 164 if (sblock->fs_flags & FS_DOWAPBL) { 165 if (sblock->fs_journal_version != UFS_WAPBL_VERSION) { 166 pfatal("INVALID JOURNAL VERSION %d", 167 sblock->fs_journal_version); 168 if (reply("CONTINUE") == 0) { 169 exit(FSCK_EXIT_CHECK_FAILED); 170 } 171 pwarn("CLEARING EXISTING JOURNAL\n"); 172 sblock->fs_flags &= ~FS_DOWAPBL; 173 sblock->fs_journal_flags = UFS_WAPBL_FLAGS_CLEAR_LOG; 174 sbdirty(); 175 ret = FSCK_EXIT_CHECK_FAILED; 176 } else { 177 switch(sblock->fs_journal_location) { 178 case UFS_WAPBL_JOURNALLOC_END_PARTITION: 179 addr = 180 sblock->fs_journallocs[UFS_WAPBL_EPART_ADDR]; 181 count = 182 sblock->fs_journallocs[UFS_WAPBL_EPART_COUNT]; 183 blksize = 184 sblock->fs_journallocs[UFS_WAPBL_EPART_BLKSZ]; 185 break; 186 case UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM: 187 addr = 188 sblock->fs_journallocs[UFS_WAPBL_INFS_ADDR]; 189 count = 190 sblock->fs_journallocs[UFS_WAPBL_INFS_COUNT]; 191 blksize = 192 sblock->fs_journallocs[UFS_WAPBL_INFS_BLKSZ]; 193 break; 194 default: 195 pfatal("INVALID JOURNAL LOCATION %d", 196 sblock->fs_journal_location); 197 if (reply("CONTINUE") == 0) { 198 exit(FSCK_EXIT_CHECK_FAILED); 199 } 200 pwarn("CLEARING EXISTING JOURNAL\n"); 201 sblock->fs_flags &= ~FS_DOWAPBL; 202 sblock->fs_journal_flags = UFS_WAPBL_FLAGS_CLEAR_LOG; 203 sblock->fs_journal_location = 204 UFS_WAPBL_JOURNALLOC_NONE; 205 sbdirty(); 206 ret = FSCK_EXIT_CHECK_FAILED; 207 break; 208 } 209 if (sblock->fs_flags & FS_DOWAPBL) { 210 error = wapbl_replay_start( 211 &wapbl_replay, 0, addr, count, blksize); 212 if (error) { 213 pfatal( 214 "UNABLE TO READ JOURNAL FOR REPLAY"); 215 if (reply("CONTINUE") == 0) { 216 exit(FSCK_EXIT_CHECK_FAILED); 217 } 218 pwarn("CLEARING EXISTING JOURNAL\n"); 219 sblock->fs_flags &= ~FS_DOWAPBL; 220 sblock->fs_journal_flags = UFS_WAPBL_FLAGS_CLEAR_LOG; 221 sbdirty(); 222 ret = FSCK_EXIT_CHECK_FAILED; 223 } 224 } 225 } 226 } 227 /* 228 * at this time fs_journal_flags can only be 0, 229 * UFS_WAPBL_FLAGS_CREATE_LOG or UFS_WAPBL_FLAGS_CLEAR_LOG. 230 * We can't have both flags at the same time. 231 */ 232 switch (sblock->fs_journal_flags) { 233 case 0: 234 break; 235 case UFS_WAPBL_FLAGS_CREATE_LOG: 236 case UFS_WAPBL_FLAGS_CLEAR_LOG: 237 switch(sblock->fs_journal_location) { 238 case UFS_WAPBL_JOURNALLOC_END_PARTITION: 239 case UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM: 240 break; 241 case UFS_WAPBL_JOURNALLOC_NONE: 242 if (sblock->fs_journal_flags == 243 UFS_WAPBL_FLAGS_CLEAR_LOG) 244 break; 245 /* FALLTHROUGH */ 246 default: 247 pfatal("INVALID JOURNAL LOCATION %d", 248 sblock->fs_journal_location); 249 if (reply("CONTINUE") == 0) { 250 exit(FSCK_EXIT_CHECK_FAILED); 251 } 252 pwarn("CLEARING JOURNAL FLAGS\n"); 253 sblock->fs_journal_flags = 0; 254 sblock->fs_journal_location = 255 UFS_WAPBL_JOURNALLOC_NONE; 256 sbdirty(); 257 ret = FSCK_EXIT_CHECK_FAILED; 258 break; 259 } 260 break; 261 default: 262 pfatal("INVALID JOURNAL FLAGS %d", 263 sblock->fs_journal_flags); 264 if (reply("CONTINUE") == 0) { 265 exit(FSCK_EXIT_CHECK_FAILED); 266 } 267 pwarn("CLEARING JOURNAL FLAGS\n"); 268 sblock->fs_journal_flags = 0; 269 sblock->fs_journal_location = 270 UFS_WAPBL_JOURNALLOC_NONE; 271 sbdirty(); 272 ret = FSCK_EXIT_CHECK_FAILED; 273 break; 274 } 275 return ret; 276} 277