xref: /dragonfly/sys/vfs/hammer/hammer_ioctl.h (revision 90da8fc8d95e1895d63ebafb10404337f9f921f4)
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             reserved01[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                 reserved01;
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             reserved02;
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 struct hammer_ioc_hist_entry {
157           hammer_tid_t        tid;
158           uint32_t  time32;
159           uint32_t  reserved01;
160 };
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           uint32_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             reserved02;
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             reserved03;
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             reserved04;
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_label[64];
231           hammer_uuid_t       vol_fsid;
232           hammer_uuid_t       vol_fstype;
233 
234           int                 version;
235           int                 nvolumes;
236           int                 rootvol;
237           int                 reserved01;
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_GET_PSEUDOFS
249  * HAMMERIOC_SET_PSEUDOFS
250  * HAMMERIOC_SCAN_PSEUDOFS
251  */
252 struct hammer_ioc_pseudofs_rw {
253           struct hammer_ioc_head        head;
254           int                           pfs_id;
255           uint32_t            bytes;
256           uint32_t            version;
257           uint32_t            reserved01;
258           hammer_pseudofs_data_t        ondisk;
259 };
260 
261 #define HAMMER_IOC_PSEUDOFS_VERSION     1
262 
263 /*
264  * HAMMERIOC_MIRROR_READ/WRITE
265  */
266 struct hammer_ioc_mirror_rw {
267           struct hammer_ioc_head        head;
268           struct hammer_base_elm        key_beg;  /* start forward scan */
269           struct hammer_base_elm        key_end;  /* stop forward scan */
270           struct hammer_base_elm        key_cur;  /* interruption point */
271           hammer_tid_t                  tid_beg;  /* filter modification range */
272           hammer_tid_t                  tid_end;  /* filter modification range */
273           void                          *ubuf;              /* user buffer */
274           int                           count;              /* current size */
275           int                           size;               /* max size */
276           int                           pfs_id;             /* PFS id being read/written */
277           int                           reserved01;
278           hammer_uuid_t                 shared_uuid;        /* validator for safety */
279 };
280 
281 #define HAMMER_IOC_MIRROR_NODATA        0x0001    /* do not include bulk data */
282 
283 /*
284  * NOTE: crc is for the data block starting at rec_size, not including the
285  * data[] array.
286  */
287 struct hammer_ioc_mrecord_head {
288           uint32_t            signature;          /* signature for byte order */
289           hammer_crc_t                  rec_crc;
290           uint32_t            rec_size;
291           uint32_t            type;
292           /* extended */
293 };
294 
295 struct hammer_ioc_mrecord_rec {
296           struct hammer_ioc_mrecord_head          head;
297           struct hammer_btree_leaf_elm  leaf;
298           /* extended by data */
299 };
300 
301 struct hammer_ioc_mrecord_skip {
302           struct hammer_ioc_mrecord_head          head;
303           struct hammer_base_elm                  skip_beg;
304           struct hammer_base_elm                  skip_end;
305 };
306 
307 struct hammer_ioc_mrecord_update {
308           struct hammer_ioc_mrecord_head          head;
309           hammer_tid_t                            tid;
310 };
311 
312 struct hammer_ioc_mrecord_sync {
313           struct hammer_ioc_mrecord_head          head;
314 };
315 
316 struct hammer_ioc_mrecord_pfs {
317           struct hammer_ioc_mrecord_head          head;
318           uint32_t                      version;
319           uint32_t                      reserved01;
320           struct hammer_pseudofs_data   pfsd;
321 };
322 
323 struct hammer_ioc_version {
324           struct hammer_ioc_head head;
325           uint32_t            cur_version;
326           uint32_t            min_version;
327           uint32_t            wip_version;
328           uint32_t            max_version;
329           char                          description[64];
330 };
331 
332 struct hammer_ioc_volume {
333           struct hammer_ioc_head head;
334           char                          device_name[MAXPATHLEN];
335           int32_t                       vol_no;
336           uint8_t                       flag;
337           uint8_t                       reserved[3];
338           int64_t                       vol_size;
339           int64_t                       boot_area_size;
340           int64_t                       memory_log_size;
341 };
342 
343 #define HAMMER_IOC_VOLUME_REBLOCK       1
344 
345 struct hammer_ioc_volume_list {
346           struct hammer_ioc_volume *vols;
347           int nvols;
348 };
349 
350 typedef union hammer_ioc_mrecord_any {
351           struct hammer_ioc_mrecord_head          head;
352           struct hammer_ioc_mrecord_rec rec;
353           struct hammer_ioc_mrecord_skip          skip;
354           struct hammer_ioc_mrecord_update update;
355           struct hammer_ioc_mrecord_update sync;
356           struct hammer_ioc_mrecord_pfs pfs;
357           struct hammer_ioc_version     version;
358 } *hammer_ioc_mrecord_any_t;
359 
360 /*
361  * MREC types.  Flags are in the upper 16 bits but some are also included
362  * in the type mask to force them into any switch() on the type.
363  *
364  * NOTE: Any record whos data is CRC-errored will have HAMMER_MRECF_CRC set,
365  *         and the bit is also part of the type mask.
366  */
367 #define HAMMER_MREC_TYPE_RESERVED       0
368 #define HAMMER_MREC_TYPE_REC            1         /* record w/ data */
369 #define HAMMER_MREC_TYPE_PFSD           2         /* (userland only) */
370 #define HAMMER_MREC_TYPE_UPDATE                   3         /* (userland only) */
371 #define HAMMER_MREC_TYPE_SYNC           4         /* (userland only) */
372 #define HAMMER_MREC_TYPE_SKIP           5         /* skip-range */
373 #define HAMMER_MREC_TYPE_PASS           6         /* record for cmp only (pass) */
374 #define HAMMER_MREC_TYPE_TERM           7         /* (userland only) */
375 #define HAMMER_MREC_TYPE_IDLE           8         /* (userland only) */
376 
377 #define HAMMER_MREC_TYPE_REC_BADCRC     (HAMMER_MREC_TYPE_REC | \
378                                                    HAMMER_MRECF_CRC_ERROR)
379 #define HAMMER_MREC_TYPE_REC_NODATA     (HAMMER_MREC_TYPE_REC | \
380                                                    HAMMER_MRECF_NODATA)
381 
382 #define HAMMER_MRECF_TYPE_LOMASK        0x000000FF
383 #define HAMMER_MRECF_TYPE_MASK                    0x800000FF
384 #define HAMMER_MRECF_CRC_ERROR                    0x80000000
385 
386 #define HAMMER_MRECF_DATA_CRC_BAD       0x40000000
387 #define HAMMER_MRECF_RECD_CRC_BAD       0x20000000
388 #define HAMMER_MRECF_NODATA             0x10000000
389 
390 #define HAMMER_MREC_CRCOFF    (offsetof(struct hammer_ioc_mrecord_head, rec_size))
391 #define HAMMER_MREC_HEADSIZE  sizeof(struct hammer_ioc_mrecord_head)
392 
393 #define HAMMER_IOC_MIRROR_SIGNATURE     0x4dd97272U
394 #define HAMMER_IOC_MIRROR_SIGNATURE_REV 0x7272d94dU
395 
396 /*
397  * HAMMERIOC_ADD_SNAPSHOT - Add snapshot tid(s).
398  * HAMMERIOC_DEL_SNAPSHOT - Delete snapshot tids.
399  * HAMMERIOC_GET_SNAPSHOT - Get/continue retrieving snapshot tids.
400  *                                (finds restart point based on last snaps[] entry)
401  *
402  * These are per-PFS operations.
403  *
404  * NOTE: There is no limit on the number of snapshots, but there is a limit
405  *         on how many can be set or returned in each ioctl.
406  *
407  * NOTE: ADD and DEL start at snap->index.  If an error occurs the index will
408  *         point at the errored record.  snap->index must be set to 0 for GET.
409  */
410 #define HAMMER_SNAPS_PER_IOCTL                    16
411 
412 #define HAMMER_IOC_SNAPSHOT_EOF                   0x0008    /* no more keys */
413 
414 struct hammer_ioc_snapshot {
415           struct hammer_ioc_head        head;
416           int                           reserved01;
417           uint32_t            index;
418           uint32_t            count;
419           struct hammer_snapshot_data snaps[HAMMER_SNAPS_PER_IOCTL];
420 };
421 
422 /*
423  * HAMMERIOC_GET_CONFIG
424  * HAMMERIOC_SET_CONFIG
425  *
426  * The configuration space is a freeform nul-terminated string, typically
427  * a text file.  It is per-PFS and used by the 'hammer cleanup' utility.
428  *
429  * The configuration space is NOT mirrored.  mirror-write will ignore
430  * configuration space records.
431  */
432 struct hammer_ioc_config {
433           struct hammer_ioc_head        head;
434           uint32_t            reserved01;
435           uint32_t            reserved02;
436           uint64_t            reserved03[4];
437           struct hammer_config_data config;
438 };
439 
440 /*
441  * HAMMERIOC_DEDUP
442  */
443 struct hammer_ioc_dedup {
444           struct hammer_ioc_head        head;
445           struct hammer_base_elm        elm1;
446           struct hammer_base_elm        elm2; /* candidate for dedup */
447 };
448 
449 #define HAMMER_IOC_DEDUP_CMP_FAILURE    0x0001 /* verification failed */
450 #define HAMMER_IOC_DEDUP_UNDERFLOW      0x0002 /* big-block underflow */
451 #define HAMMER_IOC_DEDUP_INVALID_ZONE   0x0004 /* we can't dedup all zones */
452 
453 /*
454  * HAMMERIOC_GET_DATA
455  */
456 struct hammer_ioc_data {
457           struct hammer_ioc_head                  head;
458           struct hammer_base_elm                  elm;      /* btree key to lookup */
459           struct hammer_btree_leaf_elm  leaf;
460           void                                    *ubuf;    /* user buffer */
461           int                                     size;     /* max size */
462 };
463 
464 /*
465  * Ioctl cmd ids
466  */
467 #define HAMMERIOC_PRUNE                 _IOWR('h',1,struct hammer_ioc_prune)
468 #define HAMMERIOC_GETHISTORY  _IOWR('h',2,struct hammer_ioc_history)
469 #define HAMMERIOC_REBLOCK     _IOWR('h',3,struct hammer_ioc_reblock)
470 #define HAMMERIOC_SYNCTID     _IOWR('h',4,struct hammer_ioc_synctid)
471 #define HAMMERIOC_SET_PSEUDOFS          _IOWR('h',5,struct hammer_ioc_pseudofs_rw)
472 #define HAMMERIOC_GET_PSEUDOFS          _IOWR('h',6,struct hammer_ioc_pseudofs_rw)
473 #define HAMMERIOC_MIRROR_READ _IOWR('h',7,struct hammer_ioc_mirror_rw)
474 #define HAMMERIOC_MIRROR_WRITE          _IOWR('h',8,struct hammer_ioc_mirror_rw)
475 #define HAMMERIOC_UPG_PSEUDOFS          _IOWR('h',9,struct hammer_ioc_pseudofs_rw)
476 #define HAMMERIOC_DGD_PSEUDOFS          _IOWR('h',10,struct hammer_ioc_pseudofs_rw)
477 #define HAMMERIOC_RMR_PSEUDOFS          _IOWR('h',11,struct hammer_ioc_pseudofs_rw)
478 #define HAMMERIOC_WAI_PSEUDOFS          _IOWR('h',12,struct hammer_ioc_pseudofs_rw)
479 #define HAMMERIOC_GET_VERSION _IOWR('h',13,struct hammer_ioc_version)
480 #define HAMMERIOC_SET_VERSION _IOWR('h',14,struct hammer_ioc_version)
481 #define HAMMERIOC_REBALANCE   _IOWR('h',15,struct hammer_ioc_rebalance)
482 #define HAMMERIOC_GET_INFO    _IOR('h',16,struct hammer_ioc_info)
483 #define HAMMERIOC_ADD_VOLUME  _IOWR('h',17,struct hammer_ioc_volume)
484 #define HAMMERIOC_ADD_SNAPSHOT          _IOWR('h',18,struct hammer_ioc_snapshot)
485 #define HAMMERIOC_DEL_SNAPSHOT          _IOWR('h',19,struct hammer_ioc_snapshot)
486 #define HAMMERIOC_GET_SNAPSHOT          _IOWR('h',20,struct hammer_ioc_snapshot)
487 #define HAMMERIOC_GET_CONFIG  _IOWR('h',21,struct hammer_ioc_config)
488 #define HAMMERIOC_SET_CONFIG  _IOWR('h',22,struct hammer_ioc_config)
489 #define HAMMERIOC_DEL_VOLUME  _IOWR('h',24,struct hammer_ioc_volume)
490 #define HAMMERIOC_DEDUP                 _IOWR('h',25,struct hammer_ioc_dedup)
491 #define HAMMERIOC_GET_DATA    _IOWR('h',26,struct hammer_ioc_data)
492 #define HAMMERIOC_LIST_VOLUMES          _IOWR('h',27,struct hammer_ioc_volume_list)
493 #define HAMMERIOC_SCAN_PSEUDOFS         _IOWR('h',28,struct hammer_ioc_pseudofs_rw)
494 
495 #endif /* !VFS_HAMMER_IOCTL_H_ */
496 
497