4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
27 * This file is part of Lustre, http://www.lustre.org/
28 * Lustre is a trademark of Sun Microsystems, Inc.
30 * lustre/utils/create_iam.c
32 * User-level tool for creation of iam files.
34 * Author: Wang Di <wangdi@clusterfs.com>
35 * Author: Nikita Danilov <nikita@clusterfs.com>
46 #include <sys/types.h>
51 "usage: create_iam [-h] [-k <keysize>] [-r recsize] [-b <blocksize] [-p <ptrsize>] [-v]\n");
55 IAM_LFIX_ROOT_MAGIC = 0xbedabb1edULL,
56 IAM_LVAR_ROOT_MAGIC = 0xb01dface
59 struct iam_lfix_root {
61 u_int16_t ilr_keysize;
62 u_int16_t ilr_recsize;
63 u_int16_t ilr_ptrsize;
64 u_int16_t ilr_indirect_levels;
68 IAM_LEAF_HEADER_MAGIC = 0x1976,
69 IAM_LVAR_LEAF_MAGIC = 0x1973
72 struct iam_leaf_head {
77 struct dx_countlimit {
82 typedef __u32 lvar_hash_t;
84 struct lvar_leaf_header {
85 u_int16_t vlh_magic; /* magic number IAM_LVAR_LEAF_MAGIC */
86 u_int16_t vlh_used; /* used bytes, including header */
93 u_int8_t vr_indirect_levels;
95 u_int16_t vr_padding1;
98 struct lvar_leaf_entry {
100 u_int16_t vle_keysize;
106 LVAR_ROUND = LVAR_PAD - 1
110 * Stores \a val at \a dst, where the latter is possibly unaligned. Uses
111 * memcpy(). This macro is needed to avoid dependency of user level tools on
112 * the kernel headers.
114 #define STORE_UNALIGNED(val, dst) \
116 typeof(val) __val = (val); \
118 CLASSERT(sizeof(val) == sizeof(*(dst))); \
119 memcpy(dst, &__val, sizeof(*(dst))); \
122 static void lfix_root(void *buf,
123 int blocksize, int keysize, int ptrsize, int recsize)
125 struct iam_lfix_root *root;
126 struct dx_countlimit *limit;
130 *root = (typeof(*root)) {
131 .ilr_magic = cpu_to_le64(IAM_LFIX_ROOT_MAGIC),
132 .ilr_keysize = cpu_to_le16(keysize),
133 .ilr_recsize = cpu_to_le16(recsize),
134 .ilr_ptrsize = cpu_to_le16(ptrsize),
135 .ilr_indirect_levels = 0
138 limit = (void *)(root + 1);
139 *limit = (typeof(*limit)){
141 * limit itself + one pointer to the leaf.
143 .count = cpu_to_le16(2),
144 .limit = (blocksize - sizeof(*root)) / (keysize + ptrsize)
151 entry += keysize + ptrsize;
154 * Entry format is <key> followed by <ptr>. In the minimal tree
155 * consisting of a root and single node, <key> is a minimal possible
158 * XXX: this key is hard-coded to be a sequence of 0's.
161 /* now @entry points to <ptr> */
163 STORE_UNALIGNED(cpu_to_le32(1), (u_int32_t *)entry);
165 STORE_UNALIGNED(cpu_to_le64(1), (u_int64_t *)entry);
168 static void lfix_leaf(void *buf,
169 int blocksize, int keysize, int ptrsize, int recsize)
171 struct iam_leaf_head *head;
175 *head = (struct iam_leaf_head) {
176 .ill_magic = cpu_to_le16(IAM_LEAF_HEADER_MAGIC),
178 * Leaf contains an entry with the smallest possible key
179 * (created by zeroing).
181 .ill_count = cpu_to_le16(1),
185 static void lvar_root(void *buf,
186 int blocksize, int keysize, int ptrsize, int recsize)
188 struct lvar_root *root;
189 struct dx_countlimit *limit;
193 isize = sizeof(lvar_hash_t) + ptrsize;
195 *root = (typeof(*root)) {
196 .vr_magic = cpu_to_le32(IAM_LVAR_ROOT_MAGIC),
197 .vr_recsize = cpu_to_le16(recsize),
198 .vr_ptrsize = cpu_to_le16(ptrsize),
199 .vr_indirect_levels = 0
202 limit = (void *)(root + 1);
203 *limit = (typeof(*limit)){
205 * limit itself + one pointer to the leaf.
207 .count = cpu_to_le16(2),
208 .limit = (blocksize - sizeof(*root)) / isize
218 * Entry format is <key> followed by <ptr>. In the minimal tree
219 * consisting of a root and single node, <key> is a minimal possible
222 * XXX: this key is hard-coded to be a sequence of 0's.
224 entry += sizeof(lvar_hash_t);
225 /* now @entry points to <ptr> */
227 STORE_UNALIGNED(cpu_to_le32(1), (u_int32_t *)entry);
229 STORE_UNALIGNED(cpu_to_le64(1), (u_int64_t *)entry);
232 static int lvar_esize(int namelen, int recsize)
234 return (offsetof(struct lvar_leaf_entry, vle_key) +
235 namelen + recsize + LVAR_ROUND) & ~LVAR_ROUND;
238 static void lvar_leaf(void *buf,
239 int blocksize, int keysize, int ptrsize, int recsize)
241 struct lvar_leaf_header *head;
245 *head = (typeof(*head)) {
246 .vlh_magic = cpu_to_le16(IAM_LVAR_LEAF_MAGIC),
247 .vlh_used = cpu_to_le16(sizeof(*head) + lvar_esize(0, recsize))
256 int main(int argc, char **argv)
260 int blocksize = 4096;
266 char *fmtstr = "lfix";
270 opt = getopt(argc, argv, "hb:k:r:p:vf:");
277 blocksize = atoi(optarg);
280 keysize = atoi(optarg);
283 recsize = atoi(optarg);
286 ptrsize = atoi(optarg);
293 fprintf(stderr, "Unable to parse options.");
300 if (ptrsize != 4 && ptrsize != 8) {
302 "Invalid ptrsize (%i). Only 4 and 8 are supported\n",
307 if (blocksize <= 100 || keysize < 1 || recsize < 0) {
308 fprintf(stderr, "Too small record, key or block block\n");
312 if (keysize + recsize + sizeof(struct iam_leaf_head) > blocksize / 3) {
313 fprintf(stderr, "Too large (record, key) or too small block\n");
317 if (!strcmp(fmtstr, "lfix")) {
319 } else if (!strcmp(fmtstr, "lvar")) {
322 fprintf(stderr, "Wrong format `%s'\n", fmtstr);
328 "fmt: %s, key: %i, rec: %i, ptr: %i, block: %i\n",
329 fmtstr, keysize, recsize, ptrsize, blocksize);
331 buf = malloc(blocksize);
333 fprintf(stderr, "Unable to allocate %i bytes\n", blocksize);
337 memset(buf, 0, blocksize);
340 lfix_root(buf, blocksize, keysize, ptrsize, recsize);
342 lvar_root(buf, blocksize, keysize, ptrsize, recsize);
344 rc = write(1, buf, blocksize);
345 if (rc != blocksize) {
346 fprintf(stderr, "Unable to write root node: %m (%i)\n", rc);
352 memset(buf, 0, blocksize);
355 lfix_leaf(buf, blocksize, keysize, ptrsize, recsize);
357 lvar_leaf(buf, blocksize, keysize, ptrsize, recsize);
359 rc = write(1, buf, blocksize);
361 if (rc != blocksize) {
362 fprintf(stderr, "Unable to write leaf node: %m (%i)\n", rc);
367 "Don't forget to umount/mount before accessing iam from the kernel!\n");