| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: vfs_wapbl.c,v 1.55 2013/02/09 00:32:12 christos Exp $ */ | | 1 | /* $NetBSD: vfs_wapbl.c,v 1.56 2013/09/14 13:19:50 joerg Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2003, 2008, 2009 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2003, 2008, 2009 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Wasabi Systems, Inc. | | 8 | * by Wasabi Systems, Inc. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -26,27 +26,27 @@ | | | @@ -26,27 +26,27 @@ |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 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 | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * This implements file system independent write ahead filesystem logging. | | 33 | * This implements file system independent write ahead filesystem logging. |
34 | */ | | 34 | */ |
35 | | | 35 | |
36 | #define WAPBL_INTERNAL | | 36 | #define WAPBL_INTERNAL |
37 | | | 37 | |
38 | #include <sys/cdefs.h> | | 38 | #include <sys/cdefs.h> |
39 | __KERNEL_RCSID(0, "$NetBSD: vfs_wapbl.c,v 1.55 2013/02/09 00:32:12 christos Exp $"); | | 39 | __KERNEL_RCSID(0, "$NetBSD: vfs_wapbl.c,v 1.56 2013/09/14 13:19:50 joerg Exp $"); |
40 | | | 40 | |
41 | #include <sys/param.h> | | 41 | #include <sys/param.h> |
42 | #include <sys/bitops.h> | | 42 | #include <sys/bitops.h> |
43 | | | 43 | |
44 | #ifdef _KERNEL | | 44 | #ifdef _KERNEL |
45 | #include <sys/param.h> | | 45 | #include <sys/param.h> |
46 | #include <sys/namei.h> | | 46 | #include <sys/namei.h> |
47 | #include <sys/proc.h> | | 47 | #include <sys/proc.h> |
48 | #include <sys/sysctl.h> | | 48 | #include <sys/sysctl.h> |
49 | #include <sys/uio.h> | | 49 | #include <sys/uio.h> |
50 | #include <sys/vnode.h> | | 50 | #include <sys/vnode.h> |
51 | #include <sys/file.h> | | 51 | #include <sys/file.h> |
52 | #include <sys/module.h> | | 52 | #include <sys/module.h> |
| @@ -199,28 +199,26 @@ int wapbl_debug_print = WAPBL_DEBUG_PRIN | | | @@ -199,28 +199,26 @@ int wapbl_debug_print = WAPBL_DEBUG_PRIN |
199 | | | 199 | |
200 | #ifdef WAPBL_DEBUG | | 200 | #ifdef WAPBL_DEBUG |
201 | struct wapbl *wapbl_debug_wl; | | 201 | struct wapbl *wapbl_debug_wl; |
202 | #endif | | 202 | #endif |
203 | | | 203 | |
204 | static int wapbl_write_commit(struct wapbl *wl, off_t head, off_t tail); | | 204 | static int wapbl_write_commit(struct wapbl *wl, off_t head, off_t tail); |
205 | static int wapbl_write_blocks(struct wapbl *wl, off_t *offp); | | 205 | static int wapbl_write_blocks(struct wapbl *wl, off_t *offp); |
206 | static int wapbl_write_revocations(struct wapbl *wl, off_t *offp); | | 206 | static int wapbl_write_revocations(struct wapbl *wl, off_t *offp); |
207 | static int wapbl_write_inodes(struct wapbl *wl, off_t *offp); | | 207 | static int wapbl_write_inodes(struct wapbl *wl, off_t *offp); |
208 | #endif /* _KERNEL */ | | 208 | #endif /* _KERNEL */ |
209 | | | 209 | |
210 | static int wapbl_replay_process(struct wapbl_replay *wr, off_t, off_t); | | 210 | static int wapbl_replay_process(struct wapbl_replay *wr, off_t, off_t); |
211 | | | 211 | |
212 | static inline size_t wapbl_space_free(size_t avail, off_t head, | | | |
213 | off_t tail); | | | |
214 | static inline size_t wapbl_space_used(size_t avail, off_t head, | | 212 | static inline size_t wapbl_space_used(size_t avail, off_t head, |
215 | off_t tail); | | 213 | off_t tail); |
216 | | | 214 | |
217 | #ifdef _KERNEL | | 215 | #ifdef _KERNEL |
218 | | | 216 | |
219 | static struct pool wapbl_entry_pool; | | 217 | static struct pool wapbl_entry_pool; |
220 | | | 218 | |
221 | #define WAPBL_INODETRK_SIZE 83 | | 219 | #define WAPBL_INODETRK_SIZE 83 |
222 | static int wapbl_ino_pool_refcount; | | 220 | static int wapbl_ino_pool_refcount; |
223 | static struct pool wapbl_ino_pool; | | 221 | static struct pool wapbl_ino_pool; |
224 | struct wapbl_ino { | | 222 | struct wapbl_ino { |
225 | LIST_ENTRY(wapbl_ino) wi_hash; | | 223 | LIST_ENTRY(wapbl_ino) wi_hash; |
226 | ino_t wi_ino; | | 224 | ino_t wi_ino; |
| @@ -1114,26 +1112,38 @@ wapbl_resize_buf(struct wapbl *wl, struc | | | @@ -1114,26 +1112,38 @@ wapbl_resize_buf(struct wapbl *wl, struc |
1114 | if (bp->b_flags & B_LOCKED) { | | 1112 | if (bp->b_flags & B_LOCKED) { |
1115 | mutex_enter(&wl->wl_mtx); | | 1113 | mutex_enter(&wl->wl_mtx); |
1116 | wl->wl_bufbytes += bp->b_bufsize - oldsz; | | 1114 | wl->wl_bufbytes += bp->b_bufsize - oldsz; |
1117 | wl->wl_bcount += bp->b_bcount - oldcnt; | | 1115 | wl->wl_bcount += bp->b_bcount - oldcnt; |
1118 | mutex_exit(&wl->wl_mtx); | | 1116 | mutex_exit(&wl->wl_mtx); |
1119 | } | | 1117 | } |
1120 | } | | 1118 | } |
1121 | | | 1119 | |
1122 | #endif /* _KERNEL */ | | 1120 | #endif /* _KERNEL */ |
1123 | | | 1121 | |
1124 | /****************************************************************/ | | 1122 | /****************************************************************/ |
1125 | /* Some utility inlines */ | | 1123 | /* Some utility inlines */ |
1126 | | | 1124 | |
| | | 1125 | static inline size_t |
| | | 1126 | wapbl_space_used(size_t avail, off_t head, off_t tail) |
| | | 1127 | { |
| | | 1128 | |
| | | 1129 | if (tail == 0) { |
| | | 1130 | KASSERT(head == 0); |
| | | 1131 | return 0; |
| | | 1132 | } |
| | | 1133 | return ((head + (avail - 1) - tail) % avail) + 1; |
| | | 1134 | } |
| | | 1135 | |
| | | 1136 | #ifdef _KERNEL |
1127 | /* This is used to advance the pointer at old to new value at old+delta */ | | 1137 | /* This is used to advance the pointer at old to new value at old+delta */ |
1128 | static inline off_t | | 1138 | static inline off_t |
1129 | wapbl_advance(size_t size, size_t off, off_t old, size_t delta) | | 1139 | wapbl_advance(size_t size, size_t off, off_t old, size_t delta) |
1130 | { | | 1140 | { |
1131 | off_t new; | | 1141 | off_t new; |
1132 | | | 1142 | |
1133 | /* Define acceptable ranges for inputs. */ | | 1143 | /* Define acceptable ranges for inputs. */ |
1134 | KASSERT(delta <= (size_t)size); | | 1144 | KASSERT(delta <= (size_t)size); |
1135 | KASSERT((old == 0) || ((size_t)old >= off)); | | 1145 | KASSERT((old == 0) || ((size_t)old >= off)); |
1136 | KASSERT(old < (off_t)(size + off)); | | 1146 | KASSERT(old < (off_t)(size + off)); |
1137 | | | 1147 | |
1138 | if ((old == 0) && (delta != 0)) | | 1148 | if ((old == 0) && (delta != 0)) |
1139 | new = off + delta; | | 1149 | new = off + delta; |
| @@ -1144,37 +1154,26 @@ wapbl_advance(size_t size, size_t off, o | | | @@ -1144,37 +1154,26 @@ wapbl_advance(size_t size, size_t off, o |
1144 | | | 1154 | |
1145 | /* Note some interesting axioms */ | | 1155 | /* Note some interesting axioms */ |
1146 | KASSERT((delta != 0) || (new == old)); | | 1156 | KASSERT((delta != 0) || (new == old)); |
1147 | KASSERT((delta == 0) || (new != 0)); | | 1157 | KASSERT((delta == 0) || (new != 0)); |
1148 | KASSERT((delta != (size)) || (new == old)); | | 1158 | KASSERT((delta != (size)) || (new == old)); |
1149 | | | 1159 | |
1150 | /* Define acceptable ranges for output. */ | | 1160 | /* Define acceptable ranges for output. */ |
1151 | KASSERT((new == 0) || ((size_t)new >= off)); | | 1161 | KASSERT((new == 0) || ((size_t)new >= off)); |
1152 | KASSERT((size_t)new < (size + off)); | | 1162 | KASSERT((size_t)new < (size + off)); |
1153 | return new; | | 1163 | return new; |
1154 | } | | 1164 | } |
1155 | | | 1165 | |
1156 | static inline size_t | | 1166 | static inline size_t |
1157 | wapbl_space_used(size_t avail, off_t head, off_t tail) | | | |
1158 | { | | | |
1159 | | | | |
1160 | if (tail == 0) { | | | |
1161 | KASSERT(head == 0); | | | |
1162 | return 0; | | | |
1163 | } | | | |
1164 | return ((head + (avail - 1) - tail) % avail) + 1; | | | |
1165 | } | | | |
1166 | | | | |
1167 | static inline size_t | | | |
1168 | wapbl_space_free(size_t avail, off_t head, off_t tail) | | 1167 | wapbl_space_free(size_t avail, off_t head, off_t tail) |
1169 | { | | 1168 | { |
1170 | | | 1169 | |
1171 | return avail - wapbl_space_used(avail, head, tail); | | 1170 | return avail - wapbl_space_used(avail, head, tail); |
1172 | } | | 1171 | } |
1173 | | | 1172 | |
1174 | static inline void | | 1173 | static inline void |
1175 | wapbl_advance_head(size_t size, size_t off, size_t delta, off_t *headp, | | 1174 | wapbl_advance_head(size_t size, size_t off, size_t delta, off_t *headp, |
1176 | off_t *tailp) | | 1175 | off_t *tailp) |
1177 | { | | 1176 | { |
1178 | off_t head = *headp; | | 1177 | off_t head = *headp; |
1179 | off_t tail = *tailp; | | 1178 | off_t tail = *tailp; |
1180 | | | 1179 | |
| @@ -1192,27 +1191,26 @@ wapbl_advance_tail(size_t size, size_t o | | | @@ -1192,27 +1191,26 @@ wapbl_advance_tail(size_t size, size_t o |
1192 | { | | 1191 | { |
1193 | off_t head = *headp; | | 1192 | off_t head = *headp; |
1194 | off_t tail = *tailp; | | 1193 | off_t tail = *tailp; |
1195 | | | 1194 | |
1196 | KASSERT(delta <= wapbl_space_used(size, head, tail)); | | 1195 | KASSERT(delta <= wapbl_space_used(size, head, tail)); |
1197 | tail = wapbl_advance(size, off, tail, delta); | | 1196 | tail = wapbl_advance(size, off, tail, delta); |
1198 | if (head == tail) { | | 1197 | if (head == tail) { |
1199 | head = tail = 0; | | 1198 | head = tail = 0; |
1200 | } | | 1199 | } |
1201 | *headp = head; | | 1200 | *headp = head; |
1202 | *tailp = tail; | | 1201 | *tailp = tail; |
1203 | } | | 1202 | } |
1204 | | | 1203 | |
1205 | #ifdef _KERNEL | | | |
1206 | | | 1204 | |
1207 | /****************************************************************/ | | 1205 | /****************************************************************/ |
1208 | | | 1206 | |
1209 | /* | | 1207 | /* |
1210 | * Remove transactions whose buffers are completely flushed to disk. | | 1208 | * Remove transactions whose buffers are completely flushed to disk. |
1211 | * Will block until at least minfree space is available. | | 1209 | * Will block until at least minfree space is available. |
1212 | * only intended to be called from inside wapbl_flush and therefore | | 1210 | * only intended to be called from inside wapbl_flush and therefore |
1213 | * does not protect against commit races with itself or with flush. | | 1211 | * does not protect against commit races with itself or with flush. |
1214 | */ | | 1212 | */ |
1215 | static int | | 1213 | static int |
1216 | wapbl_truncate(struct wapbl *wl, size_t minfree, int waitonly) | | 1214 | wapbl_truncate(struct wapbl *wl, size_t minfree, int waitonly) |
1217 | { | | 1215 | { |
1218 | size_t delta; | | 1216 | size_t delta; |