/*- * Copyright (c) 2010-2012 Semihalf * Copyright (c) 2008, 2009 Reinoud Zandijk * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * From: NetBSD: nilfs.h,v 1.1 2009/07/18 16:31:42 reinoud * * $FreeBSD$ */ #ifndef _FS_NANDFS_NANDFS_H_ #define _FS_NANDFS_NANDFS_H_ #include #include #include #include #include #include #include #include #include #include #include "nandfs_fs.h" MALLOC_DECLARE(M_NANDFSTEMP); /* Debug categories */ #define NANDFS_DEBUG_VOLUMES 0x000001 #define NANDFS_DEBUG_BLOCK 0x000004 #define NANDFS_DEBUG_LOCKING 0x000008 #define NANDFS_DEBUG_NODE 0x000010 #define NANDFS_DEBUG_LOOKUP 0x000020 #define NANDFS_DEBUG_READDIR 0x000040 #define NANDFS_DEBUG_TRANSLATE 0x000080 #define NANDFS_DEBUG_STRATEGY 0x000100 #define NANDFS_DEBUG_READ 0x000200 #define NANDFS_DEBUG_WRITE 0x000400 #define NANDFS_DEBUG_IFILE 0x000800 #define NANDFS_DEBUG_ATTR 0x001000 #define NANDFS_DEBUG_EXTATTR 0x002000 #define NANDFS_DEBUG_ALLOC 0x004000 #define NANDFS_DEBUG_CPFILE 0x008000 #define NANDFS_DEBUG_DIRHASH 0x010000 #define NANDFS_DEBUG_NOTIMPL 0x020000 #define NANDFS_DEBUG_SHEDULE 0x040000 #define NANDFS_DEBUG_SEG 0x080000 #define NANDFS_DEBUG_SYNC 0x100000 #define NANDFS_DEBUG_PARANOIA 0x200000 #define NANDFS_DEBUG_VNCALL 0x400000 #define NANDFS_DEBUG_BUF 0x1000000 #define NANDFS_DEBUG_BMAP 0x2000000 #define NANDFS_DEBUG_DAT 0x4000000 #define NANDFS_DEBUG_GENERIC 0x8000000 #define NANDFS_DEBUG_CLEAN 0x10000000 extern int nandfs_verbose; #define DPRINTF(name, arg) { \ if (nandfs_verbose & NANDFS_DEBUG_##name) {\ printf arg;\ };\ } #define DPRINTFIF(name, cond, arg) { \ if (nandfs_verbose & NANDFS_DEBUG_##name) { \ if (cond) printf arg;\ };\ } #define VFSTONANDFS(mp) ((struct nandfsmount *)((mp)->mnt_data)) #define VTON(vp) ((struct nandfs_node *)(vp)->v_data) #define NTOV(xp) ((xp)->nn_vnode) int nandfs_init(struct vfsconf *); int nandfs_uninit(struct vfsconf *); extern struct vop_vector nandfs_vnodeops; extern struct vop_vector nandfs_system_vnodeops; struct nandfs_node; /* Structure and derivatives */ struct nandfs_mdt { uint32_t entries_per_block; uint32_t entries_per_group; uint32_t blocks_per_group; uint32_t groups_per_desc_block; /* desc is super group */ uint32_t blocks_per_desc_block; /* desc is super group */ }; struct nandfs_segment { LIST_ENTRY(nandfs_segment) seg_link; struct nandfs_device *fsdev; TAILQ_HEAD(, buf) segsum; TAILQ_HEAD(, buf) data; uint64_t seg_num; uint64_t seg_next; uint64_t start_block; uint32_t num_blocks; uint32_t nblocks; uint32_t nbinfos; uint32_t segsum_blocks; uint32_t segsum_bytes; uint32_t bytes_left; char *current_off; }; struct nandfs_seginfo { LIST_HEAD( ,nandfs_segment) seg_list; struct nandfs_segment *curseg; struct nandfs_device *fsdev; uint32_t blocks; uint8_t reiterate; }; #define NANDFS_FSSTOR_FAILED 1 struct nandfs_fsarea { int offset; int flags; int last_used; }; extern int nandfs_cleaner_enable; extern int nandfs_cleaner_interval; extern int nandfs_cleaner_segments; struct nandfs_device { struct vnode *nd_devvp; struct g_consumer *nd_gconsumer; struct thread *nd_syncer; struct thread *nd_cleaner; int nd_syncer_exit; int nd_cleaner_exit; int nd_is_nand; struct nandfs_fsarea nd_fsarea[NANDFS_NFSAREAS]; int nd_last_fsarea; STAILQ_HEAD(nandfs_mnts, nandfsmount) nd_mounts; SLIST_ENTRY(nandfs_device) nd_next_device; /* FS structures */ struct nandfs_fsdata nd_fsdata; struct nandfs_super_block nd_super; struct nandfs_segment_summary nd_last_segsum; struct nandfs_super_root nd_super_root; struct nandfs_node *nd_dat_node; struct nandfs_node *nd_cp_node; struct nandfs_node *nd_su_node; struct nandfs_node *nd_gc_node; struct nandfs_mdt nd_dat_mdt; struct nandfs_mdt nd_ifile_mdt; struct timespec nd_ts; /* Synchronization */ struct mtx nd_mutex; struct mtx nd_sync_mtx; struct cv nd_sync_cv; struct mtx nd_clean_mtx; struct cv nd_clean_cv; struct lock nd_seg_const; struct nandfs_seginfo *nd_seginfo; /* FS geometry */ uint64_t nd_devsize; uint64_t nd_maxfilesize; uint32_t nd_blocksize; uint32_t nd_erasesize; uint32_t nd_devblocksize; /* Segment usage */ uint64_t nd_clean_segs; uint64_t *nd_free_base; uint64_t nd_free_count; uint64_t nd_dirty_bufs; /* Running values */ uint64_t nd_seg_sequence; uint64_t nd_seg_num; uint64_t nd_next_seg_num; uint64_t nd_last_pseg; uint64_t nd_last_cno; uint64_t nd_last_ino; uint64_t nd_fakevblk; int nd_mount_state; int nd_refcnt; int nd_syncing; int nd_cleaning; }; extern SLIST_HEAD(_nandfs_devices, nandfs_device) nandfs_devices; #define NANDFS_FORCE_SYNCER 0x1 #define NANDFS_UMOUNT 0x2 #define SYNCER_UMOUNT 0x0 #define SYNCER_VFS_SYNC 0x1 #define SYNCER_BDFLUSH 0x2 #define SYNCER_FFORCE 0x3 #define SYNCER_FSYNC 0x4 #define SYNCER_ROUPD 0x5 static __inline int nandfs_writelockflags(struct nandfs_device *fsdev, int flags) { int error = 0; if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE) error = lockmgr(&fsdev->nd_seg_const, flags | LK_SHARED, NULL); return (error); } static __inline void nandfs_writeunlock(struct nandfs_device *fsdev) { if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE) lockmgr(&(fsdev)->nd_seg_const, LK_RELEASE, NULL); } #define NANDFS_WRITELOCKFLAGS(fsdev, flags) nandfs_writelockflags(fsdev, flags) #define NANDFS_WRITELOCK(fsdev) NANDFS_WRITELOCKFLAGS(fsdev, 0) #define NANDFS_WRITEUNLOCK(fsdev) nandfs_writeunlock(fsdev) #define NANDFS_WRITEASSERT(fsdev) lockmgr_assert(&(fsdev)->nd_seg_const, KA_LOCKED) /* Specific mountpoint; head or a checkpoint/snapshot */ struct nandfsmount { STAILQ_ENTRY(nandfsmount) nm_next_mount; struct mount *nm_vfs_mountp; struct nandfs_device *nm_nandfsdev; struct nandfs_args nm_mount_args; struct nandfs_node *nm_ifile_node; uint8_t nm_flags; int8_t nm_ronly; }; struct nandfs_node { struct vnode *nn_vnode; struct nandfsmount *nn_nmp; struct nandfs_device *nn_nandfsdev; struct lockf *nn_lockf; uint64_t nn_ino; struct nandfs_inode nn_inode; uint64_t nn_diroff; uint32_t nn_flags; }; #define IN_ACCESS 0x0001 /* Inode access time update request */ #define IN_CHANGE 0x0002 /* Inode change time update request */ #define IN_UPDATE 0x0004 /* Inode was written to; update mtime*/ #define IN_MODIFIED 0x0008 /* node has been modified */ #define IN_RENAME 0x0010 /* node is being renamed. */ /* File permissions. */ #define IEXEC 0000100 /* Executable. */ #define IWRITE 0000200 /* Writeable. */ #define IREAD 0000400 /* Readable. */ #define ISVTX 0001000 /* Sticky bit. */ #define ISGID 0002000 /* Set-gid. */ #define ISUID 0004000 /* Set-uid. */ #define PRINT_NODE_FLAGS \ "\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFIED\5IN_RENAME" #define NANDFS_GATHER(x) ((x)->b_flags |= B_00800000) #define NANDFS_UNGATHER(x) ((x)->b_flags &= ~B_00800000) #define NANDFS_ISGATHERED(x) ((x)->b_flags & B_00800000) #endif /* !_FS_NANDFS_NANDFS_H_ */