1 /* $NetBSD: wapbl.h,v 1.15 2013/09/30 18:58:00 hannken Exp $ */ 2 3 /*- 4 * Copyright (c) 2003,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 #ifndef _SYS_WAPBL_H 33 #define _SYS_WAPBL_H 34 35 #include <sys/mutex.h> 36 37 #include <miscfs/specfs/specdev.h> 38 39 /* This header file describes the api and data structures for 40 * write ahead physical block logging (WAPBL) support. 41 */ 42 43 #if defined(_KERNEL_OPT) 44 #include "opt_wapbl.h" 45 #endif 46 47 #ifdef WAPBL_DEBUG 48 #ifndef WAPBL_DEBUG_PRINT 49 #define WAPBL_DEBUG_PRINT (WAPBL_PRINT_REPLAY | WAPBL_PRINT_OPEN) 50 #endif 51 52 #if 0 53 #define WAPBL_DEBUG_BUFBYTES 54 #endif 55 56 #endif 57 58 #ifdef WAPBL_DEBUG_PRINT 59 60 enum { 61 WAPBL_PRINT_OPEN = 0x1, 62 WAPBL_PRINT_FLUSH = 0x2, 63 WAPBL_PRINT_TRUNCATE = 0x4, 64 WAPBL_PRINT_TRANSACTION = 0x8, 65 WAPBL_PRINT_BUFFER = 0x10, 66 WAPBL_PRINT_BUFFER2 = 0x20, 67 WAPBL_PRINT_ALLOC = 0x40, 68 WAPBL_PRINT_INODE = 0x80, 69 WAPBL_PRINT_WRITE = 0x100, 70 WAPBL_PRINT_IO = 0x200, 71 WAPBL_PRINT_REPLAY = 0x400, 72 WAPBL_PRINT_ERROR = 0x800, 73 WAPBL_PRINT_DISCARD = 0x1000, 74 WAPBL_PRINT_BIODONE = 0x2000, 75 }; 76 77 #define WAPBL_PRINTF(mask, a) if (wapbl_debug_print & (mask)) printf a 78 extern int wapbl_debug_print; 79 #else 80 #define WAPBL_PRINTF(mask, a) 81 #endif 82 83 /****************************************************************/ 84 85 #include <sys/queue.h> 86 #include <sys/vnode.h> 87 #include <sys/buf.h> 88 89 #ifdef _KERNEL 90 91 struct wapbl_entry; 92 struct wapbl_replay; 93 struct wapbl; 94 95 typedef void (*wapbl_flush_fn_t)(struct mount *, daddr_t *, int *, int); 96 97 /* 98 * This structure holds per transaction log information 99 */ 100 struct wapbl_entry { 101 struct wapbl *we_wapbl; 102 SIMPLEQ_ENTRY(wapbl_entry) we_entries; 103 size_t we_bufcount; /* Count of unsynced buffers */ 104 size_t we_reclaimable_bytes; /* Number on disk bytes for this 105 transaction */ 106 int we_error; 107 #ifdef WAPBL_DEBUG_BUFBYTES 108 size_t we_unsynced_bufbytes; /* Byte count of unsynced buffers */ 109 #endif 110 }; 111 112 /* Start using a log */ 113 int wapbl_start(struct wapbl **, struct mount *, struct vnode *, daddr_t, 114 size_t, size_t, struct wapbl_replay *, 115 wapbl_flush_fn_t, wapbl_flush_fn_t); 116 117 /* Discard the current transaction, potentially dangerous */ 118 void wapbl_discard(struct wapbl *); 119 120 /* stop using a log */ 121 int wapbl_stop(struct wapbl *, int); 122 123 /* 124 * Begin a new transaction or increment transaction recursion 125 * level if called while a transaction is already in progress 126 * by the current process. 127 */ 128 int wapbl_begin(struct wapbl *, const char *, int); 129 130 131 /* End a transaction or decrement the transaction recursion level */ 132 void wapbl_end(struct wapbl *); 133 134 /* 135 * Add a new buffer to the current transaction. The buffers 136 * data will be copied to the current transaction log and the 137 * buffer will be marked B_LOCKED so that it will not be 138 * flushed to disk by the syncer or reallocated. 139 */ 140 void wapbl_add_buf(struct wapbl *, struct buf *); 141 142 /* Remove a buffer from the current transaction. */ 143 void wapbl_remove_buf(struct wapbl *, struct buf *); 144 145 void wapbl_resize_buf(struct wapbl *, struct buf *, long, long); 146 147 /* 148 * This will flush all completed transactions to disk and 149 * start asynchronous writes on the associated buffers 150 */ 151 int wapbl_flush(struct wapbl *, int); 152 153 /* 154 * Inodes that are allocated but have zero link count 155 * must be registered with the current transaction 156 * so they may be recorded in the log and cleaned up later. 157 * registration/unregistration of ino numbers already registered is ok. 158 */ 159 void wapbl_register_inode(struct wapbl *, ino_t, mode_t); 160 void wapbl_unregister_inode(struct wapbl *, ino_t, mode_t); 161 162 /* 163 * Metadata block deallocations must be registered so 164 * that revocations records can be written and to prevent 165 * the corresponding blocks from being reused as data 166 * blocks until the log is on disk. 167 */ 168 void wapbl_register_deallocation(struct wapbl *, daddr_t, int); 169 170 void wapbl_jlock_assert(struct wapbl *wl); 171 void wapbl_junlock_assert(struct wapbl *wl); 172 173 void wapbl_print(struct wapbl *wl, int full, void (*pr)(const char *, ...) 174 __printflike(1, 2)); 175 176 #if defined(WAPBL_DEBUG) || defined(DDB) 177 void wapbl_dump(struct wapbl *); 178 #endif 179 180 void wapbl_biodone(struct buf *); 181 182 extern struct wapbl_ops wapbl_ops; 183 184 static __inline struct mount * 185 wapbl_vptomp(struct vnode *vp) 186 { 187 struct mount *mp; 188 189 mp = NULL; 190 if (vp != NULL) { 191 if (vp->v_type == VBLK) 192 mp = spec_node_getmountedfs(vp); 193 else 194 mp = vp->v_mount; 195 } 196 197 return mp; 198 } 199 200 static __inline bool 201 wapbl_vphaswapbl(struct vnode *vp) 202 { 203 struct mount *mp; 204 205 if (vp == NULL) 206 return false; 207 208 mp = wapbl_vptomp(vp); 209 return mp && mp->mnt_wapbl; 210 } 211 212 #endif /* _KERNEL */ 213 214 /****************************************************************/ 215 /* Replay support */ 216 217 #ifdef WAPBL_INTERNAL 218 struct wapbl_replay { 219 struct vnode *wr_logvp; 220 struct vnode *wr_devvp; 221 daddr_t wr_logpbn; 222 223 int wr_log_dev_bshift; 224 int wr_fs_dev_bshift; 225 int64_t wr_circ_off; 226 int64_t wr_circ_size; 227 uint32_t wr_generation; 228 229 void *wr_scratch; 230 231 LIST_HEAD(wapbl_blk_head, wapbl_blk) *wr_blkhash; 232 u_long wr_blkhashmask; 233 int wr_blkhashcnt; 234 235 off_t wr_inodeshead; 236 off_t wr_inodestail; 237 int wr_inodescnt; 238 struct { 239 uint32_t wr_inumber; 240 uint32_t wr_imode; 241 } *wr_inodes; 242 }; 243 244 #define wapbl_replay_isopen(wr) ((wr)->wr_scratch != 0) 245 246 /* Supply this to provide i/o support */ 247 int wapbl_write(void *, size_t, struct vnode *, daddr_t); 248 int wapbl_read(void *, size_t, struct vnode *, daddr_t); 249 250 /****************************************************************/ 251 #else 252 struct wapbl_replay; 253 #endif /* WAPBL_INTERNAL */ 254 255 /****************************************************************/ 256 257 int wapbl_replay_start(struct wapbl_replay **, struct vnode *, 258 daddr_t, size_t, size_t); 259 void wapbl_replay_stop(struct wapbl_replay *); 260 void wapbl_replay_free(struct wapbl_replay *); 261 int wapbl_replay_write(struct wapbl_replay *, struct vnode *); 262 int wapbl_replay_can_read(struct wapbl_replay *, daddr_t, long); 263 int wapbl_replay_read(struct wapbl_replay *, void *, daddr_t, long); 264 265 /****************************************************************/ 266 267 #endif /* !_SYS_WAPBL_H */ 268