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