X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdclass%2Fmea.c;h=15f15d895ce2e3059efbde90a34a14e4ae32a3f1;hb=6957329b064f72db289ae93d0a7776cb9faa3961;hp=fa9ce2aa7ba4253e928135b07f5d6fc4e6f2472e;hpb=fc4de168e941017bce61765080c15982cb33dd88;p=fs%2Flustre-release.git diff --git a/lustre/obdclass/mea.c b/lustre/obdclass/mea.c index fa9ce2a..15f15d8 100644 --- a/lustre/obdclass/mea.c +++ b/lustre/obdclass/mea.c @@ -20,57 +20,162 @@ */ #define DEBUG_SUBSYSTEM S_CLASS +#include #ifdef __KERNEL__ #include /* for request_module() */ #include -#include #include #include #include -#else +#else #include -#include -#include +#include #endif -#include +#include +#include - -int mea_name2idx(struct mea *mea, char *name, int namelen) +#ifdef __KERNEL__ +#include +#ifdef HAVE_SERVER_SUPPORT +/* LDISKFS_SB() */ +#include +#endif +#endif +static int mea_last_char_hash(int count, char *name, int namelen) { unsigned int c; - /* just to simplify caller code */ - if (mea == NULL) - return 0; - - if (mea->mea_count == 0) - return 0; - - /* FIXME: real hash calculation here */ c = name[namelen - 1]; if (c == 0) CWARN("looks like wrong len is passed\n"); - c = c % mea->mea_count; - - LASSERT(c < mea->mea_count); + c = c % count; return c; } -int raw_name2idx(int count, const char *name, int namelen) +static int mea_all_chars_hash(int count, char *name, int namelen) { - unsigned int c; + unsigned int c = 0; + + while (--namelen >= 0) + c += name[namelen]; + c = c % count; + return c; +} + +#ifdef __KERNEL__ +/* This hash calculate method must be same as the lvar hash method */ + +#define LVAR_HASH_SANDWICH (0) +#define LVAR_HASH_TEA (1) +#define LVAR_HASH_R5 (0) +#define LVAR_HASH_PREFIX (0) + +static __u32 hash_build0(const char *name, int namelen) +{ + __u32 result; + + if (namelen == 0) + return 0; + if (strncmp(name, ".", 1) == 0 && namelen == 1) + return 1; + if (strncmp(name, "..", 2) == 0 && namelen == 2) + return 2; + + if (LVAR_HASH_PREFIX) { + result = 0; + strncpy((void *)&result, + name, min(namelen, (int)sizeof result)); + } else { + struct ldiskfs_dx_hash_info hinfo; + + if (LVAR_HASH_TEA) + hinfo.hash_version = LDISKFS_DX_HASH_TEA; + else + hinfo.hash_version = LDISKFS_DX_HASH_R5; + hinfo.seed = 0; + ldiskfsfs_dirhash(name, namelen, &hinfo); + result = hinfo.hash; + if (LVAR_HASH_SANDWICH) { + __u32 result2; + + hinfo.hash_version = LDISKFS_DX_HASH_TEA; + hinfo.seed = 0; + ldiskfsfs_dirhash(name, namelen, &hinfo); + result2 = hinfo.hash; + result = (0xfc000000 & result2) | (0x03ffffff & result); + } + } + + return result; +} + +enum { + HASH_GRAY_AREA = 1024 +}; + +static __u32 hash_build(const char *name, int namelen) +{ + __u32 hash; + + hash = (hash_build0(name, namelen) << 1) & MAX_HASH_SIZE; + if (hash > MAX_HASH_SIZE - HASH_GRAY_AREA) + hash &= HASH_GRAY_AREA - 1; + return hash; +} + +static int mea_hash_segment(int count, const char *name, int namelen) +{ + __u32 hash; + + LASSERT(IS_PO2(MAX_HASH_SIZE + 1)); + + hash = hash_build(name, namelen) / (MAX_HASH_SIZE / count); + LASSERTF(hash < count, "hash %x count %d \n", hash, count); + + return hash; +} +#else +static int mea_hash_segment(int count, char *name, int namelen) +{ +#warning "fix for liblustre" + return 0; +} +#endif +int raw_name2idx(int hashtype, int count, const char *name, int namelen) +{ + unsigned int c = 0; LASSERT(namelen > 0); if (count <= 1) return 0; - - /* FIXME: real hash calculation here */ - c = name[namelen - 1]; - if (c == 0) - CWARN("looks like wrong len is passed\n"); - c = c % count; + switch (hashtype) { + case MEA_MAGIC_LAST_CHAR: + c = mea_last_char_hash(count, (char *)name, namelen); + break; + case MEA_MAGIC_ALL_CHARS: + c = mea_all_chars_hash(count, (char *)name, namelen); + break; + case MEA_MAGIC_HASH_SEGMENT: + c = mea_hash_segment(count, (char *)name, namelen); + break; + default: + CERROR("Unknown hash type 0x%x\n", hashtype); + } + LASSERT(c < count); + return c; +} + +int mea_name2idx(struct lmv_stripe_md *mea, const char *name, int namelen) +{ + unsigned int c; + + LASSERT(mea && mea->mea_count); + + c = raw_name2idx(mea->mea_magic, mea->mea_count, name, namelen); + + LASSERT(c < mea->mea_count); return c; }