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