1 /* $NetBSD: wapbl.h,v 1.16 2014/09/05 05:42:50 matt 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 *
wapbl_vptomp(struct vnode * vp)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
wapbl_vphaswapbl(struct vnode * vp)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 LIST_HEAD(wapbl_blk_head, wapbl_blk);
219 struct wapbl_replay {
220 struct vnode *wr_logvp;
221 struct vnode *wr_devvp;
222 daddr_t wr_logpbn;
223
224 int wr_log_dev_bshift;
225 int wr_fs_dev_bshift;
226 int64_t wr_circ_off;
227 int64_t wr_circ_size;
228 uint32_t wr_generation;
229
230 void *wr_scratch;
231
232 struct wapbl_blk_head *wr_blkhash;
233 u_long wr_blkhashmask;
234 int wr_blkhashcnt;
235
236 off_t wr_inodeshead;
237 off_t wr_inodestail;
238 int wr_inodescnt;
239 struct {
240 uint32_t wr_inumber;
241 uint32_t wr_imode;
242 } *wr_inodes;
243 };
244
245 #define wapbl_replay_isopen(wr) ((wr)->wr_scratch != 0)
246
247 /* Supply this to provide i/o support */
248 int wapbl_write(void *, size_t, struct vnode *, daddr_t);
249 int wapbl_read(void *, size_t, struct vnode *, daddr_t);
250
251 /****************************************************************/
252 #else
253 struct wapbl_replay;
254 #endif /* WAPBL_INTERNAL */
255
256 /****************************************************************/
257
258 int wapbl_replay_start(struct wapbl_replay **, struct vnode *,
259 daddr_t, size_t, size_t);
260 void wapbl_replay_stop(struct wapbl_replay *);
261 void wapbl_replay_free(struct wapbl_replay *);
262 int wapbl_replay_write(struct wapbl_replay *, struct vnode *);
263 int wapbl_replay_can_read(struct wapbl_replay *, daddr_t, long);
264 int wapbl_replay_read(struct wapbl_replay *, void *, daddr_t, long);
265
266 /****************************************************************/
267
268 #endif /* !_SYS_WAPBL_H */
269