aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/nandfs/nandfs.h
blob: 9a9b28a1bc0bae0ae8957f49129c183cb98bbd59 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
/*-
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
 *
 * 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 <sys/param.h>
#include <sys/proc.h>
#include <sys/condvar.h>
#include <sys/lock.h>
#include <sys/mutex.h>

#include <sys/queue.h>
#include <sys/uio.h>
#include <sys/mutex.h>

#include <sys/disk.h>
#include <sys/kthread.h>
#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;

	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;

	uint32_t		nd_segs_reserved;

	/* 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_FS_FLAG1)
#define	NANDFS_UNGATHER(x) ((x)->b_flags &= ~B_FS_FLAG1)
#define	NANDFS_ISGATHERED(x) ((x)->b_flags & B_FS_FLAG1)

#endif /* !_FS_NANDFS_NANDFS_H_ */