1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * User-level tool for creation of iam files.
7 * Copyright (c) 2006 Cluster File Systems, Inc.
8 * Author: Wang Di <wangdi@clusterfs.com>
9 * Author: Nikita Danilov <nikita@clusterfs.com>
11 * This file is part of the Lustre file system, http://www.lustre.org
12 * Lustre is a trademark of Cluster File Systems, Inc.
14 * You may have signed or agreed to another license before downloading
15 * this software. If so, you are bound by the terms and conditions
16 * of that agreement, and the following does not apply to you. See the
17 * LICENSE file included with this distribution for more information.
19 * If you did not agree to a different license, then this copy of Lustre
20 * is open source software; you can redistribute it and/or modify it
21 * under the terms of version 2 of the GNU General Public License as
22 * published by the Free Software Foundation.
24 * In either case, Lustre is distributed in the hope that it will be
25 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
26 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * license text for more details.
37 #include <sys/types.h>
43 #include <libcfs/libcfs.h>
47 printf("usage: create_iam "
48 "[-h] [-k <keysize>] [-r recsize] [-b <blocksize] [-p <ptrsize>] [-v]\n");
52 IAM_LFIX_ROOT_MAGIC = 0xbedabb1edULL,
53 IAM_LVAR_ROOT_MAGIC = 0xb01dface
56 struct iam_lfix_root {
58 u_int16_t ilr_keysize;
59 u_int16_t ilr_recsize;
60 u_int16_t ilr_ptrsize;
61 u_int16_t ilr_indirect_levels;
65 IAM_LEAF_HEADER_MAGIC = 0x1976,
66 IAM_LVAR_LEAF_MAGIC = 0x1973
69 struct iam_leaf_head {
74 struct dx_countlimit {
79 typedef __u32 lvar_hash_t;
81 struct lvar_leaf_header {
82 u_int16_t vlh_magic; /* magic number IAM_LVAR_LEAF_MAGIC */
83 u_int16_t vlh_used; /* used bytes, including header */
90 u_int8_t vr_indirect_levels;
92 u_int16_t vr_padding1;
95 struct lvar_leaf_entry {
97 u_int16_t vle_keysize;
103 LVAR_ROUND = LVAR_PAD - 1
107 * Stores \a val at \a dst, where the latter is possibly unaligned. Uses
108 * memcpy(). This macro is needed to avoid dependency of user level tools on
109 * the kernel headers.
111 #define STORE_UNALIGNED(val, dst) \
113 typeof(val) __val = (val); \
115 CLASSERT(sizeof(val) == sizeof(*(dst))); \
116 memcpy(dst, &__val, sizeof(*(dst))); \
119 static void lfix_root(void *buf,
120 int blocksize, int keysize, int ptrsize, int recsize)
122 struct iam_lfix_root *root;
123 struct dx_countlimit *limit;
127 *root = (typeof(*root)) {
128 .ilr_magic = cpu_to_le64(IAM_LFIX_ROOT_MAGIC),
129 .ilr_keysize = cpu_to_le16(keysize),
130 .ilr_recsize = cpu_to_le16(recsize),
131 .ilr_ptrsize = cpu_to_le16(ptrsize),
132 .ilr_indirect_levels = 0
135 limit = (void *)(root + 1);
136 *limit = (typeof(*limit)){
138 * limit itself + one pointer to the leaf.
140 .count = cpu_to_le16(2),
141 .limit = (blocksize - sizeof *root) / (keysize + ptrsize)
148 entry += keysize + ptrsize;
151 * Entry format is <key> followed by <ptr>. In the minimal tree
152 * consisting of a root and single node, <key> is a minimal possible
155 * XXX: this key is hard-coded to be a sequence of 0's.
158 /* now @entry points to <ptr> */
160 STORE_UNALIGNED(cpu_to_le32(1), (u_int32_t *)entry);
162 STORE_UNALIGNED(cpu_to_le64(1), (u_int64_t *)entry);
165 static void lfix_leaf(void *buf,
166 int blocksize, int keysize, int ptrsize, int recsize)
168 struct iam_leaf_head *head;
172 *head = (struct iam_leaf_head) {
173 .ill_magic = cpu_to_le16(IAM_LEAF_HEADER_MAGIC),
175 * Leaf contains an entry with the smallest possible key
176 * (created by zeroing).
178 .ill_count = cpu_to_le16(1),
182 static void lvar_root(void *buf,
183 int blocksize, int keysize, int ptrsize, int recsize)
185 struct lvar_root *root;
186 struct dx_countlimit *limit;
190 isize = sizeof(lvar_hash_t) + ptrsize;
192 *root = (typeof(*root)) {
193 .vr_magic = cpu_to_le32(IAM_LVAR_ROOT_MAGIC),
194 .vr_recsize = cpu_to_le16(recsize),
195 .vr_ptrsize = cpu_to_le16(ptrsize),
196 .vr_indirect_levels = 0
199 limit = (void *)(root + 1);
200 *limit = (typeof(*limit)){
202 * limit itself + one pointer to the leaf.
204 .count = cpu_to_le16(2),
205 .limit = (blocksize - sizeof *root) / isize
215 * Entry format is <key> followed by <ptr>. In the minimal tree
216 * consisting of a root and single node, <key> is a minimal possible
219 * XXX: this key is hard-coded to be a sequence of 0's.
221 entry += sizeof(lvar_hash_t);
222 /* now @entry points to <ptr> */
224 STORE_UNALIGNED(cpu_to_le32(1), (u_int32_t *)entry);
226 STORE_UNALIGNED(cpu_to_le64(1), (u_int64_t *)entry);
229 static int lvar_esize(int namelen, int recsize)
231 return (offsetof(struct lvar_leaf_entry, vle_key) +
232 namelen + recsize + LVAR_ROUND) & ~LVAR_ROUND;
235 static void lvar_leaf(void *buf,
236 int blocksize, int keysize, int ptrsize, int recsize)
238 struct lvar_leaf_header *head;
242 *head = (typeof(*head)) {
243 .vlh_magic = cpu_to_le16(IAM_LVAR_LEAF_MAGIC),
244 .vlh_used = cpu_to_le16(sizeof *head + lvar_esize(0, recsize))
253 int main(int argc, char **argv)
257 int blocksize = 4096;
263 char *fmtstr = "lfix";
267 opt = getopt(argc, argv, "hb:k:r:p:vf:");
274 blocksize = atoi(optarg);
277 keysize = atoi(optarg);
280 recsize = atoi(optarg);
283 ptrsize = atoi(optarg);
290 fprintf(stderr, "Unable to parse options.");
297 if (ptrsize != 4 && ptrsize != 8) {
298 fprintf(stderr, "Invalid ptrsize (%i). "
299 "Only 4 and 8 are supported\n", ptrsize);
303 if (blocksize <= 100 || keysize < 1 || recsize < 0) {
304 fprintf(stderr, "Too small record, key or block block\n");
308 if (keysize + recsize + sizeof(struct iam_leaf_head) > blocksize / 3) {
309 fprintf(stderr, "Too large (record, key) or too small block\n");
313 if (!strcmp(fmtstr, "lfix"))
315 else if (!strcmp(fmtstr, "lvar"))
318 fprintf(stderr, "Wrong format `%s'\n", fmtstr);
324 "fmt: %s, key: %i, rec: %i, ptr: %i, block: %i\n",
325 fmtstr, keysize, recsize, ptrsize, blocksize);
327 buf = malloc(blocksize);
329 fprintf(stderr, "Unable to allocate %i bytes\n", blocksize);
333 memset(buf, 0, blocksize);
336 lfix_root(buf, blocksize, keysize, ptrsize, recsize);
338 lvar_root(buf, blocksize, keysize, ptrsize, recsize);
340 rc = write(1, buf, blocksize);
341 if (rc != blocksize) {
342 fprintf(stderr, "Unable to write root node: %m (%i)\n", rc);
348 memset(buf, 0, blocksize);
351 lfix_leaf(buf, blocksize, keysize, ptrsize, recsize);
353 lvar_leaf(buf, blocksize, keysize, ptrsize, recsize);
355 rc = write(1, buf, blocksize);
357 if (rc != blocksize) {
358 fprintf(stderr, "Unable to write leaf node: %m (%i)\n", rc);
362 fprintf(stderr, "Don't forget to umount/mount "
363 "before accessing iam from the kernel!\n");