1235537Sgber/*-
2235537Sgber * Copyright (c) 2010-2012 Semihalf
3235537Sgber * Copyright (c) 2008, 2009 Reinoud Zandijk
4235537Sgber * All rights reserved.
5235537Sgber *
6235537Sgber * Redistribution and use in source and binary forms, with or without
7235537Sgber * modification, are permitted provided that the following conditions
8235537Sgber * are met:
9235537Sgber * 1. Redistributions of source code must retain the above copyright
10235537Sgber *    notice, this list of conditions and the following disclaimer.
11235537Sgber * 2. Redistributions in binary form must reproduce the above copyright
12235537Sgber *    notice, this list of conditions and the following disclaimer in the
13235537Sgber *    documentation and/or other materials provided with the distribution.
14235537Sgber *
15235537Sgber * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16235537Sgber * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17235537Sgber * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18235537Sgber * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19235537Sgber * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20235537Sgber * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21235537Sgber * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22235537Sgber * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23235537Sgber * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24235537Sgber * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25235537Sgber *
26235537Sgber * From: NetBSD: nilfs.h,v 1.1 2009/07/18 16:31:42 reinoud
27235537Sgber *
28235537Sgber * $FreeBSD$
29235537Sgber */
30235537Sgber
31235537Sgber#ifndef _FS_NANDFS_NANDFS_H_
32235537Sgber#define _FS_NANDFS_NANDFS_H_
33235537Sgber
34235537Sgber#include <sys/param.h>
35235537Sgber#include <sys/proc.h>
36235537Sgber#include <sys/condvar.h>
37235537Sgber#include <sys/lock.h>
38235537Sgber#include <sys/mutex.h>
39235537Sgber
40235537Sgber#include <sys/queue.h>
41235537Sgber#include <sys/uio.h>
42235537Sgber#include <sys/mutex.h>
43235537Sgber
44235537Sgber#include <sys/disk.h>
45235537Sgber#include <sys/kthread.h>
46235537Sgber#include "nandfs_fs.h"
47235537Sgber
48235537SgberMALLOC_DECLARE(M_NANDFSTEMP);
49235537Sgber
50235537Sgber/* Debug categories */
51235537Sgber#define	NANDFS_DEBUG_VOLUMES		0x000001
52235537Sgber#define	NANDFS_DEBUG_BLOCK		0x000004
53235537Sgber#define	NANDFS_DEBUG_LOCKING		0x000008
54235537Sgber#define	NANDFS_DEBUG_NODE		0x000010
55235537Sgber#define	NANDFS_DEBUG_LOOKUP		0x000020
56235537Sgber#define	NANDFS_DEBUG_READDIR		0x000040
57235537Sgber#define	NANDFS_DEBUG_TRANSLATE		0x000080
58235537Sgber#define	NANDFS_DEBUG_STRATEGY		0x000100
59235537Sgber#define	NANDFS_DEBUG_READ		0x000200
60235537Sgber#define	NANDFS_DEBUG_WRITE		0x000400
61235537Sgber#define	NANDFS_DEBUG_IFILE		0x000800
62235537Sgber#define	NANDFS_DEBUG_ATTR		0x001000
63235537Sgber#define	NANDFS_DEBUG_EXTATTR		0x002000
64235537Sgber#define	NANDFS_DEBUG_ALLOC		0x004000
65235537Sgber#define	NANDFS_DEBUG_CPFILE		0x008000
66235537Sgber#define	NANDFS_DEBUG_DIRHASH		0x010000
67235537Sgber#define	NANDFS_DEBUG_NOTIMPL		0x020000
68235537Sgber#define	NANDFS_DEBUG_SHEDULE		0x040000
69235537Sgber#define	NANDFS_DEBUG_SEG		0x080000
70235537Sgber#define	NANDFS_DEBUG_SYNC		0x100000
71235537Sgber#define	NANDFS_DEBUG_PARANOIA		0x200000
72235537Sgber#define	NANDFS_DEBUG_VNCALL		0x400000
73235537Sgber#define	NANDFS_DEBUG_BUF		0x1000000
74235537Sgber#define	NANDFS_DEBUG_BMAP		0x2000000
75235537Sgber#define	NANDFS_DEBUG_DAT		0x4000000
76235537Sgber#define	NANDFS_DEBUG_GENERIC		0x8000000
77235537Sgber#define	NANDFS_DEBUG_CLEAN		0x10000000
78235537Sgber
79235537Sgberextern int nandfs_verbose;
80235537Sgber
81235537Sgber#define	DPRINTF(name, arg) { \
82235537Sgber		if (nandfs_verbose & NANDFS_DEBUG_##name) {\
83235537Sgber			printf arg;\
84235537Sgber		};\
85235537Sgber	}
86235537Sgber#define	DPRINTFIF(name, cond, arg) { \
87235537Sgber		if (nandfs_verbose & NANDFS_DEBUG_##name) { \
88235537Sgber			if (cond) printf arg;\
89235537Sgber		};\
90235537Sgber	}
91235537Sgber
92235537Sgber#define	VFSTONANDFS(mp)    ((struct nandfsmount *)((mp)->mnt_data))
93235537Sgber#define	VTON(vp) ((struct nandfs_node *)(vp)->v_data)
94235537Sgber#define	NTOV(xp) ((xp)->nn_vnode)
95235537Sgber
96235537Sgberint nandfs_init(struct vfsconf *);
97235537Sgberint nandfs_uninit(struct vfsconf *);
98235537Sgber
99235537Sgberextern struct vop_vector nandfs_vnodeops;
100235537Sgberextern struct vop_vector nandfs_system_vnodeops;
101235537Sgber
102235537Sgberstruct nandfs_node;
103235537Sgber
104235537Sgber/* Structure and derivatives */
105235537Sgberstruct nandfs_mdt {
106235537Sgber	uint32_t	entries_per_block;
107235537Sgber	uint32_t	entries_per_group;
108235537Sgber	uint32_t	blocks_per_group;
109235537Sgber	uint32_t	groups_per_desc_block;	/* desc is super group */
110235537Sgber	uint32_t	blocks_per_desc_block;	/* desc is super group */
111235537Sgber};
112235537Sgber
113235537Sgberstruct nandfs_segment {
114235537Sgber	LIST_ENTRY(nandfs_segment) seg_link;
115235537Sgber
116235537Sgber	struct nandfs_device	*fsdev;
117235537Sgber
118235537Sgber	TAILQ_HEAD(, buf)	 segsum;
119235537Sgber	TAILQ_HEAD(, buf)	 data;
120235537Sgber
121235537Sgber	uint64_t		 seg_num;
122235537Sgber	uint64_t		 seg_next;
123235537Sgber	uint64_t		 start_block;
124235537Sgber	uint32_t		 num_blocks;
125235537Sgber
126235537Sgber	uint32_t		 nblocks;
127235537Sgber	uint32_t		 nbinfos;
128235537Sgber	uint32_t		 segsum_blocks;
129235537Sgber	uint32_t		 segsum_bytes;
130235537Sgber	uint32_t		 bytes_left;
131235537Sgber	char			*current_off;
132235537Sgber};
133235537Sgber
134235537Sgberstruct nandfs_seginfo {
135235537Sgber	LIST_HEAD( ,nandfs_segment)	seg_list;
136235537Sgber	struct nandfs_segment		*curseg;
137235537Sgber	struct nandfs_device		*fsdev;
138235537Sgber	uint32_t			blocks;
139235537Sgber	uint8_t				reiterate;
140235537Sgber};
141235537Sgber
142235537Sgber#define	NANDFS_FSSTOR_FAILED	1
143235537Sgberstruct nandfs_fsarea {
144235537Sgber	int	offset;
145235537Sgber	int	flags;
146235537Sgber	int	last_used;
147235537Sgber};
148235537Sgber
149235537Sgberextern int nandfs_cleaner_enable;
150235537Sgberextern int nandfs_cleaner_interval;
151235537Sgberextern int nandfs_cleaner_segments;
152235537Sgber
153235537Sgberstruct nandfs_device {
154235537Sgber	struct vnode		*nd_devvp;
155235537Sgber	struct g_consumer	*nd_gconsumer;
156235537Sgber
157235537Sgber	struct thread		*nd_syncer;
158235537Sgber	struct thread		*nd_cleaner;
159235537Sgber	int			nd_syncer_exit;
160235537Sgber	int			nd_cleaner_exit;
161235537Sgber
162235537Sgber	int			nd_is_nand;
163235537Sgber
164235537Sgber	struct nandfs_fsarea	nd_fsarea[NANDFS_NFSAREAS];
165235537Sgber	int			nd_last_fsarea;
166235537Sgber
167235537Sgber	STAILQ_HEAD(nandfs_mnts, nandfsmount)	nd_mounts;
168235537Sgber	SLIST_ENTRY(nandfs_device)		nd_next_device;
169235537Sgber
170235537Sgber	/* FS structures */
171235537Sgber	struct nandfs_fsdata		nd_fsdata;
172235537Sgber	struct nandfs_super_block	nd_super;
173235537Sgber	struct nandfs_segment_summary	nd_last_segsum;
174235537Sgber	struct nandfs_super_root	nd_super_root;
175235537Sgber	struct nandfs_node	*nd_dat_node;
176235537Sgber	struct nandfs_node	*nd_cp_node;
177235537Sgber	struct nandfs_node	*nd_su_node;
178235537Sgber	struct nandfs_node	*nd_gc_node;
179235537Sgber
180235537Sgber	struct nandfs_mdt	nd_dat_mdt;
181235537Sgber	struct nandfs_mdt	nd_ifile_mdt;
182235537Sgber
183235537Sgber	struct timespec		nd_ts;
184235537Sgber
185235537Sgber	/* Synchronization */
186235537Sgber	struct mtx		nd_mutex;
187235537Sgber	struct mtx		nd_sync_mtx;
188235537Sgber	struct cv		nd_sync_cv;
189235537Sgber	struct mtx		nd_clean_mtx;
190235537Sgber	struct cv		nd_clean_cv;
191235537Sgber	struct lock		nd_seg_const;
192235537Sgber
193235537Sgber	struct nandfs_seginfo	*nd_seginfo;
194235537Sgber
195235537Sgber	/* FS geometry */
196235537Sgber	uint64_t		nd_devsize;
197235537Sgber	uint64_t		nd_maxfilesize;
198235537Sgber	uint32_t		nd_blocksize;
199235537Sgber	uint32_t		nd_erasesize;
200235537Sgber
201235537Sgber	uint32_t		nd_devblocksize;
202235537Sgber
203235537Sgber	/* Segment usage */
204235537Sgber	uint64_t		nd_clean_segs;
205235537Sgber	uint64_t		*nd_free_base;
206235537Sgber	uint64_t		nd_free_count;
207235537Sgber	uint64_t		nd_dirty_bufs;
208235537Sgber
209235537Sgber	/* Running values */
210235537Sgber	uint64_t		nd_seg_sequence;
211235537Sgber	uint64_t		nd_seg_num;
212235537Sgber	uint64_t		nd_next_seg_num;
213235537Sgber	uint64_t		nd_last_pseg;
214235537Sgber	uint64_t		nd_last_cno;
215235537Sgber	uint64_t		nd_last_ino;
216235537Sgber	uint64_t		nd_fakevblk;
217235537Sgber
218235537Sgber	int			nd_mount_state;
219235537Sgber	int			nd_refcnt;
220235537Sgber	int			nd_syncing;
221235537Sgber	int			nd_cleaning;
222235537Sgber};
223235537Sgber
224235537Sgberextern SLIST_HEAD(_nandfs_devices, nandfs_device) nandfs_devices;
225235537Sgber
226235537Sgber#define	NANDFS_FORCE_SYNCER	0x1
227235537Sgber#define	NANDFS_UMOUNT		0x2
228235537Sgber
229235537Sgber#define	SYNCER_UMOUNT		0x0
230235537Sgber#define	SYNCER_VFS_SYNC		0x1
231235537Sgber#define	SYNCER_BDFLUSH		0x2
232235537Sgber#define	SYNCER_FFORCE		0x3
233235537Sgber#define	SYNCER_FSYNC		0x4
234235537Sgber#define	SYNCER_ROUPD		0x5
235235537Sgber
236235537Sgberstatic __inline int
237235537Sgbernandfs_writelockflags(struct nandfs_device *fsdev, int flags)
238235537Sgber{
239235537Sgber	int error = 0;
240235537Sgber
241235537Sgber	if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE)
242235537Sgber		error = lockmgr(&fsdev->nd_seg_const, flags | LK_SHARED, NULL);
243235537Sgber
244235537Sgber	return (error);
245235537Sgber}
246235537Sgber
247235537Sgberstatic __inline void
248235537Sgbernandfs_writeunlock(struct nandfs_device *fsdev)
249235537Sgber{
250235537Sgber
251235537Sgber	if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE)
252235537Sgber		lockmgr(&(fsdev)->nd_seg_const, LK_RELEASE, NULL);
253235537Sgber}
254235537Sgber
255235537Sgber#define NANDFS_WRITELOCKFLAGS(fsdev, flags)	nandfs_writelockflags(fsdev, flags)
256235537Sgber
257235537Sgber#define NANDFS_WRITELOCK(fsdev) NANDFS_WRITELOCKFLAGS(fsdev, 0)
258235537Sgber
259235537Sgber#define NANDFS_WRITEUNLOCK(fsdev) nandfs_writeunlock(fsdev)
260235537Sgber
261235537Sgber#define NANDFS_WRITEASSERT(fsdev) lockmgr_assert(&(fsdev)->nd_seg_const, KA_LOCKED)
262235537Sgber
263235537Sgber/* Specific mountpoint; head or a checkpoint/snapshot */
264235537Sgberstruct nandfsmount {
265235537Sgber	STAILQ_ENTRY(nandfsmount) nm_next_mount;
266235537Sgber
267235537Sgber	struct mount		*nm_vfs_mountp;
268235537Sgber	struct nandfs_device	*nm_nandfsdev;
269235537Sgber	struct nandfs_args	nm_mount_args;
270235537Sgber	struct nandfs_node	*nm_ifile_node;
271235537Sgber
272235537Sgber	uint8_t			nm_flags;
273235537Sgber	int8_t			nm_ronly;
274235537Sgber};
275235537Sgber
276235537Sgberstruct nandfs_node {
277235537Sgber	struct vnode			*nn_vnode;
278235537Sgber	struct nandfsmount		*nn_nmp;
279235537Sgber	struct nandfs_device		*nn_nandfsdev;
280235537Sgber	struct lockf			*nn_lockf;
281235537Sgber
282235537Sgber	uint64_t			nn_ino;
283235537Sgber	struct nandfs_inode		nn_inode;
284235537Sgber
285235537Sgber	uint64_t			nn_diroff;
286235537Sgber	uint32_t			nn_flags;
287235537Sgber};
288235537Sgber
289235537Sgber#define	IN_ACCESS	0x0001	/* Inode access time update request  */
290235537Sgber#define	IN_CHANGE	0x0002	/* Inode change time update request  */
291235537Sgber#define	IN_UPDATE	0x0004	/* Inode was written to; update mtime*/
292235537Sgber#define	IN_MODIFIED	0x0008	/* node has been modified */
293235537Sgber#define	IN_RENAME	0x0010	/* node is being renamed. */
294235537Sgber
295235537Sgber/* File permissions. */
296235537Sgber#define	IEXEC		0000100	/* Executable. */
297235537Sgber#define	IWRITE		0000200	/* Writeable. */
298235537Sgber#define	IREAD		0000400	/* Readable. */
299235537Sgber#define	ISVTX		0001000	/* Sticky bit. */
300235537Sgber#define	ISGID		0002000	/* Set-gid. */
301235537Sgber#define	ISUID		0004000	/* Set-uid. */
302235537Sgber
303235537Sgber#define	PRINT_NODE_FLAGS \
304235537Sgber	"\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFIED\5IN_RENAME"
305235537Sgber
306235537Sgber#define	NANDFS_GATHER(x) ((x)->b_flags |= B_00800000)
307235537Sgber#define	NANDFS_UNGATHER(x) ((x)->b_flags &= ~B_00800000)
308235537Sgber#define	NANDFS_ISGATHERED(x) ((x)->b_flags & B_00800000)
309235537Sgber
310235537Sgber#endif /* !_FS_NANDFS_NANDFS_H_ */
311