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 * Original definitions written by Koji Sato <koji@osrg.net>
27235537Sgber *                    and Ryusuke Konishi <ryusuke@osrg.net>
28235537Sgber * From: NetBSD: nandfs_fs.h,v 1.1 2009/07/18 16:31:42 reinoud
29235537Sgber *
30235537Sgber * $FreeBSD$
31235537Sgber */
32235537Sgber
33235537Sgber#ifndef _NANDFS_FS_H
34235537Sgber#define _NANDFS_FS_H
35235537Sgber
36235537Sgber#include <sys/uuid.h>
37235537Sgber
38235537Sgber#define	MNINDIR(fsdev)	((fsdev)->nd_blocksize / sizeof(nandfs_daddr_t))
39235537Sgber
40235537Sgber/*
41235537Sgber * Inode structure. There are a few dedicated inode numbers that are
42235537Sgber * defined here first.
43235537Sgber */
44235537Sgber#define	NANDFS_WHT_INO		1	/* Whiteout ino			*/
45235537Sgber#define	NANDFS_ROOT_INO		2	/* Root file inode		*/
46235537Sgber#define	NANDFS_DAT_INO		3	/* DAT file			*/
47235537Sgber#define	NANDFS_CPFILE_INO	4	/* checkpoint file		*/
48235537Sgber#define	NANDFS_SUFILE_INO	5	/* segment usage file		*/
49235537Sgber#define	NANDFS_IFILE_INO	6	/* ifile			*/
50235537Sgber#define	NANDFS_GC_INO		7	/* Cleanerd node		*/
51235537Sgber#define	NANDFS_ATIME_INO	8	/* Atime file (reserved)	*/
52235537Sgber#define	NANDFS_XATTR_INO	9	/* Xattribute file (reserved)	*/
53235537Sgber#define	NANDFS_SKETCH_INO	10	/* Sketch file (obsolete)	*/
54235537Sgber#define	NANDFS_USER_INO		11	/* First user's file inode number */
55235537Sgber
56235537Sgber#define	NANDFS_SYS_NODE(ino) \
57235537Sgber	(((ino) >= NANDFS_DAT_INO) && ((ino) <= NANDFS_GC_INO))
58235537Sgber
59235537Sgber#define	NDADDR		12		/* Direct addresses in inode. */
60235537Sgber#define	NIADDR		3		/* Indirect addresses in inode. */
61235537Sgber
62235537Sgbertypedef	int64_t		nandfs_daddr_t;
63235537Sgbertypedef	int64_t		nandfs_lbn_t;
64235537Sgber
65235537Sgberstruct nandfs_inode {
66235537Sgber	uint64_t	i_blocks;	/* 0: size in device blocks		*/
67235537Sgber	uint64_t	i_size;		/* 8: size in bytes			*/
68235537Sgber	uint64_t	i_ctime;	/* 16: creation time in seconds		*/
69235537Sgber	uint64_t	i_mtime;	/* 24: modification time in seconds part*/
70235537Sgber	uint32_t	i_ctime_nsec;	/* 32: creation time nanoseconds part	*/
71235537Sgber	uint32_t	i_mtime_nsec;	/* 36: modification time in nanoseconds	*/
72235537Sgber	uint32_t	i_uid;		/* 40: user id				*/
73235537Sgber	uint32_t	i_gid;		/* 44: group id				*/
74235537Sgber	uint16_t	i_mode;		/* 48: file mode			*/
75235537Sgber	uint16_t	i_links_count;	/* 50: number of references to the inode*/
76235537Sgber	uint32_t	i_flags;	/* 52: NANDFS_*_FL flags		*/
77235537Sgber	nandfs_daddr_t	i_special;	/* 56: special				*/
78235537Sgber	nandfs_daddr_t	i_db[NDADDR];	/* 64: Direct disk blocks.		*/
79235537Sgber	nandfs_daddr_t	i_ib[NIADDR];	/* 160: Indirect disk blocks.		*/
80235537Sgber	uint64_t	i_xattr;	/* 184: reserved for extended attributes*/
81235537Sgber	uint32_t	i_generation;	/* 192: file generation for NFS		*/
82235537Sgber	uint32_t	i_pad[15];	/* 196: make it 64 bits aligned		*/
83235537Sgber};
84235537Sgber
85235537Sgber#ifdef _KERNEL
86235537SgberCTASSERT(sizeof(struct nandfs_inode) == 256);
87235537Sgber#endif
88235537Sgber
89235537Sgber/*
90235537Sgber * Each checkpoint/snapshot has a super root.
91235537Sgber *
92235537Sgber * The super root holds the inodes of the three system files: `dat', `cp' and
93235537Sgber * 'su' files. All other FS state is defined by those.
94235537Sgber *
95235537Sgber * It is CRC checksum'ed and time stamped.
96235537Sgber */
97235537Sgber
98235537Sgberstruct nandfs_super_root {
99235537Sgber	uint32_t	sr_sum;		/* check-sum				*/
100235537Sgber	uint16_t	sr_bytes;	/* byte count of this structure		*/
101235537Sgber	uint16_t	sr_flags;	/* reserved for flags			*/
102235537Sgber	uint64_t	sr_nongc_ctime;	/* timestamp, not for cleaner(?)	*/
103235537Sgber	struct nandfs_inode sr_dat;	/* DAT, virt->phys translation inode	*/
104235537Sgber	struct nandfs_inode sr_cpfile;	/* CP, checkpoints inode		*/
105235537Sgber	struct nandfs_inode sr_sufile;	/* SU, segment usage inode		*/
106235537Sgber};
107235537Sgber
108235537Sgber#define	NANDFS_SR_MDT_OFFSET(inode_size, i)			\
109235537Sgber	((uint32_t)&((struct nandfs_super_root *)0)->sr_dat +	\
110235537Sgber	(inode_size) * (i))
111235537Sgber
112235537Sgber#define	NANDFS_SR_DAT_OFFSET(inode_size)	NANDFS_SR_MDT_OFFSET(inode_size, 0)
113235537Sgber#define	NANDFS_SR_CPFILE_OFFSET(inode_size)	NANDFS_SR_MDT_OFFSET(inode_size, 1)
114235537Sgber#define	NANDFS_SR_SUFILE_OFFSET(inode_size)	NANDFS_SR_MDT_OFFSET(inode_size, 2)
115235537Sgber#define	NANDFS_SR_BYTES			(sizeof(struct nandfs_super_root))
116235537Sgber
117235537Sgber/*
118235537Sgber * The superblock describes the basic structure and mount history. It also
119235537Sgber * records some sizes of structures found on the disc for sanity checks.
120235537Sgber *
121235537Sgber * The superblock is stored at two places: NANDFS_SB_OFFSET_BYTES and
122235537Sgber * NANDFS_SB2_OFFSET_BYTES.
123235537Sgber */
124235537Sgber
125235537Sgber/* File system states stored on media in superblock's sbp->s_state */
126235537Sgber#define	NANDFS_VALID_FS		0x0001	/* cleanly unmounted and all is ok  */
127235537Sgber#define	NANDFS_ERROR_FS		0x0002	/* there were errors detected, fsck */
128235537Sgber#define	NANDFS_RESIZE_FS	0x0004	/* resize required, XXX unknown flag*/
129235537Sgber#define	NANDFS_MOUNT_STATE_BITS	"\20\1VALID_FS\2ERROR_FS\3RESIZE_FS"
130235537Sgber
131235537Sgber/*
132235537Sgber * Brief description of control structures:
133235537Sgber *
134235537Sgber * NANDFS_NFSAREAS first blocks contain fsdata and some amount of super blocks.
135235537Sgber * Simple round-robin policy is used in order to choose which block will
136235537Sgber * contain new super block.
137235537Sgber *
138235537Sgber * Simple case with 2 blocks:
139235537Sgber * 1: fsdata sblock1 [sblock3 [sblock5 ..]]
140235537Sgber * 2: fsdata sblock2 [sblock4 [sblock6 ..]]
141235537Sgber */
142235537Sgberstruct nandfs_fsdata {
143235537Sgber	uint16_t	f_magic;
144235537Sgber	uint16_t	f_bytes;
145235537Sgber
146235537Sgber	uint32_t	f_sum;		/* checksum of fsdata		*/
147235537Sgber	uint32_t	f_rev_level;	/* major disk format revision	*/
148235537Sgber
149235537Sgber	uint64_t	f_ctime;	/* creation time (execution time
150235537Sgber					   of newfs)			*/
151235537Sgber	/* Block size represented as: blocksize = 1 << (f_log_block_size + 10)	*/
152235537Sgber	uint32_t	f_log_block_size;
153235537Sgber
154235537Sgber	uint16_t	f_inode_size;		/* size of an inode		*/
155235537Sgber	uint16_t	f_dat_entry_size;	/* size of a dat entry		*/
156235537Sgber	uint16_t	f_checkpoint_size;	/* size of a checkpoint		*/
157235537Sgber	uint16_t	f_segment_usage_size;	/* size of a segment usage	*/
158235537Sgber
159235537Sgber	uint16_t	f_sbbytes;		/* byte count of CRC calculation
160235537Sgber						   for super blocks. s_reserved
161235537Sgber						   is excluded!			*/
162235537Sgber
163235537Sgber	uint16_t	f_errors;		/* behaviour on detecting errors	*/
164235537Sgber
165235537Sgber	uint32_t	f_erasesize;
166235537Sgber	uint64_t	f_nsegments;		/* number of segm. in filesystem	*/
167235537Sgber	nandfs_daddr_t	f_first_data_block;	/* 1st seg disk block number		*/
168235537Sgber	uint32_t	f_blocks_per_segment;	/* number of blocks per segment		*/
169235537Sgber	uint32_t	f_r_segments_percentage;	/* reserved segments percentage		*/
170235537Sgber
171235537Sgber	struct uuid	f_uuid;			/* 128-bit uuid for volume		*/
172235537Sgber	char		f_volume_name[16];	/* volume name				*/
173235537Sgber	uint32_t	f_pad[104];
174235537Sgber} __packed;
175235537Sgber
176235537Sgber#ifdef _KERNEL
177235537SgberCTASSERT(sizeof(struct nandfs_fsdata) == 512);
178235537Sgber#endif
179235537Sgber
180235537Sgberstruct nandfs_super_block {
181235537Sgber	uint16_t	s_magic;		/* magic value for identification */
182235537Sgber
183235537Sgber	uint32_t	s_sum;			/* check sum of super block       */
184235537Sgber
185235537Sgber	uint64_t	s_last_cno;		/* last checkpoint number         */
186235537Sgber	uint64_t	s_last_pseg;		/* addr part. segm. written last  */
187235537Sgber	uint64_t	s_last_seq;		/* seq.number of seg written last */
188235537Sgber	uint64_t	s_free_blocks_count;	/* free blocks count              */
189235537Sgber
190235537Sgber	uint64_t	s_mtime;		/* mount time                     */
191235537Sgber	uint64_t	s_wtime;		/* write time                     */
192235537Sgber	uint16_t	s_state;		/* file system state              */
193235537Sgber
194235537Sgber	char		s_last_mounted[64];	/* directory where last mounted   */
195235537Sgber
196235537Sgber	uint32_t	s_c_interval;		/* commit interval of segment     */
197235537Sgber	uint32_t	s_c_block_max;		/* threshold of data amount for
198235537Sgber						   the segment construction */
199235537Sgber	uint32_t	s_reserved[32];		/* padding to end of the block    */
200235537Sgber} __packed;
201235537Sgber
202235537Sgber#ifdef _KERNEL
203235537SgberCTASSERT(sizeof(struct nandfs_super_block) == 256);
204235537Sgber#endif
205235537Sgber
206235537Sgber#define	NANDFS_FSDATA_MAGIC	0xf8da
207235537Sgber#define	NANDFS_SUPER_MAGIC	0x8008
208235537Sgber
209235537Sgber#define	NANDFS_NFSAREAS		4
210235537Sgber#define	NANDFS_DATA_OFFSET_BYTES(esize)	(NANDFS_NFSAREAS * (esize))
211235537Sgber
212235537Sgber#define	NANDFS_SBLOCK_OFFSET_BYTES (sizeof(struct nandfs_fsdata))
213235537Sgber
214235537Sgber#define	NANDFS_DEF_BLOCKSIZE	4096
215235537Sgber#define	NANDFS_MIN_BLOCKSIZE	512
216235537Sgber
217235537Sgber#define	NANDFS_DEF_ERASESIZE	(2 << 16)
218235537Sgber
219235537Sgber#define	NANDFS_MIN_SEGSIZE	NANDFS_DEF_ERASESIZE
220235537Sgber
221235537Sgber#define	NANDFS_CURRENT_REV	9	/* current major revision */
222235537Sgber
223235537Sgber#define	NANDFS_FSDATA_CRC_BYTES offsetof(struct nandfs_fsdata, f_pad)
224235537Sgber/* Bytes count of super_block for CRC-calculation */
225235537Sgber#define	NANDFS_SB_BYTES  offsetof(struct nandfs_super_block, s_reserved)
226235537Sgber
227235537Sgber/* Maximal count of links to a file */
228235537Sgber#define	NANDFS_LINK_MAX		32000
229235537Sgber
230235537Sgber/*
231235537Sgber * Structure of a directory entry.
232235537Sgber *
233235537Sgber * Note that they can't span blocks; the rec_len fills out.
234235537Sgber */
235235537Sgber
236235537Sgber#define	NANDFS_NAME_LEN 255
237235537Sgberstruct nandfs_dir_entry {
238235537Sgber	uint64_t	inode;			/* inode number */
239235537Sgber	uint16_t	rec_len;		/* directory entry length */
240235537Sgber	uint8_t		name_len;		/* name length */
241235537Sgber	uint8_t		file_type;
242235537Sgber	char		name[NANDFS_NAME_LEN];	/* file name */
243235537Sgber	char		pad;
244235537Sgber};
245235537Sgber
246235537Sgber/*
247235537Sgber * NANDFS_DIR_PAD defines the directory entries boundaries
248235537Sgber *
249235537Sgber * NOTE: It must be a multiple of 8
250235537Sgber */
251235537Sgber#define	NANDFS_DIR_PAD			8
252235537Sgber#define	NANDFS_DIR_ROUND		(NANDFS_DIR_PAD - 1)
253235537Sgber#define	NANDFS_DIR_NAME_OFFSET		(offsetof(struct nandfs_dir_entry, name))
254235537Sgber#define	NANDFS_DIR_REC_LEN(name_len)					\
255235537Sgber	(((name_len) + NANDFS_DIR_NAME_OFFSET + NANDFS_DIR_ROUND)	\
256235537Sgber	& ~NANDFS_DIR_ROUND)
257235537Sgber#define	NANDFS_DIR_NAME_LEN(name_len)	\
258235537Sgber	(NANDFS_DIR_REC_LEN(name_len) - NANDFS_DIR_NAME_OFFSET)
259235537Sgber
260235537Sgber/*
261235537Sgber * NiLFS/NANDFS devides the disc into fixed length segments. Each segment is
262235537Sgber * filled with one or more partial segments of variable lengths.
263235537Sgber *
264235537Sgber * Each partial segment has a segment summary header followed by updates of
265235537Sgber * files and optionally a super root.
266235537Sgber */
267235537Sgber
268235537Sgber/*
269235537Sgber * Virtual to physical block translation information. For data blocks it maps
270235537Sgber * logical block number bi_blkoff to virtual block nr bi_vblocknr. For non
271235537Sgber * datablocks it is the virtual block number assigned to an indirect block
272235537Sgber * and has no bi_blkoff. The physical block number is the next
273235537Sgber * available data block in the partial segment after all the binfo's.
274235537Sgber */
275235537Sgberstruct nandfs_binfo_v {
276235537Sgber	uint64_t	bi_ino;		/* file's inode			     */
277235537Sgber	uint64_t	bi_vblocknr;	/* assigned virtual block number     */
278235537Sgber	uint64_t	bi_blkoff;	/* for file's logical block number   */
279235537Sgber};
280235537Sgber
281235537Sgber/*
282235537Sgber * DAT allocation. For data blocks just the logical block number that maps on
283235537Sgber * the next available data block in the partial segment after the binfo's.
284235537Sgber */
285235537Sgberstruct nandfs_binfo_dat {
286235537Sgber	uint64_t	bi_ino;
287235537Sgber	uint64_t	bi_blkoff;	/* DAT file's logical block number */
288235537Sgber	uint8_t		bi_level;	/* whether this is meta block */
289235537Sgber	uint8_t		bi_pad[7];
290235537Sgber};
291235537Sgber
292235537Sgber#ifdef _KERNEL
293235537SgberCTASSERT(sizeof(struct nandfs_binfo_v) == sizeof(struct nandfs_binfo_dat));
294235537Sgber#endif
295235537Sgber
296235537Sgber/* Convenience union for both types of binfo's */
297235537Sgberunion nandfs_binfo {
298235537Sgber	struct nandfs_binfo_v bi_v;
299235537Sgber	struct nandfs_binfo_dat bi_dat;
300235537Sgber};
301235537Sgber
302235537Sgber/* Indirect buffers path */
303235537Sgberstruct nandfs_indir {
304235537Sgber	nandfs_daddr_t	in_lbn;
305235537Sgber	int		in_off;
306235537Sgber};
307235537Sgber
308235537Sgber/* The (partial) segment summary */
309235537Sgberstruct nandfs_segment_summary {
310235537Sgber	uint32_t	ss_datasum;	/* CRC of complete data block        */
311235537Sgber	uint32_t	ss_sumsum;	/* CRC of segment summary only       */
312235537Sgber	uint32_t	ss_magic;	/* magic to identify segment summary */
313235537Sgber	uint16_t	ss_bytes;	/* size of segment summary structure */
314235537Sgber	uint16_t	ss_flags;	/* NANDFS_SS_* flags                  */
315235537Sgber	uint64_t	ss_seq;		/* sequence number of this segm. sum */
316235537Sgber	uint64_t	ss_create;	/* creation timestamp in seconds     */
317235537Sgber	uint64_t	ss_next;	/* blocknumber of next segment       */
318235537Sgber	uint32_t	ss_nblocks;	/* number of blocks used by summary  */
319235537Sgber	uint32_t	ss_nbinfos;	/* number of binfo structures	     */
320235537Sgber	uint32_t	ss_sumbytes;	/* total size of segment summary     */
321235537Sgber	uint32_t	ss_pad;
322235537Sgber	/* stream of binfo structures */
323235537Sgber};
324235537Sgber
325235537Sgber#define	NANDFS_SEGSUM_MAGIC	0x8e680011	/* segment summary magic number */
326235537Sgber
327235537Sgber/* Segment summary flags */
328235537Sgber#define	NANDFS_SS_LOGBGN	0x0001	/* begins a logical segment */
329235537Sgber#define	NANDFS_SS_LOGEND	0x0002	/* ends a logical segment */
330235537Sgber#define	NANDFS_SS_SR		0x0004	/* has super root */
331235537Sgber#define	NANDFS_SS_SYNDT		0x0008	/* includes data only updates */
332235537Sgber#define	NANDFS_SS_GC		0x0010	/* segment written for cleaner operation */
333235537Sgber#define	NANDFS_SS_FLAG_BITS	"\20\1LOGBGN\2LOGEND\3SR\4SYNDT\5GC"
334235537Sgber
335235537Sgber/* Segment summary constrains */
336235537Sgber#define	NANDFS_SEG_MIN_BLOCKS	16	/* minimum number of blocks in a
337235537Sgber					   full segment */
338235537Sgber#define	NANDFS_PSEG_MIN_BLOCKS	2	/* minimum number of blocks in a
339235537Sgber					   partial segment */
340235537Sgber#define	NANDFS_MIN_NRSVSEGS	8	/* minimum number of reserved
341235537Sgber					   segments */
342235537Sgber
343235537Sgber/*
344235537Sgber * Structure of DAT/inode file.
345235537Sgber *
346235537Sgber * A DAT file is devided into groups. The maximum number of groups is the
347235537Sgber * number of block group descriptors that fit into one block; this descriptor
348235537Sgber * only gives the number of free entries in the associated group.
349235537Sgber *
350235537Sgber * Each group has a block sized bitmap indicating if an entry is taken or
351235537Sgber * empty. Each bit stands for a DAT entry.
352235537Sgber *
353235537Sgber * The inode file has exactly the same format only the entries are inode
354235537Sgber * entries.
355235537Sgber */
356235537Sgber
357235537Sgberstruct nandfs_block_group_desc {
358235537Sgber	uint32_t	bg_nfrees;	/* num. free entries in block group  */
359235537Sgber};
360235537Sgber
361235537Sgber/* DAT entry in a super root's DAT file */
362235537Sgberstruct nandfs_dat_entry {
363235537Sgber	uint64_t	de_blocknr;	/* block number                      */
364235537Sgber	uint64_t	de_start;	/* valid from checkpoint             */
365235537Sgber	uint64_t	de_end;		/* valid till checkpoint             */
366235537Sgber	uint64_t	de_rsv;		/* reserved for future use           */
367235537Sgber};
368235537Sgber
369235537Sgber/*
370235537Sgber * Structure of CP file.
371235537Sgber *
372235537Sgber * A snapshot is just a checkpoint only it's protected against removal by the
373235537Sgber * cleaner. The snapshots are kept on a double linked list of checkpoints.
374235537Sgber */
375235537Sgberstruct nandfs_snapshot_list {
376235537Sgber	uint64_t	ssl_next;	/* checkpoint nr. forward */
377235537Sgber	uint64_t	ssl_prev;	/* checkpoint nr. back    */
378235537Sgber};
379235537Sgber
380235537Sgber/* Checkpoint entry structure */
381235537Sgberstruct nandfs_checkpoint {
382235537Sgber	uint32_t	cp_flags;		/* NANDFS_CHECKPOINT_* flags          */
383235537Sgber	uint32_t	cp_checkpoints_count;	/* ZERO, not used anymore?           */
384235537Sgber	struct nandfs_snapshot_list cp_snapshot_list; /* list of snapshots   */
385235537Sgber	uint64_t	cp_cno;			/* checkpoint number                 */
386235537Sgber	uint64_t	cp_create;		/* creation timestamp                */
387235537Sgber	uint64_t	cp_nblk_inc;		/* number of blocks incremented      */
388235537Sgber	uint64_t	cp_blocks_count;	/* reserved (might be deleted)       */
389235537Sgber	struct nandfs_inode cp_ifile_inode;	/* inode file inode          */
390235537Sgber};
391235537Sgber
392235537Sgber/* Checkpoint flags */
393235537Sgber#define	NANDFS_CHECKPOINT_SNAPSHOT	1
394235537Sgber#define	NANDFS_CHECKPOINT_INVALID	2
395235537Sgber#define	NANDFS_CHECKPOINT_SKETCH	4
396235537Sgber#define	NANDFS_CHECKPOINT_MINOR		8
397235537Sgber#define	NANDFS_CHECKPOINT_BITS		"\20\1SNAPSHOT\2INVALID\3SKETCH\4MINOR"
398235537Sgber
399235537Sgber/* Header of the checkpoint file */
400235537Sgberstruct nandfs_cpfile_header {
401235537Sgber	uint64_t	ch_ncheckpoints;	/* number of checkpoints             */
402235537Sgber	uint64_t	ch_nsnapshots;	/* number of snapshots               */
403235537Sgber	struct nandfs_snapshot_list ch_snapshot_list;	/* snapshot list     */
404235537Sgber};
405235537Sgber
406235537Sgber#define	NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET		\
407235537Sgber	((sizeof(struct nandfs_cpfile_header) +		\
408235537Sgber	sizeof(struct nandfs_checkpoint) - 1) /		\
409235537Sgber	sizeof(struct nandfs_checkpoint))
410235537Sgber
411235537Sgber
412235537Sgber#define NANDFS_NOSEGMENT        0xffffffff
413235537Sgber
414235537Sgber/*
415235537Sgber * Structure of SU file.
416235537Sgber *
417235537Sgber * The segment usage file sums up how each of the segments are used. They are
418235537Sgber * indexed by their segment number.
419235537Sgber */
420235537Sgber
421235537Sgber/* Segment usage entry */
422235537Sgberstruct nandfs_segment_usage {
423235537Sgber	uint64_t	su_lastmod;	/* last modified timestamp           */
424235537Sgber	uint32_t	su_nblocks;	/* number of blocks in segment       */
425235537Sgber	uint32_t	su_flags;	/* NANDFS_SEGMENT_USAGE_* flags       */
426235537Sgber};
427235537Sgber
428235537Sgber/* Segment usage flag */
429235537Sgber#define	NANDFS_SEGMENT_USAGE_ACTIVE	1
430235537Sgber#define	NANDFS_SEGMENT_USAGE_DIRTY	2
431235537Sgber#define	NANDFS_SEGMENT_USAGE_ERROR	4
432235537Sgber#define	NANDFS_SEGMENT_USAGE_GC		8
433235537Sgber#define	NANDFS_SEGMENT_USAGE_BITS	"\20\1ACTIVE\2DIRTY\3ERROR"
434235537Sgber
435235537Sgber/* Header of the segment usage file */
436235537Sgberstruct nandfs_sufile_header {
437235537Sgber	uint64_t	sh_ncleansegs;	/* number of segments marked clean   */
438235537Sgber	uint64_t	sh_ndirtysegs;	/* number of segments marked dirty   */
439235537Sgber	uint64_t	sh_last_alloc;	/* last allocated segment number     */
440235537Sgber};
441235537Sgber
442235537Sgber#define	NANDFS_SUFILE_FIRST_SEGMENT_USAGE_OFFSET	\
443235537Sgber	((sizeof(struct nandfs_sufile_header) +		\
444235537Sgber	sizeof(struct nandfs_segment_usage) - 1) /	\
445235537Sgber	sizeof(struct nandfs_segment_usage))
446235537Sgber
447235537Sgberstruct nandfs_seg_stat {
448235537Sgber	uint64_t	nss_nsegs;
449235537Sgber	uint64_t	nss_ncleansegs;
450235537Sgber	uint64_t	nss_ndirtysegs;
451235537Sgber	uint64_t	nss_ctime;
452235537Sgber	uint64_t	nss_nongc_ctime;
453235537Sgber	uint64_t	nss_prot_seq;
454235537Sgber};
455235537Sgber
456235537Sgberenum {
457235537Sgber	NANDFS_CHECKPOINT,
458235537Sgber	NANDFS_SNAPSHOT
459235537Sgber};
460235537Sgber
461235537Sgber#define	NANDFS_CPINFO_MAX		512
462235537Sgber
463235537Sgberstruct nandfs_cpinfo {
464235537Sgber	uint32_t	nci_flags;
465235537Sgber	uint32_t	nci_pad;
466235537Sgber	uint64_t	nci_cno;
467235537Sgber	uint64_t	nci_create;
468235537Sgber	uint64_t	nci_nblk_inc;
469235537Sgber	uint64_t	nci_blocks_count;
470235537Sgber	uint64_t	nci_next;
471235537Sgber};
472235537Sgber
473235537Sgber#define	NANDFS_SEGMENTS_MAX	512
474235537Sgber
475235537Sgberstruct nandfs_suinfo {
476235537Sgber	uint64_t	nsi_num;
477235537Sgber	uint64_t	nsi_lastmod;
478235537Sgber	uint32_t	nsi_blocks;
479235537Sgber	uint32_t	nsi_flags;
480235537Sgber};
481235537Sgber
482235537Sgber#define	NANDFS_VINFO_MAX	512
483235537Sgber
484235537Sgberstruct nandfs_vinfo {
485235537Sgber	uint64_t	nvi_ino;
486235537Sgber	uint64_t	nvi_vblocknr;
487235537Sgber	uint64_t	nvi_start;
488235537Sgber	uint64_t	nvi_end;
489235537Sgber	uint64_t	nvi_blocknr;
490235537Sgber	int		nvi_alive;
491235537Sgber};
492235537Sgber
493235537Sgberstruct nandfs_cpmode {
494235537Sgber	uint64_t	ncpm_cno;
495235537Sgber	uint32_t	ncpm_mode;
496235537Sgber	uint32_t	ncpm_pad;
497235537Sgber};
498235537Sgber
499235537Sgberstruct nandfs_argv {
500235537Sgber	uint64_t	nv_base;
501235537Sgber	uint32_t	nv_nmembs;
502235537Sgber	uint16_t	nv_size;
503235537Sgber	uint16_t	nv_flags;
504235537Sgber	uint64_t	nv_index;
505235537Sgber};
506235537Sgber
507235537Sgberstruct nandfs_cpstat {
508235537Sgber	uint64_t	ncp_cno;
509235537Sgber	uint64_t	ncp_ncps;
510235537Sgber	uint64_t	ncp_nss;
511235537Sgber};
512235537Sgber
513235537Sgberstruct nandfs_period {
514235537Sgber	uint64_t	p_start;
515235537Sgber	uint64_t	p_end;
516235537Sgber};
517235537Sgber
518235537Sgberstruct nandfs_vdesc {
519235537Sgber	uint64_t	vd_ino;
520235537Sgber	uint64_t	vd_cno;
521235537Sgber	uint64_t	vd_vblocknr;
522235537Sgber	struct nandfs_period	vd_period;
523235537Sgber	uint64_t	vd_blocknr;
524235537Sgber	uint64_t	vd_offset;
525235537Sgber	uint32_t	vd_flags;
526235537Sgber	uint32_t	vd_pad;
527235537Sgber};
528235537Sgber
529235537Sgberstruct nandfs_bdesc {
530235537Sgber	uint64_t	bd_ino;
531235537Sgber	uint64_t	bd_oblocknr;
532235537Sgber	uint64_t	bd_blocknr;
533235537Sgber	uint64_t	bd_offset;
534235537Sgber	uint32_t	bd_level;
535235537Sgber	uint32_t	bd_alive;
536235537Sgber};
537235537Sgber
538235537Sgber#ifndef _KERNEL
539235537Sgber#ifndef	MNAMELEN
540235537Sgber#define	MNAMELEN	88
541235537Sgber#endif
542235537Sgber#endif
543235537Sgber
544235537Sgberstruct nandfs_fsinfo {
545235537Sgber	struct nandfs_fsdata		fs_fsdata;
546235537Sgber	struct nandfs_super_block	fs_super;
547235537Sgber	char				fs_dev[MNAMELEN];
548235537Sgber};
549235537Sgber
550235537Sgber#define	NANDFS_MAX_MOUNTS	65535
551235537Sgber
552235537Sgber#define	NANDFS_IOCTL_GET_SUSTAT		_IOR('N', 100, struct nandfs_seg_stat)
553235537Sgber#define	NANDFS_IOCTL_CHANGE_CPMODE	_IOWR('N', 101, struct nandfs_cpmode)
554235537Sgber#define	NANDFS_IOCTL_GET_CPINFO		_IOWR('N', 102, struct nandfs_argv)
555235537Sgber#define	NANDFS_IOCTL_DELETE_CP		_IOWR('N', 103, uint64_t[2])
556235537Sgber#define	NANDFS_IOCTL_GET_CPSTAT		_IOR('N', 104, struct nandfs_cpstat)
557235537Sgber#define	NANDFS_IOCTL_GET_SUINFO		_IOWR('N', 105, struct nandfs_argv)
558235537Sgber#define	NANDFS_IOCTL_GET_VINFO		_IOWR('N', 106, struct nandfs_argv)
559235537Sgber#define	NANDFS_IOCTL_GET_BDESCS		_IOWR('N', 107, struct nandfs_argv)
560235537Sgber#define	NANDFS_IOCTL_GET_FSINFO		_IOR('N', 108, struct nandfs_fsinfo)
561235537Sgber#define	NANDFS_IOCTL_MAKE_SNAP		_IOWR('N', 109, uint64_t)
562235537Sgber#define	NANDFS_IOCTL_DELETE_SNAP	_IOWR('N', 110, uint64_t)
563235537Sgber#define	NANDFS_IOCTL_SYNC		_IOWR('N', 111, uint64_t)
564235537Sgber
565235537Sgber#endif /* _NANDFS_FS_H */
566