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