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