1/*- 2 * Copyright (c) 2010-2012 Semihalf 3 * Copyright (c) 2008, 2009 Reinoud Zandijk 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * From: NetBSD: nilfs.h,v 1.1 2009/07/18 16:31:42 reinoud 27 * 28 * $FreeBSD$ 29 */ 30 31#ifndef _FS_NANDFS_NANDFS_H_ 32#define _FS_NANDFS_NANDFS_H_ 33 34#include <sys/param.h> 35#include <sys/proc.h> 36#include <sys/condvar.h> 37#include <sys/lock.h> 38#include <sys/mutex.h> 39 40#include <sys/queue.h> 41#include <sys/uio.h> 42#include <sys/mutex.h> 43 44#include <sys/disk.h> 45#include <sys/kthread.h> 46#include "nandfs_fs.h" 47 48MALLOC_DECLARE(M_NANDFSTEMP); 49 50/* Debug categories */ 51#define NANDFS_DEBUG_VOLUMES 0x000001 52#define NANDFS_DEBUG_BLOCK 0x000004 53#define NANDFS_DEBUG_LOCKING 0x000008 54#define NANDFS_DEBUG_NODE 0x000010 55#define NANDFS_DEBUG_LOOKUP 0x000020 56#define NANDFS_DEBUG_READDIR 0x000040 57#define NANDFS_DEBUG_TRANSLATE 0x000080 58#define NANDFS_DEBUG_STRATEGY 0x000100 59#define NANDFS_DEBUG_READ 0x000200 60#define NANDFS_DEBUG_WRITE 0x000400 61#define NANDFS_DEBUG_IFILE 0x000800 62#define NANDFS_DEBUG_ATTR 0x001000 63#define NANDFS_DEBUG_EXTATTR 0x002000 64#define NANDFS_DEBUG_ALLOC 0x004000 65#define NANDFS_DEBUG_CPFILE 0x008000 66#define NANDFS_DEBUG_DIRHASH 0x010000 67#define NANDFS_DEBUG_NOTIMPL 0x020000 68#define NANDFS_DEBUG_SHEDULE 0x040000 69#define NANDFS_DEBUG_SEG 0x080000 70#define NANDFS_DEBUG_SYNC 0x100000 71#define NANDFS_DEBUG_PARANOIA 0x200000 72#define NANDFS_DEBUG_VNCALL 0x400000 73#define NANDFS_DEBUG_BUF 0x1000000 74#define NANDFS_DEBUG_BMAP 0x2000000 75#define NANDFS_DEBUG_DAT 0x4000000 76#define NANDFS_DEBUG_GENERIC 0x8000000 77#define NANDFS_DEBUG_CLEAN 0x10000000 78 79extern int nandfs_verbose; 80 81#define DPRINTF(name, arg) { \ 82 if (nandfs_verbose & NANDFS_DEBUG_##name) {\ 83 printf arg;\ 84 };\ 85 } 86#define DPRINTFIF(name, cond, arg) { \ 87 if (nandfs_verbose & NANDFS_DEBUG_##name) { \ 88 if (cond) printf arg;\ 89 };\ 90 } 91 92#define VFSTONANDFS(mp) ((struct nandfsmount *)((mp)->mnt_data)) 93#define VTON(vp) ((struct nandfs_node *)(vp)->v_data) 94#define NTOV(xp) ((xp)->nn_vnode) 95 96int nandfs_init(struct vfsconf *); 97int nandfs_uninit(struct vfsconf *); 98 99extern struct vop_vector nandfs_vnodeops; 100extern struct vop_vector nandfs_system_vnodeops; 101 102struct nandfs_node; 103 104/* Structure and derivatives */ 105struct nandfs_mdt { 106 uint32_t entries_per_block; 107 uint32_t entries_per_group; 108 uint32_t blocks_per_group; 109 uint32_t groups_per_desc_block; /* desc is super group */ 110 uint32_t blocks_per_desc_block; /* desc is super group */ 111}; 112 113struct nandfs_segment { 114 LIST_ENTRY(nandfs_segment) seg_link; 115 116 struct nandfs_device *fsdev; 117 118 TAILQ_HEAD(, buf) segsum; 119 TAILQ_HEAD(, buf) data; 120 121 uint64_t seg_num; 122 uint64_t seg_next; 123 uint64_t start_block; 124 uint32_t num_blocks; 125 126 uint32_t nblocks; 127 uint32_t nbinfos; 128 uint32_t segsum_blocks; 129 uint32_t segsum_bytes; 130 uint32_t bytes_left; 131 char *current_off; 132}; 133 134struct nandfs_seginfo { 135 LIST_HEAD( ,nandfs_segment) seg_list; 136 struct nandfs_segment *curseg; 137 struct nandfs_device *fsdev; 138 uint32_t blocks; 139 uint8_t reiterate; 140}; 141 142#define NANDFS_FSSTOR_FAILED 1 143struct nandfs_fsarea { 144 int offset; 145 int flags; 146 int last_used; 147}; 148 149extern int nandfs_cleaner_enable; 150extern int nandfs_cleaner_interval; 151extern int nandfs_cleaner_segments; 152 153struct nandfs_device { 154 struct vnode *nd_devvp; 155 struct g_consumer *nd_gconsumer; 156 157 struct thread *nd_syncer; 158 struct thread *nd_cleaner; 159 int nd_syncer_exit; 160 int nd_cleaner_exit; 161 162 int nd_is_nand; 163 164 struct nandfs_fsarea nd_fsarea[NANDFS_NFSAREAS]; 165 int nd_last_fsarea; 166 167 STAILQ_HEAD(nandfs_mnts, nandfsmount) nd_mounts; 168 SLIST_ENTRY(nandfs_device) nd_next_device; 169 170 /* FS structures */ 171 struct nandfs_fsdata nd_fsdata; 172 struct nandfs_super_block nd_super; 173 struct nandfs_segment_summary nd_last_segsum; 174 struct nandfs_super_root nd_super_root; 175 struct nandfs_node *nd_dat_node; 176 struct nandfs_node *nd_cp_node; 177 struct nandfs_node *nd_su_node; 178 struct nandfs_node *nd_gc_node; 179 180 struct nandfs_mdt nd_dat_mdt; 181 struct nandfs_mdt nd_ifile_mdt; 182 183 struct timespec nd_ts; 184 185 /* Synchronization */ 186 struct mtx nd_mutex; 187 struct mtx nd_sync_mtx; 188 struct cv nd_sync_cv; 189 struct mtx nd_clean_mtx; 190 struct cv nd_clean_cv; 191 struct lock nd_seg_const; 192 193 struct nandfs_seginfo *nd_seginfo; 194 195 /* FS geometry */ 196 uint64_t nd_devsize; 197 uint64_t nd_maxfilesize; 198 uint32_t nd_blocksize; 199 uint32_t nd_erasesize; 200 201 uint32_t nd_devblocksize; 202 203 /* Segment usage */ 204 uint64_t nd_clean_segs; 205 uint64_t *nd_free_base; 206 uint64_t nd_free_count; 207 uint64_t nd_dirty_bufs; 208 209 /* Running values */ 210 uint64_t nd_seg_sequence; 211 uint64_t nd_seg_num; 212 uint64_t nd_next_seg_num; 213 uint64_t nd_last_pseg; 214 uint64_t nd_last_cno; 215 uint64_t nd_last_ino; 216 uint64_t nd_fakevblk; 217 218 int nd_mount_state; 219 int nd_refcnt; 220 int nd_syncing; 221 int nd_cleaning; 222}; 223 224extern SLIST_HEAD(_nandfs_devices, nandfs_device) nandfs_devices; 225 226#define NANDFS_FORCE_SYNCER 0x1 227#define NANDFS_UMOUNT 0x2 228 229#define SYNCER_UMOUNT 0x0 230#define SYNCER_VFS_SYNC 0x1 231#define SYNCER_BDFLUSH 0x2 232#define SYNCER_FFORCE 0x3 233#define SYNCER_FSYNC 0x4 234#define SYNCER_ROUPD 0x5 235 236static __inline int 237nandfs_writelockflags(struct nandfs_device *fsdev, int flags) 238{ 239 int error = 0; 240 241 if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE) 242 error = lockmgr(&fsdev->nd_seg_const, flags | LK_SHARED, NULL); 243 244 return (error); 245} 246 247static __inline void 248nandfs_writeunlock(struct nandfs_device *fsdev) 249{ 250 251 if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE) 252 lockmgr(&(fsdev)->nd_seg_const, LK_RELEASE, NULL); 253} 254 255#define NANDFS_WRITELOCKFLAGS(fsdev, flags) nandfs_writelockflags(fsdev, flags) 256 257#define NANDFS_WRITELOCK(fsdev) NANDFS_WRITELOCKFLAGS(fsdev, 0) 258 259#define NANDFS_WRITEUNLOCK(fsdev) nandfs_writeunlock(fsdev) 260 261#define NANDFS_WRITEASSERT(fsdev) lockmgr_assert(&(fsdev)->nd_seg_const, KA_LOCKED) 262 263/* Specific mountpoint; head or a checkpoint/snapshot */ 264struct nandfsmount { 265 STAILQ_ENTRY(nandfsmount) nm_next_mount; 266 267 struct mount *nm_vfs_mountp; 268 struct nandfs_device *nm_nandfsdev; 269 struct nandfs_args nm_mount_args; 270 struct nandfs_node *nm_ifile_node; 271 272 uint8_t nm_flags; 273 int8_t nm_ronly; 274}; 275 276struct nandfs_node { 277 struct vnode *nn_vnode; 278 struct nandfsmount *nn_nmp; 279 struct nandfs_device *nn_nandfsdev; 280 struct lockf *nn_lockf; 281 282 uint64_t nn_ino; 283 struct nandfs_inode nn_inode; 284 285 uint64_t nn_diroff; 286 uint32_t nn_flags; 287}; 288 289#define IN_ACCESS 0x0001 /* Inode access time update request */ 290#define IN_CHANGE 0x0002 /* Inode change time update request */ 291#define IN_UPDATE 0x0004 /* Inode was written to; update mtime*/ 292#define IN_MODIFIED 0x0008 /* node has been modified */ 293#define IN_RENAME 0x0010 /* node is being renamed. */ 294 295/* File permissions. */ 296#define IEXEC 0000100 /* Executable. */ 297#define IWRITE 0000200 /* Writeable. */ 298#define IREAD 0000400 /* Readable. */ 299#define ISVTX 0001000 /* Sticky bit. */ 300#define ISGID 0002000 /* Set-gid. */ 301#define ISUID 0004000 /* Set-uid. */ 302 303#define PRINT_NODE_FLAGS \ 304 "\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFIED\5IN_RENAME" 305 306#define NANDFS_GATHER(x) ((x)->b_flags |= B_00800000) 307#define NANDFS_UNGATHER(x) ((x)->b_flags &= ~B_00800000) 308#define NANDFS_ISGATHERED(x) ((x)->b_flags & B_00800000) 309 310#endif /* !_FS_NANDFS_NANDFS_H_ */ 311