Home | History | Annotate | Line # | Download | only in sys
      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