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