From 530f4091626a9713c31127f69dbf47ee60dd0b52 Mon Sep 17 00:00:00 2001 From: nikita Date: Sun, 2 Jul 2006 21:17:42 +0000 Subject: [PATCH] iam: add lvar format --- ldiskfs/ldiskfs/Makefile.in | 3 +- .../kernel_patches/patches/ext3-iam-separate.patch | 835 ++++++++++++++++++++- lustre/kernel_patches/patches/ext3-iam-uapi.patch | 125 +-- lustre/ldiskfs/Makefile.in | 3 +- lustre/mdt/mdt_handler.c | 35 +- lustre/tests/iam_ut | Bin 62539 -> 63499 bytes lustre/utils/mkfs_lustre.c | 110 ++- 7 files changed, 953 insertions(+), 158 deletions(-) diff --git a/ldiskfs/ldiskfs/Makefile.in b/ldiskfs/ldiskfs/Makefile.in index 5a05bf8..2afd2cf 100644 --- a/ldiskfs/ldiskfs/Makefile.in +++ b/ldiskfs/ldiskfs/Makefile.in @@ -11,7 +11,8 @@ ext3_headers := $(wildcard @LINUX@/fs/ext3/*.h) linux_headers := $(wildcard @LINUX@/include/linux/ext3*.h) ext3_sources := $(filter-out %.mod.c,$(wildcard @LINUX@/fs/ext3/*.c)) -new_sources := iopen.c iopen.h extents.c mballoc.c iam.c iam_lfix.c iam_htree.c iam-uapi.c +new_sources := iopen.c iopen.h extents.c mballoc.c \ + iam.c iam_lfix.c iam_lvar.c iam_htree.c iam-uapi.c new_headers := ext3_extents.h ldiskfs_patched_sources := $(notdir $(ext3_sources) $(ext3_headers)) $(new_sources) $(new_headers) ldiskfs_sources := $(ldiskfs_patched_sources) diff --git a/lustre/kernel_patches/patches/ext3-iam-separate.patch b/lustre/kernel_patches/patches/ext3-iam-separate.patch index fc0f437..2744677 100644 --- a/lustre/kernel_patches/patches/ext3-iam-separate.patch +++ b/lustre/kernel_patches/patches/ext3-iam-separate.patch @@ -1,7 +1,7 @@ Index: iam/fs/ext3/Makefile =================================================================== --- iam.orig/fs/ext3/Makefile 2006-05-31 20:24:32.000000000 +0400 -+++ iam/fs/ext3/Makefile 2006-06-29 18:50:12.000000000 +0400 ++++ iam/fs/ext3/Makefile 2006-07-03 01:03:10.000000000 +0400 @@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ @@ -14,8 +14,8 @@ Index: iam/fs/ext3/Makefile Index: iam/fs/ext3/iam.c =================================================================== --- iam.orig/fs/ext3/iam.c 2004-04-06 17:27:52.000000000 +0400 -+++ iam/fs/ext3/iam.c 2006-06-28 22:46:13.000000000 +0400 -@@ -0,0 +1,1233 @@ ++++ iam/fs/ext3/iam.c 2006-07-01 20:21:38.000000000 +0400 +@@ -0,0 +1,1262 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * @@ -164,6 +164,7 @@ Index: iam/fs/ext3/iam.c + * so that iam_htree_guess() runs last. + */ + iam_htree_format_init(); ++ iam_lvar_format_init(); + iam_lfix_format_init(); + initialized = 1; + } @@ -336,6 +337,11 @@ Index: iam/fs/ext3/iam.c + return iam_leaf_ops(leaf)->key(leaf); +} + ++static int iam_leaf_key_size(const struct iam_leaf *leaf) ++{ ++ return iam_leaf_ops(leaf)->key_size(leaf); ++} ++ +static struct iam_ikey *iam_leaf_ikey(const struct iam_leaf *leaf, + struct iam_ikey *key) +{ @@ -550,13 +556,14 @@ Index: iam/fs/ext3/iam.c + int result; + + result = iam_it_get(it, k); -+ if (result == 0 && -+ (it_state(it) != IAM_IT_ATTACHED || it_keycmp(it, k) != 0)) ++ if (result > 0) ++ result = 0; ++ else if (result == 0) + /* + * Return -ENOENT if cursor is located above record with a key + * different from one specified, or in the empty leaf. + * -+ * XXX returning -ENOENT only works if iam_it_get never ++ * XXX returning -ENOENT only works if iam_it_get() never + * returns -ENOENT as a legitimate error. + */ + result = -ENOENT; @@ -656,6 +663,7 @@ Index: iam/fs/ext3/iam.c + * least key not larger than @k. + * + * Return value: 0: positioned on existing record, ++ * +ve: exact position found, + * -ve: error. + * + * precondition: it_state(it) == IAM_IT_DETACHED @@ -672,19 +680,25 @@ Index: iam/fs/ext3/iam.c + result = iam_path_lookup(&it->ii_path); + if (result >= 0) { + switch (result) { ++ case IAM_LOOKUP_EXACT: ++ result = +1; ++ it->ii_state = IAM_IT_ATTACHED; ++ break; + case IAM_LOOKUP_OK: ++ result = 0; + it->ii_state = IAM_IT_ATTACHED; + break; + case IAM_LOOKUP_BEFORE: + case IAM_LOOKUP_EMPTY: ++ result = 0; + it->ii_state = IAM_IT_SKEWED; + break; + default: + assert(0); + } -+ result = 0; + } else + iam_it_unlock(it); ++ assert(ergo(result > 0, it_keycmp(it, k) == 0)); + assert(ergo(result == 0 && it_state(it) == IAM_IT_ATTACHED, + it_keycmp(it, k) <= 0)); + /* @@ -698,6 +712,7 @@ Index: iam/fs/ext3/iam.c + * Attach iterator, and assure it points to the record (not skewed). + * + * Return value: 0: positioned on existing record, ++ * +ve: exact position found, + * -ve: error. + * + * precondition: it_state(it) == IAM_IT_DETACHED && @@ -715,7 +730,7 @@ Index: iam/fs/ext3/iam.c + result = iam_it_next(it); + } + } -+ assert(ergo(result == 0, it_state(it) == IAM_IT_ATTACHED)); ++ assert(ergo(result >= 0, it_state(it) == IAM_IT_ATTACHED)); + return result; +} + @@ -869,16 +884,30 @@ Index: iam/fs/ext3/iam.c + * + * precondition: it_state(it) == IAM_IT_ATTACHED || + * it_state(it) == IAM_IT_SKEWED -+ * postcondition: it_state(it) == IAM_IT_ATTACHED + */ +struct iam_key *iam_it_key_get(const struct iam_iterator *it) +{ -+ assert(it_state(it) == IAM_IT_ATTACHED); ++ assert(it_state(it) == IAM_IT_ATTACHED || ++ it_state(it) == IAM_IT_SKEWED); + assert(it_at_rec(it)); + return iam_leaf_key(&it->ii_path.ip_leaf); +} + +/* ++ * Return size of key under iterator (in bytes) ++ * ++ * precondition: it_state(it) == IAM_IT_ATTACHED || ++ * it_state(it) == IAM_IT_SKEWED ++ */ ++int iam_it_key_size(const struct iam_iterator *it) ++{ ++ assert(it_state(it) == IAM_IT_ATTACHED || ++ it_state(it) == IAM_IT_SKEWED); ++ assert(it_at_rec(it)); ++ return iam_leaf_key_size(&it->ii_path.ip_leaf); ++} ++ ++/* + * Insertion of new record. Interaction with jbd during non-trivial case (when + * split happens) is as following: + * @@ -976,7 +1005,7 @@ Index: iam/fs/ext3/iam.c + * (it_state(it) == IAM_IT_ATTACHED || + * it_state(it) == IAM_IT_SKEWED) && + * ergo(it_state(it) == IAM_IT_ATTACHED, -+ * it_keycmp(it, k) < 0) && ++ * it_keycmp(it, k) <= 0) && + * ergo(it_before(it), it_keycmp(it, k) > 0)); + * postcondition: ergo(result == 0, + * it_state(it) == IAM_IT_ATTACHED && @@ -994,7 +1023,7 @@ Index: iam/fs/ext3/iam.c + assert(it->ii_flags&IAM_IT_WRITE); + assert(it_state(it) == IAM_IT_ATTACHED || + it_state(it) == IAM_IT_SKEWED); -+ assert(ergo(it_state(it) == IAM_IT_ATTACHED, it_keycmp(it, k) < 0)); ++ assert(ergo(it_state(it) == IAM_IT_ATTACHED, it_keycmp(it, k) <= 0)); + assert(ergo(it_before(it), it_keycmp(it, k) > 0)); + result = iam_add_rec(h, path, k, r); + if (result == 0) @@ -1252,8 +1281,8 @@ Index: iam/fs/ext3/iam.c Index: iam/fs/ext3/iam_htree.c =================================================================== --- iam.orig/fs/ext3/iam_htree.c 2004-04-06 17:27:52.000000000 +0400 -+++ iam/fs/ext3/iam_htree.c 2006-06-28 22:18:53.000000000 +0400 -@@ -0,0 +1,645 @@ ++++ iam/fs/ext3/iam_htree.c 2006-07-01 19:09:16.000000000 +0400 +@@ -0,0 +1,655 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * @@ -1421,7 +1450,8 @@ Index: iam/fs/ext3/iam_htree.c + * Leaf operations. + */ + -+struct iam_ikey *iam_htree_ikey(const struct iam_leaf *l, struct iam_ikey *key) ++static struct iam_ikey *iam_htree_ikey(const struct iam_leaf *l, ++ struct iam_ikey *key) +{ + __u32 *hash; + assert(iam_leaf_at_rec(l)); @@ -1431,13 +1461,20 @@ Index: iam/fs/ext3/iam_htree.c + return key; +} + -+struct iam_key *iam_htree_key(const struct iam_leaf *l) ++static struct iam_key *iam_htree_key(const struct iam_leaf *l) +{ + assert(iam_leaf_at_rec(l)); + + return (struct iam_key *)&getent(l)->name; +} + ++static int iam_htree_key_size(const struct iam_leaf *l) ++{ ++ assert(iam_leaf_at_rec(l)); ++ ++ return getent(l)->name_len; ++} ++ +static void iam_htree_start(struct iam_leaf *l) +{ + l->il_at = (void *)skipdead(getstart(l)); @@ -1511,10 +1548,12 @@ Index: iam/fs/ext3/iam_htree.c + namelen = strlen(name); + hash = hashname(l, name, namelen); + found = NULL; ++ result = IAM_LOOKUP_OK; + for (scan = getstart(l); scan < getlast(l, namelen); + scan = entnext(scan)) { + if (match(namelen, name, scan)) { + found = scan; ++ result = IAM_LOOKUP_EXACT; + break; + } else if (ent_is_live(scan) && gethash(l, scan) <= hash) + found = scan; @@ -1527,7 +1566,6 @@ Index: iam/fs/ext3/iam_htree.c + result = IAM_LOOKUP_BEFORE; + } else { + l->il_at = (void *)found; -+ result = IAM_LOOKUP_OK; + assert(iam_leaf_at_rec(l)); + } + return result; @@ -1674,6 +1712,7 @@ Index: iam/fs/ext3/iam_htree.c + .rec = iam_htree_rec, + .key_set = iam_htree_key_set, + .key_cmp = iam_htree_key_cmp, ++ .key_size = iam_htree_key_size, + .rec_set = iam_htree_rec_set, + .lookup = iam_htree_lookup, + .at_end = iam_htree_at_end, @@ -1902,8 +1941,8 @@ Index: iam/fs/ext3/iam_htree.c Index: iam/fs/ext3/iam_lfix.c =================================================================== --- iam.orig/fs/ext3/iam_lfix.c 2004-04-06 17:27:52.000000000 +0400 -+++ iam/fs/ext3/iam_lfix.c 2006-06-28 21:18:56.000000000 +0400 -@@ -0,0 +1,649 @@ ++++ iam/fs/ext3/iam_lfix.c 2006-07-01 19:19:48.000000000 +0400 +@@ -0,0 +1,660 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * @@ -2025,20 +2064,26 @@ Index: iam/fs/ext3/iam_lfix.c + folio->il_at < iam_lfix_get_end(folio); +} + -+struct iam_ikey *iam_lfix_ikey(const struct iam_leaf *l, struct iam_ikey *key) ++static struct iam_ikey *iam_lfix_ikey(const struct iam_leaf *l, ++ struct iam_ikey *key) +{ + void *ie = l->il_at; + assert(iam_leaf_at_rec(l)); + return (struct iam_ikey*)ie; +} + -+struct iam_key *iam_lfix_key(const struct iam_leaf *l) ++static struct iam_key *iam_lfix_key(const struct iam_leaf *l) +{ + void *ie = l->il_at; + assert(iam_leaf_at_rec(l)); + return (struct iam_key*)ie; +} + ++static int iam_lfix_key_size(const struct iam_leaf *l) ++{ ++ return iam_leaf_descr(l)->id_key_size; ++} ++ +static void iam_lfix_start(struct iam_leaf *l) +{ + l->il_at = iam_get_lentries(l); @@ -2162,6 +2207,9 @@ Index: iam/fs/ext3/iam_lfix.c + } + assert(iam_leaf_at_rec(l)); + ++ if (lfix_keycmp(c, iam_leaf_key_at(l->il_at), k) == 0) ++ result = IAM_LOOKUP_EXACT; ++ + return result; +} + @@ -2328,6 +2376,7 @@ Index: iam/fs/ext3/iam_lfix.c + .rec = iam_lfix_rec, + .key_set = iam_lfix_key_set, + .key_cmp = iam_lfix_key_cmp, ++ .key_size = iam_lfix_key_size, + .rec_set = iam_lfix_rec_set, + .lookup = iam_lfix_lookup, + .at_end = iam_lfix_at_end, @@ -2360,7 +2409,8 @@ Index: iam/fs/ext3/iam_lfix.c + __le16 ilr_keysize; + __le16 ilr_recsize; + __le16 ilr_ptrsize; -+ __le16 ilr_indirect_levels; ++ u8 ilr_indirect_levels; ++ u8 ilr_padding; +}; + +static __u32 iam_lfix_root_ptr(struct iam_container *c) @@ -2437,7 +2487,7 @@ Index: iam/fs/ext3/iam_lfix.c + struct iam_lfix_root *root; + + root = data; -+ path->ip_indirect = le16_to_cpu(root->ilr_indirect_levels); ++ path->ip_indirect = root->ilr_indirect_levels; + path->ip_ikey_target = (struct iam_ikey *)path->ip_key_target; + } + frame->entries = frame->at = entries; @@ -2553,6 +2603,743 @@ Index: iam/fs/ext3/iam_lfix.c + char rec[RECSIZE]; + } ll_entry[LFIX_LEAF_RECNO]; +}; +Index: iam/fs/ext3/iam_lvar.c +=================================================================== +--- iam.orig/fs/ext3/iam_lvar.c 2004-04-06 17:27:52.000000000 +0400 ++++ iam/fs/ext3/iam_lvar.c 2006-07-01 20:10:13.000000000 +0400 +@@ -0,0 +1,732 @@ ++/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- ++ * vim:expandtab:shiftwidth=8:tabstop=8: ++ * ++ * iam_lvar.c ++ * implementation of iam format for fixed size records, variable sized keys. ++ * ++ * Copyright (c) 2006 Cluster File Systems, Inc. ++ * Author: Nikita Danilov ++ * ++ * This file is part of the Lustre file system, http://www.lustre.org ++ * Lustre is a trademark of Cluster File Systems, Inc. ++ * ++ * You may have signed or agreed to another license before downloading ++ * this software. If so, you are bound by the terms and conditions ++ * of that agreement, and the following does not apply to you. See the ++ * LICENSE file included with this distribution for more information. ++ * ++ * If you did not agree to a different license, then this copy of Lustre ++ * is open source software; you can redistribute it and/or modify it ++ * under the terms of version 2 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ * ++ * In either case, Lustre is distributed in the hope that it will be ++ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * license text for more details. ++ */ ++ ++#include ++#include ++/* ext3_error() */ ++#include ++ ++#include ++ ++#include ++#include ++ ++/* ++ * Leaf operations. ++ */ ++ ++enum { ++ IAM_LVAR_LEAF_MAGIC = 0x1973 /* This is duplicated in ++ * lustre/utils/create_iam.c */ ++}; ++ ++/* This is duplicated in lustre/utils/create_iam.c */ ++struct lvar_leaf_header { ++ __le16 vlh_magic; /* magic number IAM_LVAR_LEAF_MAGIC */ ++ __le16 vlh_used; /* used bytes, including header */ ++}; ++ ++/* ++ * Format of leaf entry: ++ * ++ * __le16 keysize ++ * u8 key[keysize] ++ * u8 record[rec_size] ++ * ++ * Entries are ordered in key order. ++ */ ++ ++/* This is duplicated in lustre/utils/create_iam.c */ ++typedef __u32 lvar_hash_t; ++ ++/* This is duplicated in lustre/utils/create_iam.c */ ++struct lvar_leaf_entry { ++ __le32 vle_hash; ++ __le16 vle_keysize; ++ u8 vle_key[0]; ++}; ++ ++#define PDIFF(ptr0, ptr1) (((char *)(ptr0)) - ((char *)(ptr1))) ++ ++ ++static inline int blocksize(const struct iam_leaf *leaf) ++{ ++ return iam_leaf_container(leaf)->ic_object->i_sb->s_blocksize; ++} ++ ++static inline const char *kchar(const struct iam_key *key) ++{ ++ return (void *)key; ++} ++ ++static inline struct iam_lentry *lvar_lentry(const struct lvar_leaf_entry *ent) ++{ ++ return (struct iam_lentry *)ent; ++} ++ ++static inline struct lvar_leaf_entry *lentry_lvar(const struct iam_lentry *lent) ++{ ++ return (struct lvar_leaf_entry *)lent; ++} ++ ++ ++static inline int recsize(const struct iam_leaf *leaf) ++{ ++ return iam_leaf_descr(leaf)->id_rec_size; ++} ++ ++static inline int e_keysize(const struct lvar_leaf_entry *ent) ++{ ++ return le16_to_cpu(ent->vle_keysize); ++} ++ ++/* This is duplicated in lustre/utils/create_iam.c */ ++enum { ++ LVAR_PAD = 4, ++ LVAR_ROUND = LVAR_PAD - 1 ++}; ++ ++static inline int getsize(const struct iam_leaf *leaf, int namelen) ++{ ++ CLASSERT(!(LVAR_PAD & (LVAR_PAD - 1))); ++ ++ return (offsetof(struct lvar_leaf_entry, vle_key) + ++ namelen + recsize(leaf) + LVAR_ROUND) & ~LVAR_ROUND; ++} ++ ++static inline int e_size(const struct iam_leaf *leaf, ++ const struct lvar_leaf_entry *ent) ++{ ++ return getsize(leaf, e_keysize(ent)); ++} ++ ++static inline char *e_char(const struct lvar_leaf_entry *ent) ++{ ++ return (char *)&ent->vle_key; ++} ++ ++static inline struct iam_key *e_key(const struct lvar_leaf_entry *ent) ++{ ++ return (struct iam_key *)e_char(ent); ++} ++ ++static inline lvar_hash_t e_hash(const struct lvar_leaf_entry *ent) ++{ ++ return le32_to_cpu(ent->vle_hash); ++} ++ ++static inline struct iam_rec *e_rec(const struct lvar_leaf_entry *ent) ++{ ++ return ((void *)ent) + ++ offsetof(struct lvar_leaf_entry, vle_key) + e_keysize(ent); ++} ++ ++static int e_check(const struct iam_leaf *leaf, ++ const struct lvar_leaf_entry *ent) ++{ ++ const void *point = ent; ++ const void *start = leaf->il_bh->b_data; ++ return ++ start + sizeof(struct lvar_leaf_header) <= point && ++ point + e_size(leaf, ent) < start + blocksize(leaf); ++} ++ ++static struct lvar_leaf_entry *e_next(const struct iam_leaf *leaf, ++ const struct lvar_leaf_entry *ent) ++{ ++ return ((void *)ent) + e_size(leaf, ent); ++} ++ ++static inline lvar_hash_t get_hash(const struct iam_container *bag, ++ const char *name, int namelen) ++{ ++ lvar_hash_t result; ++ ++ result = 0; ++ strncpy((void *)&result, name, min(namelen, (int)sizeof result)); ++ return result << 1; ++} ++ ++static inline int e_eq(const struct lvar_leaf_entry *ent, ++ const char *name, int namelen) ++{ ++ return namelen == e_keysize(ent) && !memcmp(e_char(ent), name, namelen); ++} ++ ++static inline int e_cmp(const struct iam_leaf *leaf, ++ const struct lvar_leaf_entry *ent, lvar_hash_t hash) ++{ ++ lvar_hash_t ehash; ++ ++ ehash = e_hash(ent); ++ return ehash == hash ? 0 : (ehash < hash ? -1 : +1); ++} ++ ++static struct lvar_leaf_header *n_head(const struct iam_leaf *l) ++{ ++ return (struct lvar_leaf_header *)l->il_bh->b_data; ++} ++ ++static int h_used(const struct lvar_leaf_header *hdr) ++{ ++ return le16_to_cpu(hdr->vlh_used); ++} ++ ++static void h_used_adj(const struct iam_leaf *leaf, ++ struct lvar_leaf_header *hdr, int adj) ++{ ++ int used; ++ ++ used = h_used(hdr) + adj; ++ assert(sizeof *hdr <= used && used <= blocksize(leaf)); ++ hdr->vlh_used = cpu_to_le16(used); ++} ++ ++static struct lvar_leaf_entry *n_start(const struct iam_leaf *leaf) ++{ ++ return (void *)leaf->il_bh->b_data + sizeof(struct lvar_leaf_header); ++} ++ ++static struct lvar_leaf_entry *n_end(const struct iam_leaf *l) ++{ ++ return (void *)l->il_bh->b_data + h_used(n_head(l)); ++} ++ ++static struct lvar_leaf_entry *n_cur(const struct iam_leaf *l) ++{ ++ return lentry_lvar(l->il_at); ++} ++ ++static int n_at_rec(const struct iam_leaf *folio) ++{ ++ return ++ n_start(folio) <= lentry_lvar(folio->il_at) && ++ lentry_lvar(folio->il_at) < n_end(folio); ++} ++ ++static struct iam_ikey *lvar_ikey(const struct iam_leaf *l, ++ struct iam_ikey *key) ++{ ++ lvar_hash_t *hash; ++ ++ assert(n_at_rec(l)); ++ ++ hash = (void *)key; ++ *hash = e_hash(n_cur(l)); ++ BUG(); /* shouldn't be called currently */ ++ return key; ++} ++ ++static struct iam_key *lvar_key(const struct iam_leaf *l) ++{ ++ return e_key(n_cur(l)); ++} ++ ++static int lvar_key_size(const struct iam_leaf *l) ++{ ++ return e_keysize(n_cur(l)); ++} ++ ++static void lvar_start(struct iam_leaf *l) ++{ ++ l->il_at = lvar_lentry(n_start(l)); ++} ++ ++static int lvar_init(struct iam_leaf *l) ++{ ++ int result; ++ int used; ++ struct lvar_leaf_header *head; ++ ++ assert(l->il_bh != NULL); ++ ++ head = n_head(l); ++ used = h_used(head); ++ if (head->vlh_magic == le16_to_cpu(IAM_LVAR_LEAF_MAGIC) && ++ used <= blocksize(l)) { ++ l->il_at = l->il_entries = lvar_lentry(n_start(l)); ++ result = 0; ++ } else { ++ struct inode *obj; ++ ++ obj = iam_leaf_container(l)->ic_object; ++ ext3_error(obj->i_sb, __FUNCTION__, ++ "Wrong magic in node %llu (#%lu): %#x != %#x or " ++ "wrong used: %i", ++ (unsigned long long)l->il_bh->b_blocknr, obj->i_ino, ++ head->vlh_magic, le16_to_cpu(IAM_LVAR_LEAF_MAGIC), ++ used); ++ result = -EIO; ++ BREAKPOINT; ++ } ++ return result; ++} ++ ++static void lvar_fini(struct iam_leaf *l) ++{ ++ l->il_entries = l->il_at = NULL; ++} ++ ++struct iam_rec *lvar_rec(const struct iam_leaf *l) ++{ ++ assert(n_at_rec(l)); ++ return e_rec(n_cur(l)); ++} ++ ++static void lvar_next(struct iam_leaf *l) ++{ ++ assert(n_at_rec(l)); ++ l->il_at = lvar_lentry(e_next(l, n_cur(l))); ++} ++ ++static int lvar_lookup(struct iam_leaf *leaf, const struct iam_key *k) ++{ ++ struct lvar_leaf_entry *found; ++ struct lvar_leaf_entry *scan; ++ struct lvar_leaf_entry *end; ++ int result; ++ const char *name; ++ int namelen; ++ int found_equal; ++ lvar_hash_t hash; ++ ++ end = n_end(leaf); ++ ++ name = kchar(k); ++ namelen = strlen(name); ++ hash = get_hash(iam_leaf_container(leaf), name, namelen); ++ found = NULL; ++ found_equal = 0; ++ ++ for (scan = n_start(leaf); scan < end; scan = e_next(leaf, scan)) { ++ lvar_hash_t scan_hash; ++ ++ scan_hash = e_hash(scan); ++ if (scan_hash < hash) ++ found = scan; ++ else if (scan_hash == hash) { ++ if (e_eq(scan, name, namelen)) { ++ /* ++ * perfect match ++ */ ++ leaf->il_at = lvar_lentry(scan); ++ return IAM_LOOKUP_EXACT; ++ } else if (!found_equal) { ++ found = scan; ++ found_equal = 1; ++ } ++ } else ++ break; ++ } ++ if (found == NULL) { ++ /* ++ * @k is less than all hashes in the leaf. ++ */ ++ lvar_start(leaf); ++ result = IAM_LOOKUP_BEFORE; ++ } else { ++ leaf->il_at = lvar_lentry(found); ++ result = IAM_LOOKUP_OK; ++ assert(n_at_rec(leaf)); ++ } ++ return result; ++} ++ ++static void lvar_key_set(struct iam_leaf *l, const struct iam_key *k) ++{ ++ assert(n_at_rec(l)); ++ assert(strlen(kchar(k)) == e_keysize(n_cur(l))); ++ memcpy(e_key(n_cur(l)), k, e_keysize(n_cur(l))); ++} ++ ++static int lvar_key_cmp(const struct iam_leaf *l, const struct iam_key *k) ++{ ++ lvar_hash_t hash; ++ const char *name; ++ ++ name = kchar(k); ++ hash = get_hash(iam_leaf_container(l), name, strlen(name)); ++ return e_cmp(l, n_cur(l), hash); ++} ++ ++static void lvar_rec_set(struct iam_leaf *l, const struct iam_rec *r) ++{ ++ assert(n_at_rec(l)); ++ iam_reccpy(iam_leaf_path(l), e_rec(n_cur(l)), r); ++} ++ ++static int lvar_can_add(const struct iam_leaf *l, ++ const struct iam_key *k, const struct iam_rec *r) ++{ ++ return h_used(n_head(l)) + getsize(l, strlen(kchar(k))) <= blocksize(l); ++} ++ ++static int lvar_at_end(const struct iam_leaf *folio) ++{ ++ return n_cur(folio) == n_end(folio); ++} ++ ++static void lvar_rec_add(struct iam_leaf *leaf, ++ const struct iam_key *k, const struct iam_rec *r) ++{ ++ const char *key; ++ int ksize; ++ int shift; ++ void *end; ++ void *start; ++ ptrdiff_t diff; ++ ++ assert(lvar_can_add(leaf, k, r)); ++ ++ key = kchar(k); ++ ksize = strlen(key); ++ shift = getsize(leaf, ksize); ++ ++ if (!lvar_at_end(leaf)) { ++ end = n_end(leaf); ++ if (lvar_key_cmp(leaf, k) <= 0) ++ lvar_next(leaf); ++ else ++ /* ++ * Another exceptional case: insertion with the key ++ * less than least key in the leaf. ++ */ ++ assert(leaf->il_at == leaf->il_entries); ++ ++ start = leaf->il_at; ++ diff = PDIFF(end, start); ++ assert(diff >= 0); ++ memmove(start + shift, start, diff); ++ } ++ h_used_adj(leaf, n_head(leaf), shift); ++ n_cur(leaf)->vle_keysize = cpu_to_le16(ksize); ++ n_cur(leaf)->vle_hash = cpu_to_le32(get_hash(iam_leaf_container(leaf), ++ key, ksize)); ++ lvar_key_set(leaf, k); ++ lvar_rec_set(leaf, r); ++ assert(n_at_rec(leaf)); ++} ++ ++static void lvar_rec_del(struct iam_leaf *leaf, int shift) ++{ ++ void *next; ++ void *end; ++ int nob; ++ ++ assert(n_at_rec(leaf)); ++ ++ end = n_end(leaf); ++ next = e_next(leaf, n_cur(leaf)); ++ nob = e_size(leaf, n_cur(leaf)); ++ memmove(leaf->il_at, next, end - next); ++ h_used_adj(leaf, n_head(leaf), -nob); ++} ++ ++static void lvar_init_new(struct iam_container *c, struct buffer_head *bh) ++{ ++ struct lvar_leaf_header *hdr; ++ ++ hdr = (struct lvar_leaf_header *)bh->b_data; ++ hdr->vlh_magic = cpu_to_le16(IAM_LVAR_LEAF_MAGIC); ++ hdr->vlh_used = sizeof *hdr; ++} ++ ++static struct lvar_leaf_entry *find_pivot(const struct iam_leaf *leaf, ++ struct lvar_leaf_entry **prev) ++{ ++ void *scan; ++ void *start; ++ int threshold; ++ ++ *prev = NULL; ++ threshold = blocksize(leaf) / 2; ++ for (scan = start = n_start(leaf); scan - start <= threshold; ++ *prev = scan, scan = e_next(leaf, scan)) { ++ ; ++ } ++ return scan; ++} ++ ++static void lvar_split(struct iam_leaf *leaf, struct buffer_head **bh, ++ iam_ptr_t new_blknr) ++{ ++ struct lvar_leaf_entry *first_to_move; ++ struct lvar_leaf_entry *last_to_stay; ++ struct iam_path *path; ++ struct lvar_leaf_header *hdr; ++ struct buffer_head *new_leaf; ++ ++ ptrdiff_t tomove; ++ lvar_hash_t hash; ++ ++ new_leaf = *bh; ++ path = iam_leaf_path(leaf); ++ ++ hdr = (void *)new_leaf->b_data; ++ ++ first_to_move = find_pivot(leaf, &last_to_stay); ++ assert(last_to_stay != NULL); ++ assert(e_next(leaf, last_to_stay) == first_to_move); ++ ++ hash = e_hash(first_to_move); ++ if (hash == e_hash(last_to_stay)) ++ /* ++ * Duplicate hash. ++ */ ++ hash |= 1; ++ ++ tomove = PDIFF(n_end(leaf), first_to_move); ++ memmove(hdr + 1, first_to_move, tomove); ++ ++ h_used_adj(leaf, hdr, tomove); ++ h_used_adj(leaf, n_head(leaf), -tomove); ++ ++ assert(n_end(leaf) == first_to_move); ++ ++ /* ++ * Insert pointer to the new node (together with the least key in ++ * the node) into index node. ++ */ ++ iam_insert_key(path, path->ip_frame, (struct iam_ikey *)&hash, ++ new_blknr); ++ if (n_cur(leaf) >= first_to_move) { ++ /* ++ * insertion point moves into new leaf. ++ */ ++ ptrdiff_t shift; ++ int result; ++ ++ shift = PDIFF(leaf->il_at, first_to_move); ++ *bh = leaf->il_bh; ++ leaf->il_bh = new_leaf; ++ result = lvar_init(leaf); ++ /* ++ * init cannot fail, as node was just initialized. ++ */ ++ assert(result == 0); ++ leaf->il_at = ((void *)leaf->il_at) + shift; ++ } ++} ++ ++static struct iam_leaf_operations lvar_leaf_ops = { ++ .init = lvar_init, ++ .init_new = lvar_init_new, ++ .fini = lvar_fini, ++ .start = lvar_start, ++ .next = lvar_next, ++ .key = lvar_key, ++ .ikey = lvar_ikey, ++ .rec = lvar_rec, ++ .key_set = lvar_key_set, ++ .key_cmp = lvar_key_cmp, ++ .key_size = lvar_key_size, ++ .rec_set = lvar_rec_set, ++ .lookup = lvar_lookup, ++ .at_end = lvar_at_end, ++ .rec_add = lvar_rec_add, ++ .rec_del = lvar_rec_del, ++ .can_add = lvar_can_add, ++ .split = lvar_split ++}; ++ ++/* ++ * Index operations. ++ */ ++ ++enum { ++ /* This is duplicated in lustre/utils/create_iam.c */ ++ /* egrep -i '^o?x?[olabcdef]*$' /usr/share/dict/words */ ++ IAM_LVAR_ROOT_MAGIC = 0xb01dface ++}; ++ ++/* This is duplicated in lustre/utils/create_iam.c */ ++struct lvar_root { ++ __le32 vr_magic; ++ __le16 vr_recsize; ++ __le16 vr_ptrsize; ++ u8 vr_indirect_levels; ++ u8 vr_padding0; ++ __le16 vr_padding1; ++}; ++ ++static __u32 lvar_root_ptr(struct iam_container *c) ++{ ++ return 0; ++} ++ ++static int lvar_node_init(struct iam_container *c, struct buffer_head *bh, ++ int root) ++{ ++ return 0; ++} ++ ++static struct iam_entry *lvar_root_inc(struct iam_container *c, ++ struct iam_path *path, ++ struct iam_frame *frame) ++{ ++ struct lvar_root *root; ++ struct iam_entry *entries; ++ ++ entries = frame->entries; ++ ++ dx_set_count(entries, 2); ++ assert(dx_get_limit(entries) == dx_root_limit(path)); ++ ++ root = (void *)frame->bh->b_data; ++ assert(le64_to_cpu(root->vr_magic) == IAM_LVAR_ROOT_MAGIC); ++ root->vr_indirect_levels ++; ++ return iam_entry_shift(path, entries, 1); ++} ++ ++static int lvar_node_check(struct iam_path *path, struct iam_frame *frame) ++{ ++ unsigned count; ++ unsigned limit; ++ unsigned limit_correct; ++ struct iam_entry *entries; ++ ++ entries = dx_node_get_entries(path, frame); ++ ++ if (frame == path->ip_frames) { ++ struct lvar_root *root; ++ ++ root = (void *)frame->bh->b_data; ++ if (le64_to_cpu(root->vr_magic) != IAM_LVAR_ROOT_MAGIC) { ++ BREAKPOINT; ++ return -EIO; ++ } ++ limit_correct = dx_root_limit(path); ++ } else ++ limit_correct = dx_node_limit(path); ++ count = dx_get_count(entries); ++ limit = dx_get_limit(entries); ++ if (count > limit) { ++ BREAKPOINT; ++ return -EIO; ++ } ++ if (limit != limit_correct) { ++ BREAKPOINT; ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int lvar_node_load(struct iam_path *path, struct iam_frame *frame) ++{ ++ struct iam_entry *entries; ++ void *data; ++ entries = dx_node_get_entries(path, frame); ++ ++ data = frame->bh->b_data; ++ ++ if (frame == path->ip_frames) { ++ struct lvar_root *root; ++ const char *name; ++ ++ root = data; ++ name = kchar(path->ip_key_target); ++ path->ip_indirect = root->vr_indirect_levels; ++ path->ip_ikey_target = iam_path_ikey(path, 4); ++ *(lvar_hash_t *)path->ip_ikey_target = ++ get_hash(path->ip_container, name, strlen(name)); ++ } ++ frame->entries = frame->at = entries; ++ return 0; ++} ++ ++static int lvar_ikeycmp(const struct iam_container *c, ++ const struct iam_ikey *k1, const struct iam_ikey *k2) ++{ ++ lvar_hash_t p1 = le32_to_cpu(*(lvar_hash_t *)k1); ++ lvar_hash_t p2 = le32_to_cpu(*(lvar_hash_t *)k2); ++ ++ return p1 > p2 ? +1 : (p1 < p2 ? -1 : 0); ++} ++ ++static struct iam_path_descr *lvar_ipd_alloc(const struct iam_container *c) ++{ ++ return iam_ipd_alloc(c->ic_descr->id_ikey_size); ++} ++ ++static void lvar_ipd_free(const struct iam_container *c, ++ struct iam_path_descr *ipd) ++{ ++ iam_ipd_free(ipd); ++} ++ ++static struct iam_operations lvar_ops = { ++ .id_root_ptr = lvar_root_ptr, ++ .id_node_read = iam_node_read, ++ .id_node_init = lvar_node_init, ++ .id_node_check = lvar_node_check, ++ .id_node_load = lvar_node_load, ++ .id_ikeycmp = lvar_ikeycmp, ++ .id_root_inc = lvar_root_inc, ++ .id_ipd_alloc = lvar_ipd_alloc, ++ .id_ipd_free = lvar_ipd_free, ++ .id_name = "lvar" ++}; ++ ++static int lvar_guess(struct iam_container *c) ++{ ++ int result; ++ struct buffer_head *bh; ++ const struct lvar_root *root; ++ ++ assert(c->ic_object != NULL); ++ ++ result = iam_node_read(c, lvar_root_ptr(c), NULL, &bh); ++ if (result == 0) { ++ root = (void *)bh->b_data; ++ if (le64_to_cpu(root->vr_magic) == IAM_LVAR_ROOT_MAGIC) { ++ struct iam_descr *descr; ++ ++ descr = c->ic_descr; ++ descr->id_key_size = EXT3_NAME_LEN; ++ descr->id_ikey_size = sizeof (lvar_hash_t); ++ descr->id_rec_size = le16_to_cpu(root->vr_recsize); ++ descr->id_ptr_size = le16_to_cpu(root->vr_ptrsize); ++ descr->id_root_gap = sizeof *root; ++ descr->id_node_gap = 0; ++ descr->id_ops = &lvar_ops; ++ descr->id_leaf_ops = &lvar_leaf_ops; ++ } else ++ result = -EBADF; ++ } ++ return result; ++} ++ ++static struct iam_format lvar_format = { ++ .if_guess = lvar_guess ++}; ++ ++void iam_lvar_format_init(void) ++{ ++ iam_format_register(&lvar_format); ++} ++ Index: iam/fs/ext3/namei.c =================================================================== --- iam.orig/fs/ext3/namei.c 2006-05-31 20:24:32.000000000 +0400 @@ -4551,7 +5338,7 @@ Index: iam/fs/ext3/namei.c Index: iam/include/linux/lustre_iam.h =================================================================== --- iam.orig/include/linux/lustre_iam.h 2006-05-31 20:24:32.000000000 +0400 -+++ iam/include/linux/lustre_iam.h 2006-06-29 18:50:12.000000000 +0400 ++++ iam/include/linux/lustre_iam.h 2006-07-03 01:03:10.000000000 +0400 @@ -1,9 +1,68 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: diff --git a/lustre/kernel_patches/patches/ext3-iam-uapi.patch b/lustre/kernel_patches/patches/ext3-iam-uapi.patch index 910169b..4c829bf 100644 --- a/lustre/kernel_patches/patches/ext3-iam-uapi.patch +++ b/lustre/kernel_patches/patches/ext3-iam-uapi.patch @@ -1,20 +1,20 @@ Index: iam/fs/ext3/Makefile =================================================================== ---- iam.orig/fs/ext3/Makefile 2006-06-29 18:50:12.000000000 +0400 -+++ iam/fs/ext3/Makefile 2006-06-29 18:50:13.000000000 +0400 +--- iam.orig/fs/ext3/Makefile 2006-07-03 01:03:10.000000000 +0400 ++++ iam/fs/ext3/Makefile 2006-07-03 01:03:11.000000000 +0400 @@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ ioctl.o namei.o super.o symlink.o hash.o resize.o \ - extents.o mballoc.o iam.o iam_lfix.o -+ extents.o mballoc.o iam.o iam_lfix.o iam_htree.o iam_uapi.o ++ extents.o mballoc.o iam.o iam_lfix.o iam_lvar.o iam_htree.o iam_uapi.o ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o Index: iam/fs/ext3/dir.c =================================================================== ---- iam.orig/fs/ext3/dir.c 2006-06-29 18:50:12.000000000 +0400 -+++ iam/fs/ext3/dir.c 2006-06-29 18:50:13.000000000 +0400 +--- iam.orig/fs/ext3/dir.c 2006-07-03 01:03:10.000000000 +0400 ++++ iam/fs/ext3/dir.c 2006-07-03 01:03:11.000000000 +0400 @@ -28,6 +28,7 @@ #include #include @@ -112,8 +112,8 @@ Index: iam/fs/ext3/dir.c (filp->f_version != inode->i_version)) { Index: iam/fs/ext3/file.c =================================================================== ---- iam.orig/fs/ext3/file.c 2006-06-29 18:50:12.000000000 +0400 -+++ iam/fs/ext3/file.c 2006-06-29 18:50:13.000000000 +0400 +--- iam.orig/fs/ext3/file.c 2006-07-03 01:03:10.000000000 +0400 ++++ iam/fs/ext3/file.c 2006-07-03 01:03:11.000000000 +0400 @@ -23,6 +23,7 @@ #include #include @@ -149,8 +149,8 @@ Index: iam/fs/ext3/file.c Index: iam/fs/ext3/iam-uapi.c =================================================================== --- iam.orig/fs/ext3/iam-uapi.c 2004-04-06 17:27:52.000000000 +0400 -+++ iam/fs/ext3/iam-uapi.c 2006-06-29 18:50:13.000000000 +0400 -@@ -0,0 +1,357 @@ ++++ iam/fs/ext3/iam-uapi.c 2006-07-03 01:03:11.000000000 +0400 +@@ -0,0 +1,361 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * @@ -199,7 +199,7 @@ Index: iam/fs/ext3/iam-uapi.c +}; + +enum { -+ IAM_INSERT_CREDITS = 10 ++ IAM_INSERT_CREDITS = 20 +}; + +static struct iam_private_info *get_ipi(struct file *filp) @@ -240,7 +240,7 @@ Index: iam/fs/ext3/iam-uapi.c + st = it->ii_state; + if (st == IAM_IT_ATTACHED || st == IAM_IT_SKEWED) + memcpy(itop->iui_op.iul_key, iam_it_key_get(it), -+ ipi->ipi_bag.ic_descr->id_key_size); ++ iam_it_key_size(it)); + if (st == IAM_IT_ATTACHED) + iam_reccpy(&it->ii_path, + itop->iui_op.iul_rec, iam_it_rec_get(it)); @@ -445,9 +445,13 @@ Index: iam/fs/ext3/iam-uapi.c + struct iam_uapi_it it; + enum outop_t opt; + -+ if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) ++ if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) { + result = -EACCES; -+ else if (cmd == IAM_IOC_INIT) { ++ } else if (cmd == IAM_IOC_POLYMORPH) { ++ inode->i_mode = (umode_t)arg; ++ mark_inode_dirty(inode); ++ result = 0; ++ } else if (cmd == IAM_IOC_INIT) { + if (filp->private_data == NULL) { + result = getua(&ua, arg); + if (result == 0) @@ -510,8 +514,8 @@ Index: iam/fs/ext3/iam-uapi.c +} Index: iam/fs/ext3/ioctl.c =================================================================== ---- iam.orig/fs/ext3/ioctl.c 2006-06-29 18:50:12.000000000 +0400 -+++ iam/fs/ext3/ioctl.c 2006-06-29 18:50:13.000000000 +0400 +--- iam.orig/fs/ext3/ioctl.c 2006-07-03 01:03:10.000000000 +0400 ++++ iam/fs/ext3/ioctl.c 2006-07-03 01:03:11.000000000 +0400 @@ -250,6 +250,6 @@ flags_err: @@ -522,8 +526,8 @@ Index: iam/fs/ext3/ioctl.c } Index: iam/include/linux/lustre_iam.h =================================================================== ---- iam.orig/include/linux/lustre_iam.h 2006-06-29 18:50:12.000000000 +0400 -+++ iam/include/linux/lustre_iam.h 2006-06-29 18:50:13.000000000 +0400 +--- iam.orig/include/linux/lustre_iam.h 2006-07-03 01:03:10.000000000 +0400 ++++ iam/include/linux/lustre_iam.h 2006-07-03 01:03:11.000000000 +0400 @@ -30,9 +30,6 @@ #ifndef __LINUX_LUSTRE_IAM_H__ #define __LINUX_LUSTRE_IAM_H__ @@ -584,7 +588,7 @@ Index: iam/include/linux/lustre_iam.h typedef __u64 iam_ptr_t; /* -@@ -123,6 +134,27 @@ struct iam_leaf { +@@ -123,6 +134,31 @@ struct iam_leaf { void *il_descr_data; }; @@ -593,6 +597,10 @@ Index: iam/include/linux/lustre_iam.h + */ +enum iam_lookup_t { + /* ++ * lookup found a record with the key requested ++ */ ++ IAM_LOOKUP_EXACT, ++ /* + * lookup positioned leaf on some record + */ + IAM_LOOKUP_OK, @@ -612,7 +620,7 @@ Index: iam/include/linux/lustre_iam.h struct iam_operations { /* * Returns pointer (in the same sense as pointer in index entry) to -@@ -131,11 +163,15 @@ struct iam_operations { +@@ -131,11 +167,15 @@ struct iam_operations { __u32 (*id_root_ptr)(struct iam_container *c); /* @@ -630,7 +638,7 @@ Index: iam/include/linux/lustre_iam.h * Initialize new node (stored in @bh) that is going to be added into * tree. */ -@@ -144,23 +180,33 @@ struct iam_operations { +@@ -144,23 +184,33 @@ struct iam_operations { int (*id_node_read)(struct iam_container *c, iam_ptr_t ptr, handle_t *h, struct buffer_head **bh); /* @@ -672,7 +680,7 @@ Index: iam/include/linux/lustre_iam.h struct iam_leaf_operations { /* * leaf operations. -@@ -186,7 +232,8 @@ struct iam_leaf_operations { +@@ -186,7 +236,8 @@ struct iam_leaf_operations { void (*start)(struct iam_leaf *l); /* more leaf to the next entry. */ void (*next)(struct iam_leaf *l); @@ -682,7 +690,7 @@ Index: iam/include/linux/lustre_iam.h * either pointer to the key stored in node, or copy key into * @k buffer supplied by caller and return pointer to this * buffer. The latter approach is used when keys in nodes are -@@ -194,8 +241,10 @@ struct iam_leaf_operations { +@@ -194,8 +245,10 @@ struct iam_leaf_operations { * all). * * Caller should assume that returned pointer is only valid @@ -695,16 +703,17 @@ Index: iam/include/linux/lustre_iam.h /* return pointer to entry body. Pointer is valid while corresponding leaf node is locked and pinned. */ struct iam_rec *(*rec)(const struct iam_leaf *l); -@@ -203,6 +252,8 @@ struct iam_leaf_operations { +@@ -203,6 +256,9 @@ struct iam_leaf_operations { void (*key_set)(struct iam_leaf *l, const struct iam_key *k); void (*rec_set)(struct iam_leaf *l, const struct iam_rec *r); + int (*key_cmp)(const struct iam_leaf *l, const struct iam_key *k); + ++ int (*key_size)(const struct iam_leaf *l); /* * Search leaf @l for a record with key @k or for a place * where such record is to be inserted. -@@ -221,12 +272,13 @@ struct iam_leaf_operations { +@@ -221,12 +277,13 @@ struct iam_leaf_operations { /* * remove rec for a leaf */ @@ -720,7 +729,7 @@ Index: iam/include/linux/lustre_iam.h }; struct iam_path *iam_leaf_path(const struct iam_leaf *leaf); -@@ -241,6 +293,10 @@ struct iam_descr { +@@ -241,6 +298,10 @@ struct iam_descr { */ size_t id_key_size; /* @@ -731,7 +740,7 @@ Index: iam/include/linux/lustre_iam.h * Size of a pointer to the next level (stored in index nodes), in * bytes. */ -@@ -264,6 +320,9 @@ struct iam_descr { +@@ -264,6 +325,9 @@ struct iam_descr { struct iam_leaf_operations *id_leaf_ops; }; @@ -741,7 +750,7 @@ Index: iam/include/linux/lustre_iam.h struct iam_container { /* * Underlying flat file. IO against this object is issued to -@@ -284,7 +343,7 @@ struct iam_path_descr { +@@ -284,7 +348,7 @@ struct iam_path_descr { /* * Scratch-pad area for temporary keys. */ @@ -750,7 +759,7 @@ Index: iam/include/linux/lustre_iam.h }; /* -@@ -316,6 +375,7 @@ struct iam_path { +@@ -316,6 +380,7 @@ struct iam_path { * Key searched for. */ const struct iam_key *ip_key_target; @@ -758,7 +767,7 @@ Index: iam/include/linux/lustre_iam.h /* * Description-specific data. */ -@@ -334,6 +394,7 @@ struct iam_path_compat { +@@ -334,6 +399,7 @@ struct iam_path_compat { struct dx_hash_info *ipc_hinfo; struct dentry *ipc_dentry; struct iam_path_descr ipc_descr; @@ -766,7 +775,7 @@ Index: iam/include/linux/lustre_iam.h }; /* -@@ -347,7 +408,9 @@ enum iam_it_state { +@@ -347,7 +413,9 @@ enum iam_it_state { /* initial state */ IAM_IT_DETACHED, /* iterator is above particular record in the container */ @@ -777,7 +786,7 @@ Index: iam/include/linux/lustre_iam.h }; /* -@@ -355,7 +418,7 @@ enum iam_it_state { +@@ -355,7 +423,7 @@ enum iam_it_state { */ enum iam_it_flags { /* @@ -786,7 +795,7 @@ Index: iam/include/linux/lustre_iam.h */ IAM_IT_MOVE = (1 << 0), /* -@@ -372,15 +435,26 @@ enum iam_it_flags { +@@ -372,15 +440,26 @@ enum iam_it_flags { * doesn't point to any particular record in this container. * * After successful call to iam_it_get() and until corresponding call to @@ -816,7 +825,7 @@ Index: iam/include/linux/lustre_iam.h * */ struct iam_iterator { -@@ -390,7 +464,8 @@ struct iam_iterator { +@@ -390,7 +469,8 @@ struct iam_iterator { __u32 ii_flags; enum iam_it_state ii_state; /* @@ -826,7 +835,7 @@ Index: iam/include/linux/lustre_iam.h */ struct iam_path ii_path; }; -@@ -405,133 +480,24 @@ void iam_path_compat_fini(struct iam_pat +@@ -405,133 +485,25 @@ void iam_path_compat_fini(struct iam_pat struct iam_path_descr *iam_ipd_alloc(int keysize); void iam_ipd_free(struct iam_path_descr *ipd); @@ -930,6 +939,7 @@ Index: iam/include/linux/lustre_iam.h - * !memcmp(iam_it_rec_get(it), r, ...)) - */ +struct iam_key *iam_it_key_get(const struct iam_iterator *it); ++int iam_it_key_size(const struct iam_iterator *it); int iam_it_rec_insert(handle_t *h, struct iam_iterator *it, const struct iam_key *k, const struct iam_rec *r); -/* @@ -962,7 +972,7 @@ Index: iam/include/linux/lustre_iam.h int iam_it_load(struct iam_iterator *it, iam_pos_t pos); int iam_lookup(struct iam_container *c, const struct iam_key *k, -@@ -577,16 +543,65 @@ static inline struct inode *iam_path_obj +@@ -577,16 +549,65 @@ static inline struct inode *iam_path_obj return p->ip_container->ic_object; } @@ -975,18 +985,14 @@ Index: iam/include/linux/lustre_iam.h +} + +static inline size_t iam_entry_size(struct iam_path *p) - { -- memcpy(k1, k2, c->ic_descr->id_key_size); ++{ + return iam_path_descr(p)->id_ikey_size + iam_path_descr(p)->id_ptr_size; - } - --static inline int iam_keycmp(const struct iam_container *c, -- const struct iam_key *k1, const struct iam_key *k2) ++} ++ +static inline struct iam_entry *iam_entry_shift(struct iam_path *p, + struct iam_entry *entry, + int shift) - { -- return c->ic_descr->id_ops->id_keycmp(c, k1, k2); ++{ + void *e = entry; + return e + shift * iam_entry_size(p); +} @@ -1021,20 +1027,24 @@ Index: iam/include/linux/lustre_iam.h + */ +static inline void iam_ikeycpy0(const struct iam_container *c, + struct iam_ikey *k1, const struct iam_ikey *k2) -+{ + { +- memcpy(k1, k2, c->ic_descr->id_key_size); + if (k1 != k2) + iam_ikeycpy(c, k1, k2); -+} -+ + } + +-static inline int iam_keycmp(const struct iam_container *c, +- const struct iam_key *k1, const struct iam_key *k2) +static inline int iam_ikeycmp(const struct iam_container *c, + const struct iam_ikey *k1, + const struct iam_ikey *k2) -+{ + { +- return c->ic_descr->id_ops->id_keycmp(c, k1, k2); + return c->ic_descr->id_ops->id_ikeycmp(c, k1, k2); } static inline void iam_reccpy(const struct iam_path *p, struct iam_rec *rec_dst, -@@ -604,7 +619,7 @@ static inline void *iam_entry_off(struct +@@ -604,7 +625,7 @@ static inline void *iam_entry_off(struct static inline unsigned dx_get_block(struct iam_path *p, struct iam_entry *entry) { return le32_to_cpu(*(u32*)iam_entry_off(entry, @@ -1043,7 +1053,7 @@ Index: iam/include/linux/lustre_iam.h & 0x00ffffff; } -@@ -612,21 +627,64 @@ static inline void dx_set_block(struct i +@@ -612,21 +633,64 @@ static inline void dx_set_block(struct i struct iam_entry *entry, unsigned value) { *(u32*)iam_entry_off(entry, @@ -1112,7 +1122,7 @@ Index: iam/include/linux/lustre_iam.h static inline unsigned dx_get_count(struct iam_entry *entries) { return le16_to_cpu(((struct dx_countlimit *) entries)->count); -@@ -647,9 +705,18 @@ static inline unsigned dx_node_limit(str +@@ -647,9 +711,18 @@ static inline unsigned dx_node_limit(str struct iam_descr *param = iam_path_descr(p); unsigned entry_space = iam_path_obj(p)->i_sb->s_blocksize - param->id_node_gap; @@ -1132,7 +1142,7 @@ Index: iam/include/linux/lustre_iam.h static inline struct iam_entry *dx_get_entries(struct iam_path *path, void *data, int root) { -@@ -665,7 +732,8 @@ static inline struct iam_entry *dx_node_ +@@ -665,7 +738,8 @@ static inline struct iam_entry *dx_node_ frame->bh->b_data, frame == path->ip_frames); } @@ -1142,7 +1152,7 @@ Index: iam/include/linux/lustre_iam.h { assert(0 <= nr && nr < ARRAY_SIZE(path->ip_data->ipd_key_scratch)); return path->ip_data->ipd_key_scratch[nr]; -@@ -674,6 +742,7 @@ static inline struct iam_key *iam_path_k +@@ -674,6 +748,7 @@ static inline struct iam_key *iam_path_k int dx_lookup(struct iam_path *path); void dx_insert_block(struct iam_path *path, struct iam_frame *frame, u32 hash, u32 block); @@ -1150,7 +1160,7 @@ Index: iam/include/linux/lustre_iam.h int ext3_htree_next_block(struct inode *dir, __u32 hash, struct iam_path *path, __u32 *start_hash); -@@ -681,6 +750,21 @@ int ext3_htree_next_block(struct inode * +@@ -681,6 +756,21 @@ int ext3_htree_next_block(struct inode * struct buffer_head *ext3_append(handle_t *handle, struct inode *inode, u32 *block, int *err); int split_index_node(handle_t *handle, struct iam_path *path); @@ -1172,7 +1182,7 @@ Index: iam/include/linux/lustre_iam.h /* * external -@@ -698,10 +782,12 @@ int iam_node_read(struct iam_container * +@@ -698,10 +788,12 @@ int iam_node_read(struct iam_container * handle_t *handle, struct buffer_head **bh); void iam_insert_key(struct iam_path *path, struct iam_frame *frame, @@ -1186,7 +1196,7 @@ Index: iam/include/linux/lustre_iam.h struct iam_path *iam_leaf_path(const struct iam_leaf *leaf); struct iam_container *iam_leaf_container(const struct iam_leaf *leaf); -@@ -709,14 +795,76 @@ struct iam_descr *iam_leaf_descr(const s +@@ -709,14 +801,79 @@ struct iam_descr *iam_leaf_descr(const s struct iam_leaf_operations *iam_leaf_ops(const struct iam_leaf *leaf); @@ -1216,6 +1226,7 @@ Index: iam/include/linux/lustre_iam.h void iam_format_register(struct iam_format *fmt); void iam_lfix_format_init(void); ++void iam_lvar_format_init(void); +void iam_htree_format_init(void); + +struct iam_private_info; @@ -1258,7 +1269,9 @@ Index: iam/include/linux/lustre_iam.h + IAM_IOC_DELETE = _IOR('i', 5, struct iam_uapi_op), + IAM_IOC_IT_START = _IOR('i', 6, struct iam_uapi_it), + IAM_IOC_IT_NEXT = _IOW('i', 7, struct iam_uapi_it), -+ IAM_IOC_IT_STOP = _IOR('i', 8, struct iam_uapi_it) ++ IAM_IOC_IT_STOP = _IOR('i', 8, struct iam_uapi_it), ++ ++ IAM_IOC_POLYMORPH = _IOR('i', 9, unsigned long) +}; /* __LINUX_LUSTRE_IAM_H__ */ diff --git a/lustre/ldiskfs/Makefile.in b/lustre/ldiskfs/Makefile.in index 5a05bf8..2afd2cf 100644 --- a/lustre/ldiskfs/Makefile.in +++ b/lustre/ldiskfs/Makefile.in @@ -11,7 +11,8 @@ ext3_headers := $(wildcard @LINUX@/fs/ext3/*.h) linux_headers := $(wildcard @LINUX@/include/linux/ext3*.h) ext3_sources := $(filter-out %.mod.c,$(wildcard @LINUX@/fs/ext3/*.c)) -new_sources := iopen.c iopen.h extents.c mballoc.c iam.c iam_lfix.c iam_htree.c iam-uapi.c +new_sources := iopen.c iopen.h extents.c mballoc.c \ + iam.c iam_lfix.c iam_lvar.c iam_htree.c iam-uapi.c new_headers := ext3_extents.h ldiskfs_patched_sources := $(notdir $(ext3_sources) $(ext3_headers)) $(new_sources) $(new_headers) ldiskfs_sources := $(ldiskfs_patched_sources) diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 61800c4..e9c6608 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -209,7 +209,7 @@ static int mdt_getattr_pack_msg(struct mdt_thread_info *info) CERROR("MD size %d larger than maximum possible %u\n", rc, MAX_MD_SIZE); } else { - req_capsule_set_size(pill, &RMF_MDT_MD, + req_capsule_set_size(pill, &RMF_MDT_MD, RCL_SERVER, rc); } } else if (S_ISLNK(la->la_mode) && (body->valid & OBD_MD_LINKNAME)) { @@ -233,7 +233,7 @@ static int mdt_getattr_pack_msg(struct mdt_thread_info *info) } req_capsule_set_size(pill, &RMF_EADATA, RCL_SERVER, 0); } else - req_capsule_set_size(pill, &RMF_EADATA, + req_capsule_set_size(pill, &RMF_EADATA, RCL_SERVER, rc); } #endif @@ -405,7 +405,7 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info, /*step 3: find the child object by fid & lock it*/ lhc->mlh_mode = LCK_CR; - child = mdt_object_find_lock(info->mti_ctxt, info->mti_mdt, + child = mdt_object_find_lock(info->mti_ctxt, info->mti_mdt, &child_fid, lhc, child_bits); if (IS_ERR(child)) GOTO(out_parent, result = PTR_ERR(child)); @@ -1043,7 +1043,7 @@ static int mdt_req_handle(struct mdt_thread_info *info, /* If we're DISCONNECTing, the mdt_export_data is already freed */ if (result == 0 && h->mh_opc != MDS_DISCONNECT) { #ifdef MDT_CODE - /* FIXME: fake untill journal callback & open handling is OK.*/ + /* FIXME: fake untill journal callback & open handling is OK.*/ __u64 last_transno; __u64 last_committed; struct mdt_device *mdt = info->mti_mdt; @@ -1053,7 +1053,7 @@ static int mdt_req_handle(struct mdt_thread_info *info, last_transno = ++ (mdt->mdt_last_transno); last_committed = ++ (mdt->mdt_last_committed); spin_unlock(&mdt->mdt_transno_lock); - + req->rq_repmsg->transno = req->rq_transno = last_transno; req->rq_repmsg->last_xid = req->rq_xid; req->rq_repmsg->last_committed = last_committed; @@ -1474,7 +1474,10 @@ static int mdt_intent_getattr(enum mdt_it_code opcode, } rc = mdt_getattr_name_lock(info, &lhc, child_bits); - ldlm_rep = req_capsule_server_get(&info->mti_pill, + /* + * XXX nikita: if rc != 0, reply message is not necessary packed. + */ + ldlm_rep = req_capsule_server_get(&info->mti_pill, &RMF_DLM_REP); if (rc) intent_set_disposition(ldlm_rep, DISP_LOOKUP_NEG); @@ -1495,7 +1498,7 @@ static int mdt_intent_getattr(enum mdt_it_code opcode, new_lock = ldlm_handle2lock(&lhc.mlh_lh); if (new_lock == NULL && (flags & LDLM_FL_INTENT_ONLY)) RETURN(0); - + LASSERTF(new_lock != NULL, "op %d lockh "LPX64"\n", opcode, lhc.mlh_lh.cookie); @@ -1705,7 +1708,7 @@ static int mdt_seq_fini(const struct lu_context *ctx, } static int mdt_seq_init(const struct lu_context *ctx, - const char *uuid, + const char *uuid, struct mdt_device *m) { struct lu_site *ls; @@ -1720,7 +1723,7 @@ static int mdt_seq_init(const struct lu_context *ctx, OBD_ALLOC_PTR(ls->ls_ctlr_seq); if (ls->ls_ctlr_seq != NULL) { - rc = seq_server_init(ls->ls_ctlr_seq, + rc = seq_server_init(ls->ls_ctlr_seq, m->mdt_bottom, uuid, LUSTRE_SEQ_CTLR, ctx); @@ -1734,7 +1737,7 @@ static int mdt_seq_init(const struct lu_context *ctx, OBD_ALLOC_PTR(ls->ls_server_seq); if (ls->ls_server_seq != NULL) { - rc = seq_server_init(ls->ls_server_seq, + rc = seq_server_init(ls->ls_server_seq, m->mdt_bottom, uuid, LUSTRE_SEQ_SRV, ctx); @@ -1822,17 +1825,17 @@ static void mdt_seq_fini_ctlr(struct mdt_device *m) if (ls && ls->ls_server_seq) seq_server_fini_ctlr(ls->ls_server_seq); - + if (ls && ls->ls_client_seq) { seq_client_fini(ls->ls_client_seq); OBD_FREE_PTR(ls->ls_client_seq); ls->ls_client_seq = NULL; } - + if (ls && ls->ls_ctlr_exp) { int rc = obd_disconnect(ls->ls_ctlr_exp); ls->ls_ctlr_exp = NULL; - + if (rc) { CERROR("failure to disconnect " "obd: %d\n", rc); @@ -1845,7 +1848,7 @@ static void mdt_seq_fini_ctlr(struct mdt_device *m) * FLD wrappers */ static int mdt_fld_init(const struct lu_context *ctx, - const char *uuid, + const char *uuid, struct mdt_device *m) { struct lu_site *ls; @@ -2400,8 +2403,8 @@ static int mdt_notify(struct obd_device *obd, struct obd_device *watched, rc = next->ld_ops->ldo_notify(&ctxt, next, watched, ev, data); lu_context_exit(&ctxt); out: - lu_context_fini(&ctxt); - RETURN(rc); + lu_context_fini(&ctxt); + RETURN(rc); } static struct obd_ops mdt_obd_device_ops = { diff --git a/lustre/tests/iam_ut b/lustre/tests/iam_ut index 958c0f451b50fbb42e87bed663e161dce42f0d2b..3cf58045d22fbf37f89868a73edfad1942aa1d25 100755 GIT binary patch delta 28924 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 Nd+BtV_r{OW{|{cd$rAto delta 27966 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 [options] \n", progname); - fprintf(out, + fprintf(out, "\t:block device or file (e.g /dev/sda or /tmp/ost1)\n" "\ttarget types:\n" "\t\t--ost: object storage, mutually exclusive with mdt\n" @@ -105,7 +105,7 @@ static void fatal(void) /*================ utility functions =====================*/ -inline unsigned int +inline unsigned int dev_major (unsigned long long int __dev) { return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff); @@ -126,16 +126,16 @@ int get_os_version() char release[4] = ""; fd = open("/proc/sys/kernel/osrelease", O_RDONLY); - if (fd < 0) + if (fd < 0) fprintf(stderr, "%s: Warning: Can't resolve kernel " "version, assuming 2.6\n", progname); else { read(fd, release, 4); close(fd); } - if (strncmp(release, "2.4.", 4) == 0) + if (strncmp(release, "2.4.", 4) == 0) version = 24; - else + else version = 26; } return version; @@ -145,10 +145,10 @@ int run_command(char *cmd) { char log[] = "/tmp/mkfs_logXXXXXX"; int fd, rc; - + if (verbose > 1) printf("cmd: %s\n", cmd); - + if ((fd = mkstemp(log)) >= 0) { close(fd); strcat(cmd, " >"); @@ -164,16 +164,16 @@ int run_command(char *cmd) fp = fopen(log, "r"); if (fp) { while (fgets(buf, sizeof(buf), fp) != NULL) { - if (rc || verbose > 2) + if (rc || verbose > 2) printf(" %s", buf); } fclose(fp); } } - if (fd >= 0) + if (fd >= 0) remove(log); return rc; -} +} static int check_mtab_entry(char *spec, char *type) { @@ -222,7 +222,7 @@ int loop_setup(struct mkfs_opts *mop) for (i = 0; i < MAX_LOOP_DEVICES; i++) { char cmd[128]; sprintf(l_device, "%s%d", loop_base, i); - if (access(l_device, F_OK | R_OK)) + if (access(l_device, F_OK | R_OK)) break; sprintf(cmd, "losetup %s > /dev/null 2>&1", l_device); ret = system(cmd); @@ -240,10 +240,10 @@ int loop_setup(struct mkfs_opts *mop) return ret; } } - + fprintf(stderr, "%s: out of loop devices!\n", progname); return EMFILE; -} +} int loop_cleanup(struct mkfs_opts *mop) { @@ -263,7 +263,7 @@ int is_block(char* devname) int ret = 0; ret = access(devname, F_OK); - if (ret != 0) + if (ret != 0) return 0; ret = stat(devname, &st); if (ret != 0) { @@ -273,14 +273,14 @@ int is_block(char* devname) return S_ISBLK(st.st_mode); } -__u64 get_device_size(char* device) +__u64 get_device_size(char* device) { int ret, fd; __u64 size = 0; fd = open(device, O_RDONLY); if (fd < 0) { - fprintf(stderr, "%s: cannot open %s: %s\n", + fprintf(stderr, "%s: cannot open %s: %s\n", progname, device, strerror(errno)); return 0; } @@ -289,11 +289,11 @@ __u64 get_device_size(char* device) ret = ioctl(fd, BLKGETSIZE64, (void*)&size); close(fd); if (ret < 0) { - fprintf(stderr, "%s: size ioctl failed: %s\n", + fprintf(stderr, "%s: size ioctl failed: %s\n", progname, strerror(errno)); return 0; } - + vprint("device size = "LPU64"MB\n", size >> 20); /* return value in KB */ return size >> 10; @@ -302,7 +302,7 @@ __u64 get_device_size(char* device) int loop_format(struct mkfs_opts *mop) { int ret = 0; - + if (mop->mo_device_sz == 0) { fatal(); fprintf(stderr, "loop device requires a --device-size= " @@ -314,7 +314,7 @@ int loop_format(struct mkfs_opts *mop) ret = truncate(mop->mo_device, mop->mo_device_sz * 1024); if (ret != 0) { ret = errno; - fprintf(stderr, "%s: Unable to create backing store: %d\n", + fprintf(stderr, "%s: Unable to create backing store: %d\n", progname, ret); } @@ -350,8 +350,8 @@ static int file_in_dev(char *file_name, char *dev_name) /* Filesystem has unsupported feature */ vprint("%.*s", i, debugfs_cmd); /* in all likelihood, the "unsupported feature" is - 'extents', which older debugfs does not understand. - Use e2fsprogs-1.38-cfs1 or later, available from + 'extents', which older debugfs does not understand. + Use e2fsprogs-1.38-cfs1 or later, available from ftp://ftp.lustre.org/pub/lustre/other/e2fsprogs/ */ return -1; } @@ -364,13 +364,13 @@ static int is_lustre_target(struct mkfs_opts *mop) { int rc; vprint("checking for existing Lustre data\n"); - + if ((rc = file_in_dev(MOUNT_DATA_FILE, mop->mo_device)) - || (rc = file_in_dev(LAST_RCVD, mop->mo_device))) { + || (rc = file_in_dev(LAST_RCVD, mop->mo_device))) { vprint("found Lustre data\n"); /* in the -1 case, 'extents' means this really IS a lustre target */ - return rc; + return rc; } return 0; /* The device is not a lustre target. */ @@ -393,16 +393,16 @@ int make_lustre_backfs(struct mkfs_opts *mop) return EINVAL; } block_count = mop->mo_device_sz / (L_BLOCK_SIZE >> 10); - } - + } + if ((mop->mo_ldd.ldd_mount_type == LDD_MT_EXT3) || - (mop->mo_ldd.ldd_mount_type == LDD_MT_LDISKFS)) { + (mop->mo_ldd.ldd_mount_type == LDD_MT_LDISKFS)) { __u64 device_sz = mop->mo_device_sz; /* we really need the size */ if (device_sz == 0) { device_sz = get_device_size(mop->mo_device); - if (device_sz == 0) + if (device_sz == 0) return ENODEV; } @@ -425,22 +425,22 @@ int make_lustre_backfs(struct mkfs_opts *mop) /* Default bytes_per_inode is block size */ if (strstr(mop->mo_mkfsopts, "-i") == NULL) { long bytes_per_inode = 0; - - if (IS_MDT(&mop->mo_ldd)) + + if (IS_MDT(&mop->mo_ldd)) bytes_per_inode = 4096; /* Allocate fewer inodes on large OST devices. Most - filesystems can be much more aggressive than even + filesystems can be much more aggressive than even this. */ - if ((IS_OST(&mop->mo_ldd) && (device_sz > 1000000))) + if ((IS_OST(&mop->mo_ldd) && (device_sz > 1000000))) bytes_per_inode = 16384; - + if (bytes_per_inode > 0) { sprintf(buf, " -i %ld", bytes_per_inode); strcat(mop->mo_mkfsopts, buf); } } - + /* This is an undocumented mke2fs option. Default is 128. */ if (strstr(mop->mo_mkfsopts, "-I") == NULL) { long inode_size = 0; @@ -452,10 +452,10 @@ int make_lustre_backfs(struct mkfs_opts *mop) inode_size = 2048; else if (mop->mo_stripe_count > 13) inode_size = 1024; - else + else inode_size = 512; } else if (IS_OST(&mop->mo_ldd)) { - /* now as we store fids in EA on OST we need + /* now as we store fids in EA on OST we need to make inode bigger */ inode_size = 256; } @@ -464,7 +464,7 @@ int make_lustre_backfs(struct mkfs_opts *mop) sprintf(buf, " -I %ld", inode_size); strcat(mop->mo_mkfsopts, buf); } - + } if (verbose < 2) { @@ -476,7 +476,7 @@ int make_lustre_backfs(struct mkfs_opts *mop) strcat(mop->mo_mkfsopts, " -O dir_index"); } - /* Allow reformat of full devices (as opposed to + /* Allow reformat of full devices (as opposed to partitions.) We already checked for mounted dev. */ strcat(mop->mo_mkfsopts, " -F"); @@ -485,7 +485,7 @@ int make_lustre_backfs(struct mkfs_opts *mop) } else if (mop->mo_ldd.ldd_mount_type == LDD_MT_REISERFS) { long journal_sz = 0; /* FIXME default journal size */ - if (journal_sz > 0) { + if (journal_sz > 0) { sprintf(buf, " --journal_size %ld", journal_sz); strcat(mop->mo_mkfsopts, buf); } @@ -493,16 +493,16 @@ int make_lustre_backfs(struct mkfs_opts *mop) } else { fprintf(stderr,"%s: unsupported fs type: %d (%s)\n", - progname, mop->mo_ldd.ldd_mount_type, + progname, mop->mo_ldd.ldd_mount_type, MT_STR(&mop->mo_ldd)); return EINVAL; } /* For loop device format the dev, not the filename */ dev = mop->mo_device; - if (mop->mo_flags & MO_IS_LOOP) + if (mop->mo_flags & MO_IS_LOOP) dev = mop->mo_loopdev; - + vprint("formatting backing filesystem %s on %s\n", MT_STR(&mop->mo_ldd), dev); vprint("\ttarget name %s\n", mop->mo_ldd.ldd_svname); @@ -536,7 +536,7 @@ void print_ldd(char *str, struct lustre_disk_data *ldd) { printf("\n %s:\n", str); printf("Target: %s\n", ldd->ldd_svname); - if (ldd->ldd_svindex == INDEX_UNASSIGNED) + if (ldd->ldd_svindex == INDEX_UNASSIGNED) printf("Index: unassigned\n"); else printf("Index: %d\n", ldd->ldd_svindex); @@ -545,7 +545,7 @@ void print_ldd(char *str, struct lustre_disk_data *ldd) printf("Mount type: %s\n", MT_STR(ldd)); printf("Flags: %#x\n", ldd->ldd_flags); printf(" (%s%s%s%s%s%s%s%s)\n", - IS_MDT(ldd) ? "MDT ":"", + IS_MDT(ldd) ? "MDT ":"", IS_OST(ldd) ? "OST ":"", IS_MGS(ldd) ? "MGS ":"", ldd->ldd_flags & LDD_F_NEED_INDEX ? "needs_index ":"", @@ -575,15 +575,15 @@ int write_local_files(struct mkfs_opts *mop) } dev = mop->mo_device; - if (mop->mo_flags & MO_IS_LOOP) + if (mop->mo_flags & MO_IS_LOOP) dev = mop->mo_loopdev; - + ret = mount(dev, mntpt, MT_STR(&mop->mo_ldd), 0, NULL); if (ret) { - fprintf(stderr, "%s: Unable to mount %s: %s\n", + fprintf(stderr, "%s: Unable to mount %s: %s\n", progname, dev, strerror(errno)); if (errno == ENODEV) { - fprintf(stderr, "Is the %s module available?\n", + fprintf(stderr, "Is the %s module available?\n", MT_STR(&mop->mo_ldd)); } goto out_rmdir; @@ -593,17 +593,7 @@ int write_local_files(struct mkfs_opts *mop) sprintf(filepnm, "%s/%s", mntpt, MOUNT_CONFIGS_DIR); ret = mkdir(filepnm, 0777); if ((ret != 0) && (errno != EEXIST)) { - fprintf(stderr, "%s: Can't make configs dir %s (%d)\n", - progname, filepnm, ret); - goto out_umnt; - } else if (errno == EEXIST) { - ret = 0; - } - - sprintf(filepnm, "%s/%s", mntpt, "oi"); - ret = mkdir(filepnm, 0777); - if ((ret != 0) && (errno != EEXIST)) { - fprintf(stderr, "%s: Can't make oi dir %s (%d)\n", + fprintf(stderr, "%s: Can't make configs dir %s (%d)\n", progname, filepnm, ret); goto out_umnt; } else if (errno == EEXIST) { -- 1.8.3.1