1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see [sun.com URL with a
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/utils/create_iam.c
38 * User-level tool for creation of iam files.
40 * Author: Wang Di <wangdi@clusterfs.com>
41 * Author: Nikita Danilov <nikita@clusterfs.com>
51 #include <sys/types.h>
57 #include <libcfs/libcfs.h>
61 printf("usage: create_iam "
62 "[-h] [-k <keysize>] [-r recsize] [-b <blocksize] [-p <ptrsize>] [-v]\n");
66 IAM_LFIX_ROOT_MAGIC = 0xbedabb1edULL,
67 IAM_LVAR_ROOT_MAGIC = 0xb01dface
70 struct iam_lfix_root {
72 u_int16_t ilr_keysize;
73 u_int16_t ilr_recsize;
74 u_int16_t ilr_ptrsize;
75 u_int16_t ilr_indirect_levels;
79 IAM_LEAF_HEADER_MAGIC = 0x1976,
80 IAM_LVAR_LEAF_MAGIC = 0x1973
83 struct iam_leaf_head {
88 struct dx_countlimit {
93 typedef __u32 lvar_hash_t;
95 struct lvar_leaf_header {
96 u_int16_t vlh_magic; /* magic number IAM_LVAR_LEAF_MAGIC */
97 u_int16_t vlh_used; /* used bytes, including header */
102 u_int16_t vr_recsize;
103 u_int16_t vr_ptrsize;
104 u_int8_t vr_indirect_levels;
105 u_int8_t vr_padding0;
106 u_int16_t vr_padding1;
109 struct lvar_leaf_entry {
111 u_int16_t vle_keysize;
117 LVAR_ROUND = LVAR_PAD - 1
121 * Stores \a val at \a dst, where the latter is possibly unaligned. Uses
122 * memcpy(). This macro is needed to avoid dependency of user level tools on
123 * the kernel headers.
125 #define STORE_UNALIGNED(val, dst) \
127 typeof(val) __val = (val); \
129 CLASSERT(sizeof(val) == sizeof(*(dst))); \
130 memcpy(dst, &__val, sizeof(*(dst))); \
133 static void lfix_root(void *buf,
134 int blocksize, int keysize, int ptrsize, int recsize)
136 struct iam_lfix_root *root;
137 struct dx_countlimit *limit;
141 *root = (typeof(*root)) {
142 .ilr_magic = cpu_to_le64(IAM_LFIX_ROOT_MAGIC),
143 .ilr_keysize = cpu_to_le16(keysize),
144 .ilr_recsize = cpu_to_le16(recsize),
145 .ilr_ptrsize = cpu_to_le16(ptrsize),
146 .ilr_indirect_levels = 0
149 limit = (void *)(root + 1);
150 *limit = (typeof(*limit)){
152 * limit itself + one pointer to the leaf.
154 .count = cpu_to_le16(2),
155 .limit = (blocksize - sizeof *root) / (keysize + ptrsize)
162 entry += keysize + ptrsize;
165 * Entry format is <key> followed by <ptr>. In the minimal tree
166 * consisting of a root and single node, <key> is a minimal possible
169 * XXX: this key is hard-coded to be a sequence of 0's.
172 /* now @entry points to <ptr> */
174 STORE_UNALIGNED(cpu_to_le32(1), (u_int32_t *)entry);
176 STORE_UNALIGNED(cpu_to_le64(1), (u_int64_t *)entry);
179 static void lfix_leaf(void *buf,
180 int blocksize, int keysize, int ptrsize, int recsize)
182 struct iam_leaf_head *head;
186 *head = (struct iam_leaf_head) {
187 .ill_magic = cpu_to_le16(IAM_LEAF_HEADER_MAGIC),
189 * Leaf contains an entry with the smallest possible key
190 * (created by zeroing).
192 .ill_count = cpu_to_le16(1),
196 static void lvar_root(void *buf,
197 int blocksize, int keysize, int ptrsize, int recsize)
199 struct lvar_root *root;
200 struct dx_countlimit *limit;
204 isize = sizeof(lvar_hash_t) + ptrsize;
206 *root = (typeof(*root)) {
207 .vr_magic = cpu_to_le32(IAM_LVAR_ROOT_MAGIC),
208 .vr_recsize = cpu_to_le16(recsize),
209 .vr_ptrsize = cpu_to_le16(ptrsize),
210 .vr_indirect_levels = 0
213 limit = (void *)(root + 1);
214 *limit = (typeof(*limit)){
216 * limit itself + one pointer to the leaf.
218 .count = cpu_to_le16(2),
219 .limit = (blocksize - sizeof *root) / isize
229 * Entry format is <key> followed by <ptr>. In the minimal tree
230 * consisting of a root and single node, <key> is a minimal possible
233 * XXX: this key is hard-coded to be a sequence of 0's.
235 entry += sizeof(lvar_hash_t);
236 /* now @entry points to <ptr> */
238 STORE_UNALIGNED(cpu_to_le32(1), (u_int32_t *)entry);
240 STORE_UNALIGNED(cpu_to_le64(1), (u_int64_t *)entry);
243 static int lvar_esize(int namelen, int recsize)
245 return (offsetof(struct lvar_leaf_entry, vle_key) +
246 namelen + recsize + LVAR_ROUND) & ~LVAR_ROUND;
249 static void lvar_leaf(void *buf,
250 int blocksize, int keysize, int ptrsize, int recsize)
252 struct lvar_leaf_header *head;
256 *head = (typeof(*head)) {
257 .vlh_magic = cpu_to_le16(IAM_LVAR_LEAF_MAGIC),
258 .vlh_used = cpu_to_le16(sizeof *head + lvar_esize(0, recsize))
267 int main(int argc, char **argv)
271 int blocksize = 4096;
277 char *fmtstr = "lfix";
281 opt = getopt(argc, argv, "hb:k:r:p:vf:");
288 blocksize = atoi(optarg);
291 keysize = atoi(optarg);
294 recsize = atoi(optarg);
297 ptrsize = atoi(optarg);
304 fprintf(stderr, "Unable to parse options.");
311 if (ptrsize != 4 && ptrsize != 8) {
312 fprintf(stderr, "Invalid ptrsize (%i). "
313 "Only 4 and 8 are supported\n", ptrsize);
317 if (blocksize <= 100 || keysize < 1 || recsize < 0) {
318 fprintf(stderr, "Too small record, key or block block\n");
322 if (keysize + recsize + sizeof(struct iam_leaf_head) > blocksize / 3) {
323 fprintf(stderr, "Too large (record, key) or too small block\n");
327 if (!strcmp(fmtstr, "lfix"))
329 else if (!strcmp(fmtstr, "lvar"))
332 fprintf(stderr, "Wrong format `%s'\n", fmtstr);
338 "fmt: %s, key: %i, rec: %i, ptr: %i, block: %i\n",
339 fmtstr, keysize, recsize, ptrsize, blocksize);
341 buf = malloc(blocksize);
343 fprintf(stderr, "Unable to allocate %i bytes\n", blocksize);
347 memset(buf, 0, blocksize);
350 lfix_root(buf, blocksize, keysize, ptrsize, recsize);
352 lvar_root(buf, blocksize, keysize, ptrsize, recsize);
354 rc = write(1, buf, blocksize);
355 if (rc != blocksize) {
356 fprintf(stderr, "Unable to write root node: %m (%i)\n", rc);
362 memset(buf, 0, blocksize);
365 lfix_leaf(buf, blocksize, keysize, ptrsize, recsize);
367 lvar_leaf(buf, blocksize, keysize, ptrsize, recsize);
369 rc = write(1, buf, blocksize);
371 if (rc != blocksize) {
372 fprintf(stderr, "Unable to write leaf node: %m (%i)\n", rc);
376 fprintf(stderr, "Don't forget to umount/mount "
377 "before accessing iam from the kernel!\n");