xref: /dragonfly/sys/vfs/hammer/hammer_ioctl.h (revision c6f73aab)
1 /*
2  * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
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
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $DragonFly: src/sys/vfs/hammer/hammer_ioctl.h,v 1.23 2008/11/13 02:18:43 dillon Exp $
35  */
36 /*
37  * HAMMER ioctl's.  This file can be #included from userland
38  */
39 
40 #ifndef VFS_HAMMER_IOCTL_H_
41 #define VFS_HAMMER_IOCTL_H_
42 
43 #include <sys/param.h>
44 #include <sys/ioccom.h>
45 
46 #include "hammer_disk.h"
47 
48 /*
49  * Common HAMMER ioctl header
50  *
51  * Global flags are stored in the upper 16 bits.
52  */
53 struct hammer_ioc_head {
54 	int32_t		flags;
55 	int32_t		error;
56 	int32_t		reserved02[4];
57 };
58 
59 #define HAMMER_IOC_HEAD_ERROR	0x00008000
60 #define HAMMER_IOC_HEAD_INTR	0x00010000
61 #define HAMMER_IOC_DO_BTREE	0x00020000	/* reblocker */
62 #define HAMMER_IOC_DO_INODES	0x00040000	/* reblocker */
63 #define HAMMER_IOC_DO_DATA	0x00080000	/* reblocker */
64 #define HAMMER_IOC_DO_DIRS	0x00100000	/* reblocker */
65 
66 #define HAMMER_IOC_DO_FLAGS	(HAMMER_IOC_DO_BTREE |	\
67 				 HAMMER_IOC_DO_INODES |	\
68 				 HAMMER_IOC_DO_DATA |	\
69 				 HAMMER_IOC_DO_DIRS)
70 
71 /*
72  * HAMMERIOC_PRUNE
73  *
74  * beg/end TID ranges in the element array must be sorted in descending
75  * order, with the most recent (highest) range at elms[0].
76  */
77 struct hammer_ioc_prune_elm {
78 	hammer_tid_t	beg_tid;	/* starting tid */
79 	hammer_tid_t	end_tid;	/* ending tid (non inclusive) */
80 	hammer_tid_t	mod_tid;	/* modulo */
81 };
82 
83 #define HAMMER_MAX_PRUNE_ELMS	(1024*1024/24)
84 
85 struct hammer_ioc_prune {
86 	struct hammer_ioc_head head;
87 	int		nelms;
88 	int		reserved01;
89 
90 	struct hammer_base_elm key_beg;	/* stop forward scan (reverse scan) */
91 	struct hammer_base_elm key_end;	/* start forward scan (reverse scan) */
92 	struct hammer_base_elm key_cur;	/* scan interruption point */
93 
94 	int64_t		stat_scanrecords;/* number of records scanned */
95 	int64_t		stat_rawrecords; /* number of raw records pruned */
96 	int64_t		stat_dirrecords; /* number of dir records pruned */
97 	int64_t		stat_bytes;	 /* number of data bytes pruned */
98 	int64_t		stat_realignments; /* number of raw records realigned */
99 	hammer_tid_t	stat_oldest_tid; /* oldest create_tid encountered */
100 	int64_t		reserved02[6];
101 	struct hammer_ioc_prune_elm *elms; /* user supplied array */
102 };
103 
104 #define HAMMER_IOC_PRUNE_ALL	0x0001
105 
106 /*
107  * HAMMERIOC_REPACK
108  *
109  * Forward scan leaf-up B-Tree packing.  The saturation point is typically
110  * set to HAMMER_BTREE_LEAF_ELMS * 2 / 3 for 2/3rds fill.  Referenced nodes
111  * have to be skipped, we can't track cursors through pack ops.
112  */
113 struct hammer_ioc_rebalance {
114 	struct hammer_ioc_head head;
115 	int		saturation;	/* saturation pt elements/node */
116 	int		reserved02;
117 
118 	struct hammer_base_elm key_beg;	/* start forward scan */
119 	struct hammer_base_elm key_end; /* stop forward scan (inclusive) */
120 	struct hammer_base_elm key_cur; /* current scan index */
121 
122 	int64_t		stat_ncount;	/* number of nodes scanned */
123 	int64_t		stat_deletions; /* number of nodes deleted */
124 	int64_t		stat_collisions;/* number of collision retries */
125 	int64_t		stat_nrebal;	/* number of btree-nodes rebalanced */
126 	int32_t		allpfs;		/* rebalance all PFS if set */
127 	int32_t		unused04;
128 };
129 
130 /*
131  * HAMMERIOC_GETHISTORY
132  *
133  * Retrieve an array of ordered transaction ids >= beg and < end indicating
134  * all changes made to the specified object's inode up to the
135  * maximum.
136  *
137  * If ATKEY is set the key field indicates a particular key within the
138  * inode to retrieve the history for.
139  *
140  * On return count is set to the number of elements returned, nxt_tid is
141  * set to the tid the caller should store in beg_tid to continue the
142  * iteration, and nxt_key is set to the nearest key boundary > key
143  * indicating the range key - nxt_key (nxt_key non-inclusive) the tid
144  * array represents.  Also obj_id is set to the object's inode number.
145  *
146  * nxt_key can be used to iterate the contents of a single file but should
147  * not be stored in key until all modifications at key have been retrieved.
148  * To work properly nxt_key should be initialized to HAMMER_MAX_KEY.
149  * Successive ioctl() calls will reduce nxt_key as appropriate so at the
150  * end of your iterating for 'key', key to nxt_key will represent the
151  * shortest range of keys that all returned TIDs apply to.
152  */
153 
154 #define HAMMER_MAX_HISTORY_ELMS	64
155 
156 typedef struct hammer_ioc_hist_entry {
157 	hammer_tid_t	tid;
158 	u_int32_t	time32;
159 	u_int32_t	unused;
160 } *hammer_ioc_hist_entry_t;
161 
162 struct hammer_ioc_history {
163 	struct hammer_ioc_head head;
164 	int64_t		obj_id;
165 	hammer_tid_t	beg_tid;
166 	hammer_tid_t	nxt_tid;
167 	hammer_tid_t	end_tid;
168 	int64_t		key;
169 	int64_t		nxt_key;
170 	int		count;
171 	int		reserve01;
172 	struct hammer_ioc_hist_entry hist_ary[HAMMER_MAX_HISTORY_ELMS];
173 };
174 
175 #define HAMMER_IOC_HISTORY_ATKEY	0x0001
176 #define HAMMER_IOC_HISTORY_NEXT_TID	0x0002	/* iterate via nxt_tid */
177 #define HAMMER_IOC_HISTORY_NEXT_KEY	0x0004	/* iterate via nxt_key */
178 #define HAMMER_IOC_HISTORY_EOF		0x0008	/* no more keys */
179 #define HAMMER_IOC_HISTORY_UNSYNCED	0x0010	/* unsynced info in inode */
180 
181 /*
182  * Reblock request
183  */
184 struct hammer_ioc_reblock {
185 	struct hammer_ioc_head head;
186 	int32_t		free_level;		/* 0 for maximum compaction */
187 	u_int32_t	reserved01;
188 
189 	struct hammer_base_elm key_beg;		/* start forward scan */
190 	struct hammer_base_elm key_end;		/* stop forward scan */
191 	struct hammer_base_elm key_cur;		/* scan interruption point */
192 
193 	int64_t		btree_count;		/* B-Tree nodes checked */
194 	int64_t		reserved02a;
195 	int64_t		data_count;		/* Data segments checked */
196 	int64_t		data_byte_count;	/* Data bytes checked */
197 
198 	int64_t		btree_moves;		/* B-Tree nodes moved */
199 	int64_t		reserved02b;
200 	int64_t		data_moves;		/* Data segments moved */
201 	int64_t		data_byte_moves;	/* Data bytes moved */
202 
203 	int16_t		allpfs;			/* Reblock all PFS if set */
204 	int16_t		vol_no;			/* Volume to reblock if set */
205 	int32_t		unused03;
206 };
207 
208 /*
209  * HAMMERIOC_SYNCTID
210  */
211 enum hammer_synctid_op {
212 	HAMMER_SYNCTID_NONE,	/* no sync (TID will not be accurate) */
213 	HAMMER_SYNCTID_ASYNC,	/* async (TID will not be accurate) */
214 	HAMMER_SYNCTID_SYNC1,	/* single sync - might undo after crash */
215 	HAMMER_SYNCTID_SYNC2	/* double sync - guarantee no undo */
216 };
217 
218 struct hammer_ioc_synctid {
219 	struct hammer_ioc_head	head;
220 	enum hammer_synctid_op	op;
221 	hammer_tid_t		tid;
222 };
223 
224 /*
225  * HAMMERIOC_GET_INFO
226  */
227 struct hammer_ioc_info {
228 	struct hammer_ioc_head		head;
229 
230 	char		vol_name[64];
231 	uuid_t		vol_fsid;
232 	uuid_t		vol_fstype;
233 
234 	int		version;
235 	int		nvolumes;
236 	int		reserved01;
237 	int		reserved02;
238 
239 	int64_t		bigblocks;
240 	int64_t		freebigblocks;
241 	int64_t		rsvbigblocks;
242 	int64_t		inodes;
243 
244 	int64_t		reservedext[16];
245 };
246 
247 /*
248  * HAMMERIOC_PFS_ITERATE
249  */
250 struct hammer_ioc_pfs_iterate {
251 	struct hammer_ioc_head  head;
252 	uint32_t pos;  /* set PFS id here */
253 	struct hammer_pseudofs_data *ondisk;
254 };
255 
256 /*
257  * HAMMERIOC_GET_PSEUDOFS
258  * HAMMERIOC_SET_PSEUDOFS
259  */
260 struct hammer_ioc_pseudofs_rw {
261 	struct hammer_ioc_head	head;
262 	int			pfs_id;
263 	u_int32_t		bytes;
264 	u_int32_t		version;
265 	u_int32_t		flags;
266 	struct hammer_pseudofs_data *ondisk;
267 };
268 
269 #define HAMMER_IOC_PSEUDOFS_VERSION	1
270 
271 #define HAMMER_IOC_PFS_SYNC_BEG		0x0001
272 #define HAMMER_IOC_PFS_SYNC_END		0x0002
273 #define HAMMER_IOC_PFS_SHARED_UUID	0x0004
274 #define HAMMER_IOC_PFS_MIRROR_UUID	0x0008
275 #define HAMMER_IOC_PFS_MASTER_ID	0x0010
276 #define HAMMER_IOC_PFS_MIRROR_FLAGS	0x0020
277 #define HAMMER_IOC_PFS_LABEL		0x0040
278 
279 #define HAMMER_MAX_PFS			65536
280 
281 /*
282  * HAMMERIOC_MIRROR_READ/WRITE
283  */
284 struct hammer_ioc_mirror_rw {
285 	struct hammer_ioc_head	head;
286 	struct hammer_base_elm	key_beg;	/* start forward scan */
287 	struct hammer_base_elm	key_end;	/* stop forward scan */
288 	struct hammer_base_elm	key_cur;	/* interruption point */
289 	hammer_tid_t		tid_beg;	/* filter modification range */
290 	hammer_tid_t		tid_end;	/* filter modification range */
291 	void			*ubuf;		/* user buffer */
292 	int			count;		/* current size */
293 	int			size;		/* max size */
294 	int			pfs_id;		/* PFS id being read/written */
295 	int			reserved01;
296 	uuid_t			shared_uuid;	/* validator for safety */
297 };
298 
299 #define HAMMER_IOC_MIRROR_NODATA	0x0001	/* do not include bulk data */
300 
301 /*
302  * NOTE: crc is for the data block starting at rec_size, not including the
303  * data[] array.
304  */
305 struct hammer_ioc_mrecord_head {
306 	u_int32_t		signature;	/* signature for byte order */
307 	u_int32_t		rec_crc;
308 	u_int32_t		rec_size;
309 	u_int32_t		type;
310 	/* extended */
311 };
312 
313 typedef struct hammer_ioc_mrecord_head *hammer_ioc_mrecord_head_t;
314 
315 struct hammer_ioc_mrecord_rec {
316 	struct hammer_ioc_mrecord_head	head;
317 	struct hammer_btree_leaf_elm	leaf;
318 	/* extended by data */
319 };
320 
321 struct hammer_ioc_mrecord_skip {
322 	struct hammer_ioc_mrecord_head	head;
323 	struct hammer_base_elm		skip_beg;
324 	struct hammer_base_elm		skip_end;
325 };
326 
327 struct hammer_ioc_mrecord_update {
328 	struct hammer_ioc_mrecord_head	head;
329 	hammer_tid_t			tid;
330 };
331 
332 struct hammer_ioc_mrecord_sync {
333 	struct hammer_ioc_mrecord_head	head;
334 };
335 
336 struct hammer_ioc_mrecord_pfs {
337 	struct hammer_ioc_mrecord_head	head;
338 	u_int32_t			version;
339 	u_int32_t			reserved01;
340 	struct hammer_pseudofs_data	pfsd;
341 };
342 
343 struct hammer_ioc_version {
344 	struct hammer_ioc_head head;
345 	u_int32_t		cur_version;
346 	u_int32_t		min_version;
347 	u_int32_t		wip_version;
348 	u_int32_t		max_version;
349 	char			description[64];
350 };
351 
352 struct hammer_ioc_volume {
353 	struct hammer_ioc_head head;
354 	char			device_name[MAXPATHLEN];
355 	int64_t			vol_size;
356 	int64_t			boot_area_size;
357 	int64_t			mem_area_size;
358 };
359 
360 struct hammer_ioc_volume_list {
361 	struct hammer_ioc_volume *vols;
362 	int nvols;
363 };
364 
365 union hammer_ioc_mrecord_any {
366 	struct hammer_ioc_mrecord_head	head;
367 	struct hammer_ioc_mrecord_rec	rec;
368 	struct hammer_ioc_mrecord_skip	skip;
369 	struct hammer_ioc_mrecord_update update;
370 	struct hammer_ioc_mrecord_update sync;
371 	struct hammer_ioc_mrecord_pfs	pfs;
372 	struct hammer_ioc_version	version;
373 };
374 
375 typedef union hammer_ioc_mrecord_any *hammer_ioc_mrecord_any_t;
376 
377 /*
378  * MREC types.  Flags are in the upper 16 bits but some are also included
379  * in the type mask to force them into any switch() on the type.
380  *
381  * NOTE: Any record whos data is CRC-errored will have HAMMER_MRECF_CRC set,
382  *	 and the bit is also part of the type mask.
383  */
384 #define HAMMER_MREC_TYPE_RESERVED	0
385 #define HAMMER_MREC_TYPE_REC		1	/* record w/ data */
386 #define HAMMER_MREC_TYPE_PFSD		2	/* (userland only) */
387 #define HAMMER_MREC_TYPE_UPDATE		3	/* (userland only) */
388 #define HAMMER_MREC_TYPE_SYNC		4	/* (userland only) */
389 #define HAMMER_MREC_TYPE_SKIP		5	/* skip-range */
390 #define HAMMER_MREC_TYPE_PASS		6	/* record for cmp only (pass) */
391 #define HAMMER_MREC_TYPE_TERM		7	/* (userland only) */
392 #define HAMMER_MREC_TYPE_IDLE		8	/* (userland only) */
393 
394 #define HAMMER_MREC_TYPE_REC_BADCRC	(HAMMER_MREC_TYPE_REC | \
395 					 HAMMER_MRECF_CRC_ERROR)
396 #define HAMMER_MREC_TYPE_REC_NODATA	(HAMMER_MREC_TYPE_REC | \
397 					 HAMMER_MRECF_NODATA)
398 
399 #define HAMMER_MRECF_TYPE_LOMASK	0x000000FF
400 #define HAMMER_MRECF_TYPE_MASK		0x800000FF
401 #define HAMMER_MRECF_CRC_ERROR		0x80000000
402 
403 #define HAMMER_MRECF_DATA_CRC_BAD	0x40000000
404 #define HAMMER_MRECF_RECD_CRC_BAD	0x20000000
405 #define HAMMER_MRECF_NODATA		0x10000000
406 
407 #define HAMMER_MREC_CRCOFF	(offsetof(struct hammer_ioc_mrecord_head, rec_size))
408 #define HAMMER_MREC_HEADSIZE	sizeof(struct hammer_ioc_mrecord_head)
409 
410 #define HAMMER_IOC_MIRROR_SIGNATURE	0x4dd97272U
411 #define HAMMER_IOC_MIRROR_SIGNATURE_REV	0x7272d94dU
412 
413 /*
414  * HAMMERIOC_ADD_SNAPSHOT - Add snapshot tid(s).
415  * HAMMERIOC_DEL_SNAPSHOT - Delete snapshot tids.
416  * HAMMERIOC_GET_SNAPSHOT - Get/continue retrieving snapshot tids.
417  *			    (finds restart point based on last snaps[] entry)
418  *
419  * These are per-PFS operations.
420  *
421  * NOTE: There is no limit on the number of snapshots, but there is a limit
422  *	 on how many can be set or returned in each ioctl.
423  *
424  * NOTE: ADD and DEL start at snap->index.  If an error occurs the index will
425  *	 point at the errored record.  snap->index must be set to 0 for GET.
426  */
427 #define HAMMER_SNAPS_PER_IOCTL		16
428 
429 #define HAMMER_IOC_SNAPSHOT_EOF		0x0008	/* no more keys */
430 
431 struct hammer_ioc_snapshot {
432 	struct hammer_ioc_head	head;
433 	int			unused01;
434 	u_int32_t		index;
435 	u_int32_t		count;
436 	struct hammer_snapshot_data snaps[HAMMER_SNAPS_PER_IOCTL];
437 };
438 
439 /*
440  * HAMMERIOC_GET_CONFIG
441  * HAMMERIOC_SET_CONFIG
442  *
443  * The configuration space is a freeform nul-terminated string, typically
444  * a text file.  It is per-PFS and used by the 'hammer cleanup' utility.
445  *
446  * The configuration space is NOT mirrored.  mirror-write will ignore
447  * configuration space records.
448  */
449 struct hammer_ioc_config {
450 	struct hammer_ioc_head	head;
451 	u_int32_t		reserved01;
452 	u_int32_t		reserved02;
453 	u_int64_t		reserved03[4];
454 	struct hammer_config_data config;
455 };
456 
457 /*
458  * HAMMERIOC_DEDUP
459  */
460 struct hammer_ioc_dedup {
461 	struct hammer_ioc_head	head;
462 	struct hammer_base_elm	elm1;
463 	struct hammer_base_elm	elm2; /* candidate for dedup */
464 };
465 
466 #define HAMMER_IOC_DEDUP_CMP_FAILURE	0x0001 /* verification failed */
467 #define HAMMER_IOC_DEDUP_UNDERFLOW	0x0002 /* big-block underflow */
468 #define HAMMER_IOC_DEDUP_INVALID_ZONE	0x0004 /* we can't dedup all zones */
469 
470 /*
471  * HAMMERIOC_GET_DATA
472  */
473 struct hammer_ioc_data {
474 	struct hammer_ioc_head		head;
475 	struct hammer_base_elm		elm;	/* btree key to lookup */
476 	struct hammer_btree_leaf_elm	leaf;
477 	void				*ubuf;	/* user buffer */
478 	int				size;	/* max size */
479 };
480 
481 /*
482  * Ioctl cmd ids
483  */
484 #define HAMMERIOC_PRUNE		_IOWR('h',1,struct hammer_ioc_prune)
485 #define HAMMERIOC_GETHISTORY	_IOWR('h',2,struct hammer_ioc_history)
486 #define HAMMERIOC_REBLOCK	_IOWR('h',3,struct hammer_ioc_reblock)
487 #define HAMMERIOC_SYNCTID	_IOWR('h',4,struct hammer_ioc_synctid)
488 #define HAMMERIOC_SET_PSEUDOFS	_IOWR('h',5,struct hammer_ioc_pseudofs_rw)
489 #define HAMMERIOC_GET_PSEUDOFS	_IOWR('h',6,struct hammer_ioc_pseudofs_rw)
490 #define HAMMERIOC_MIRROR_READ	_IOWR('h',7,struct hammer_ioc_mirror_rw)
491 #define HAMMERIOC_MIRROR_WRITE	_IOWR('h',8,struct hammer_ioc_mirror_rw)
492 #define HAMMERIOC_UPG_PSEUDOFS	_IOWR('h',9,struct hammer_ioc_pseudofs_rw)
493 #define HAMMERIOC_DGD_PSEUDOFS	_IOWR('h',10,struct hammer_ioc_pseudofs_rw)
494 #define HAMMERIOC_RMR_PSEUDOFS	_IOWR('h',11,struct hammer_ioc_pseudofs_rw)
495 #define HAMMERIOC_WAI_PSEUDOFS	_IOWR('h',12,struct hammer_ioc_pseudofs_rw)
496 #define HAMMERIOC_GET_VERSION	_IOWR('h',13,struct hammer_ioc_version)
497 #define HAMMERIOC_SET_VERSION	_IOWR('h',14,struct hammer_ioc_version)
498 #define HAMMERIOC_REBALANCE	_IOWR('h',15,struct hammer_ioc_rebalance)
499 #define HAMMERIOC_GET_INFO	_IOR('h',16,struct hammer_ioc_info)
500 #define HAMMERIOC_ADD_VOLUME	_IOWR('h',17,struct hammer_ioc_volume)
501 #define HAMMERIOC_ADD_SNAPSHOT	_IOWR('h',18,struct hammer_ioc_snapshot)
502 #define HAMMERIOC_DEL_SNAPSHOT	_IOWR('h',19,struct hammer_ioc_snapshot)
503 #define HAMMERIOC_GET_SNAPSHOT	_IOWR('h',20,struct hammer_ioc_snapshot)
504 #define HAMMERIOC_GET_CONFIG	_IOWR('h',21,struct hammer_ioc_config)
505 #define HAMMERIOC_SET_CONFIG	_IOWR('h',22,struct hammer_ioc_config)
506 #define HAMMERIOC_DEL_VOLUME	_IOWR('h',24,struct hammer_ioc_volume)
507 #define HAMMERIOC_DEDUP		_IOWR('h',25,struct hammer_ioc_dedup)
508 #define HAMMERIOC_GET_DATA	_IOWR('h',26,struct hammer_ioc_data)
509 #define HAMMERIOC_LIST_VOLUMES	_IOWR('h',27,struct hammer_ioc_volume_list)
510 #define HAMMERIOC_PFS_ITERATE	_IOWR('h',28,struct hammer_ioc_pfs_iterate)
511 
512 #endif
513 
514