Whamcloud - gitweb
15f15d895ce2e3059efbde90a34a14e4ae32a3f1
[fs/lustre-release.git] / lustre / obdclass / mea.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2002, 2003 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #define DEBUG_SUBSYSTEM S_CLASS
23 #include <obd_class.h>
24 #ifdef __KERNEL__
25 #include <linux/kmod.h>   /* for request_module() */
26 #include <linux/module.h>
27 #include <linux/random.h>
28 #include <linux/slab.h>
29 #include <linux/pagemap.h>
30 #else
31 #include <liblustre.h>
32 #include <obd.h>
33 #endif
34 #include <lprocfs_status.h>
35 #include <lustre/lustre_idl.h>
36
37 #ifdef __KERNEL__
38 #include <linux/jbd.h>
39 #ifdef HAVE_SERVER_SUPPORT
40 /* LDISKFS_SB() */
41 #include <linux/ldiskfs_fs.h>
42 #endif
43 #endif
44 static int mea_last_char_hash(int count, char *name, int namelen)
45 {
46         unsigned int c;
47
48         c = name[namelen - 1];
49         if (c == 0)
50                 CWARN("looks like wrong len is passed\n");
51         c = c % count;
52         return c;
53 }
54
55 static int mea_all_chars_hash(int count, char *name, int namelen)
56 {
57         unsigned int c = 0;
58
59         while (--namelen >= 0)
60                 c += name[namelen];
61         c = c % count;
62         return c;
63 }
64
65 #ifdef __KERNEL__
66 /* This hash calculate method must be same as the lvar hash method */
67
68 #define LVAR_HASH_SANDWICH  (0)
69 #define LVAR_HASH_TEA       (1)
70 #define LVAR_HASH_R5        (0)
71 #define LVAR_HASH_PREFIX    (0)
72
73 static __u32 hash_build0(const char *name, int namelen)
74 {
75         __u32 result;
76
77         if (namelen == 0)
78                 return 0;
79         if (strncmp(name, ".", 1) == 0 && namelen == 1)
80                 return 1;
81         if (strncmp(name, "..", 2) == 0 && namelen == 2)
82                 return 2;
83
84         if (LVAR_HASH_PREFIX) {
85                 result = 0;
86                 strncpy((void *)&result,
87                         name, min(namelen, (int)sizeof result));
88         } else {
89                 struct ldiskfs_dx_hash_info hinfo;
90
91                 if (LVAR_HASH_TEA)
92                         hinfo.hash_version = LDISKFS_DX_HASH_TEA;
93                 else
94                         hinfo.hash_version = LDISKFS_DX_HASH_R5;
95                 hinfo.seed = 0;
96                 ldiskfsfs_dirhash(name, namelen, &hinfo);
97                 result = hinfo.hash;
98                 if (LVAR_HASH_SANDWICH) {
99                         __u32 result2;
100
101                         hinfo.hash_version = LDISKFS_DX_HASH_TEA;
102                         hinfo.seed = 0;
103                         ldiskfsfs_dirhash(name, namelen, &hinfo);
104                         result2 = hinfo.hash;
105                         result = (0xfc000000 & result2) | (0x03ffffff & result);
106                 }
107         }
108
109         return result;
110 }
111
112 enum {
113         HASH_GRAY_AREA = 1024
114 };
115
116 static __u32 hash_build(const char *name, int namelen)
117 {
118         __u32 hash;
119
120         hash = (hash_build0(name, namelen) << 1) & MAX_HASH_SIZE;
121         if (hash > MAX_HASH_SIZE - HASH_GRAY_AREA)
122                 hash &= HASH_GRAY_AREA - 1;
123         return hash;
124 }
125
126 static int mea_hash_segment(int count, const char *name, int namelen)
127 {
128         __u32 hash;
129
130         LASSERT(IS_PO2(MAX_HASH_SIZE + 1));
131
132         hash = hash_build(name, namelen) / (MAX_HASH_SIZE / count);
133         LASSERTF(hash < count, "hash %x count %d \n", hash, count);
134
135         return hash;
136 }
137 #else
138 static int mea_hash_segment(int count, char *name, int namelen)
139 {
140 #warning "fix for liblustre"
141         return 0;
142 }
143 #endif
144 int raw_name2idx(int hashtype, int count, const char *name, int namelen)
145 {
146         unsigned int c = 0;
147
148         LASSERT(namelen > 0);
149         if (count <= 1)
150                 return 0;
151
152         switch (hashtype) {
153                 case MEA_MAGIC_LAST_CHAR:
154                         c = mea_last_char_hash(count, (char *)name, namelen);
155                         break;
156                 case MEA_MAGIC_ALL_CHARS:
157                         c = mea_all_chars_hash(count, (char *)name, namelen);
158                         break;
159                 case MEA_MAGIC_HASH_SEGMENT:
160                         c = mea_hash_segment(count, (char *)name, namelen);
161                         break;
162                 default:
163                         CERROR("Unknown hash type 0x%x\n", hashtype);
164         }
165         
166         LASSERT(c < count);
167         return c;
168 }
169
170 int mea_name2idx(struct lmv_stripe_md *mea, const char *name, int namelen)
171 {
172         unsigned int c;
173
174         LASSERT(mea && mea->mea_count);
175
176         c = raw_name2idx(mea->mea_magic, mea->mea_count, name, namelen);
177
178         LASSERT(c < mea->mea_count);
179         return c;
180 }
181