xref: /NextBSD/sys/fs/nandfs/nandfs.h (revision e5d2f8730c92c4abb6de986ec4e1f39a242b9868)
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 
48 MALLOC_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 
79 extern 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 
96 int nandfs_init(struct vfsconf *);
97 int nandfs_uninit(struct vfsconf *);
98 
99 extern struct vop_vector nandfs_vnodeops;
100 extern struct vop_vector nandfs_system_vnodeops;
101 
102 struct nandfs_node;
103 
104 /* Structure and derivatives */
105 struct 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 
113 struct 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 
134 struct 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
143 struct nandfs_fsarea {
144 	int	offset;
145 	int	flags;
146 	int	last_used;
147 };
148 
149 extern int nandfs_cleaner_enable;
150 extern int nandfs_cleaner_interval;
151 extern int nandfs_cleaner_segments;
152 
153 struct 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 	struct nandfs_fsarea	nd_fsarea[NANDFS_NFSAREAS];
163 	int			nd_last_fsarea;
164 
165 	STAILQ_HEAD(nandfs_mnts, nandfsmount)	nd_mounts;
166 	SLIST_ENTRY(nandfs_device)		nd_next_device;
167 
168 	/* FS structures */
169 	struct nandfs_fsdata		nd_fsdata;
170 	struct nandfs_super_block	nd_super;
171 	struct nandfs_segment_summary	nd_last_segsum;
172 	struct nandfs_super_root	nd_super_root;
173 	struct nandfs_node	*nd_dat_node;
174 	struct nandfs_node	*nd_cp_node;
175 	struct nandfs_node	*nd_su_node;
176 	struct nandfs_node	*nd_gc_node;
177 
178 	struct nandfs_mdt	nd_dat_mdt;
179 	struct nandfs_mdt	nd_ifile_mdt;
180 
181 	struct timespec		nd_ts;
182 
183 	/* Synchronization */
184 	struct mtx		nd_mutex;
185 	struct mtx		nd_sync_mtx;
186 	struct cv		nd_sync_cv;
187 	struct mtx		nd_clean_mtx;
188 	struct cv		nd_clean_cv;
189 	struct lock		nd_seg_const;
190 
191 	struct nandfs_seginfo	*nd_seginfo;
192 
193 	/* FS geometry */
194 	uint64_t		nd_devsize;
195 	uint64_t		nd_maxfilesize;
196 	uint32_t		nd_blocksize;
197 	uint32_t		nd_erasesize;
198 
199 	uint32_t		nd_devblocksize;
200 
201 	uint32_t		nd_segs_reserved;
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 
224 extern 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 
236 static __inline int
nandfs_writelockflags(struct nandfs_device * fsdev,int flags)237 nandfs_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 
247 static __inline void
nandfs_writeunlock(struct nandfs_device * fsdev)248 nandfs_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 */
264 struct 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 
276 struct 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_FS_FLAG1)
307 #define	NANDFS_UNGATHER(x) ((x)->b_flags &= ~B_FS_FLAG1)
308 #define	NANDFS_ISGATHERED(x) ((x)->b_flags & B_FS_FLAG1)
309 
310 #endif /* !_FS_NANDFS_NANDFS_H_ */
311