1 /* -*- MODE: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * lustre/fld/fld_handler.c
5 * FLD (Fids Location Database)
7 * Copyright (C) 2006 Cluster File Systems, Inc.
8 * Author: Yury Umanets <umka@clusterfs.com>
10 * This file is part of the Lustre file system, http://www.lustre.org
11 * Lustre is a trademark of Cluster File Systems, Inc.
13 * You may have signed or agreed to another license before downloading
14 * this software. If so, you are bound by the terms and conditions
15 * of that agreement, and the following does not apply to you. See the
16 * LICENSE file included with this distribution for more information.
18 * If you did not agree to a different license, then this copy of Lustre
19 * is open source software; you can redistribute it and/or modify it
20 * under the terms of version 2 of the GNU General Public License as
21 * published by the Free Software Foundation.
23 * In either case, Lustre is distributed in the hope that it will be
24 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * license text for more details.
29 # define EXPORT_SYMTAB
31 #define DEBUG_SUBSYSTEM S_FLD
34 # include <libcfs/libcfs.h>
35 # include <linux/module.h>
36 # include <linux/jbd.h>
37 # include <asm/div64.h>
38 #else /* __KERNEL__ */
39 # include <liblustre.h>
40 # include <libcfs/list.h>
44 #include <obd_class.h>
45 #include <lustre_ver.h>
46 #include <obd_support.h>
47 #include <lprocfs_status.h>
49 #include <dt_object.h>
50 #include <md_object.h>
51 #include <lustre_req_layout.h>
52 #include <lustre_fld.h>
53 #include "fld_internal.h"
56 extern struct fld_cache_info *fld_cache;
58 static __u32 fld_cache_hash(__u64 seq)
64 fld_cache_insert(struct fld_cache_info *fld_cache,
67 struct fld_cache *fld;
68 struct hlist_head *bucket;
69 struct hlist_node *scan;
73 bucket = fld_cache->fld_hash + (fld_cache_hash(seq) &
74 fld_cache->fld_hash_mask);
80 INIT_HLIST_NODE(&fld->fld_list);
84 spin_lock(&fld_cache->fld_lock);
85 hlist_for_each_entry(fld, scan, bucket, fld_list) {
86 if (fld->fld_seq == seq)
87 GOTO(exit_unlock, rc = -EEXIST);
89 hlist_add_head(&fld->fld_list, bucket);
92 spin_unlock(&fld_cache->fld_lock);
94 OBD_FREE(fld, sizeof(*fld));
99 fld_cache_delete(struct fld_cache_info *fld_cache, __u64 seq)
101 struct hlist_head *bucket;
102 struct hlist_node *scan;
103 struct fld_cache *fld;
106 bucket = fld_cache->fld_hash + (fld_cache_hash(seq) &
107 fld_cache->fld_hash_mask);
109 spin_lock(&fld_cache->fld_lock);
110 hlist_for_each_entry(fld, scan, bucket, fld_list) {
111 if (fld->fld_seq == seq) {
112 hlist_del_init(&fld->fld_list);
119 spin_unlock(&fld_cache->fld_lock);
123 static struct fld_cache *
124 fld_cache_lookup(struct fld_cache_info *fld_cache, __u64 seq)
126 struct hlist_head *bucket;
127 struct hlist_node *scan;
128 struct fld_cache *fld;
131 bucket = fld_cache->fld_hash + (fld_cache_hash(seq) &
132 fld_cache->fld_hash_mask);
134 spin_lock(&fld_cache->fld_lock);
135 hlist_for_each_entry(fld, scan, bucket, fld_list) {
136 if (fld->fld_seq == seq) {
137 spin_unlock(&fld_cache->fld_lock);
141 spin_unlock(&fld_cache->fld_lock);
147 static int fld_rrb_hash(struct lu_client_fld *fld, __u64 seq)
149 if (fld->fld_count == 0)
152 return do_div(seq, fld->fld_count);
155 static int fld_dht_hash(struct lu_client_fld *fld, __u64 seq)
157 /* XXX: here should DHT hash */
158 return fld_rrb_hash(fld, seq);
161 static struct lu_fld_hash fld_hash[3] = {
164 .fh_func = fld_dht_hash
167 .fh_name = "Round Robin",
168 .fh_func = fld_rrb_hash
175 static struct obd_export *
176 fld_client_get_export(struct lu_client_fld *fld, __u64 seq)
178 struct obd_export *fld_exp;
182 LASSERT(fld->fld_hash != NULL);
183 hash = fld->fld_hash->fh_func(fld, seq);
185 spin_lock(&fld->fld_lock);
186 list_for_each_entry(fld_exp,
187 &fld->fld_exports, exp_fld_chain) {
189 spin_unlock(&fld->fld_lock);
194 spin_unlock(&fld->fld_lock);
198 /* add export to FLD. This is usually done by CMM and LMV as they are main users
200 int fld_client_add_export(struct lu_client_fld *fld,
201 struct obd_export *exp)
203 struct obd_export *fld_exp;
206 LASSERT(exp != NULL);
208 CDEBUG(D_INFO|D_WARNING, "adding export %s\n",
209 exp->exp_client_uuid.uuid);
211 spin_lock(&fld->fld_lock);
212 list_for_each_entry(fld_exp, &fld->fld_exports, exp_fld_chain) {
213 if (obd_uuid_equals(&fld_exp->exp_client_uuid,
214 &exp->exp_client_uuid))
216 spin_unlock(&fld->fld_lock);
221 fld_exp = class_export_get(exp);
222 list_add_tail(&fld_exp->exp_fld_chain,
226 spin_unlock(&fld->fld_lock);
230 EXPORT_SYMBOL(fld_client_add_export);
232 /* remove export from FLD */
233 int fld_client_del_export(struct lu_client_fld *fld,
234 struct obd_export *exp)
236 struct obd_export *fld_exp;
237 struct obd_export *tmp;
240 spin_lock(&fld->fld_lock);
241 list_for_each_entry_safe(fld_exp, tmp, &fld->fld_exports, exp_fld_chain) {
242 if (obd_uuid_equals(&fld_exp->exp_client_uuid,
243 &exp->exp_client_uuid))
246 list_del(&fld_exp->exp_fld_chain);
247 class_export_get(fld_exp);
249 spin_unlock(&fld->fld_lock);
253 spin_unlock(&fld->fld_lock);
256 EXPORT_SYMBOL(fld_client_del_export);
258 int fld_client_init(struct lu_client_fld *fld, int hash)
263 LASSERT(fld != NULL);
265 if (hash < 0 || hash >= LUSTRE_CLI_FLD_HASH_LAST) {
266 CERROR("wrong hash function 0x%x\n", hash);
270 INIT_LIST_HEAD(&fld->fld_exports);
271 spin_lock_init(&fld->fld_lock);
272 fld->fld_hash = &fld_hash[hash];
275 CDEBUG(D_INFO|D_WARNING, "Client FLD initialized, using \"%s\" hash\n",
276 fld->fld_hash->fh_name);
279 EXPORT_SYMBOL(fld_client_init);
281 void fld_client_fini(struct lu_client_fld *fld)
283 struct obd_export *fld_exp;
284 struct obd_export *tmp;
287 spin_lock(&fld->fld_lock);
288 list_for_each_entry_safe(fld_exp, tmp,
289 &fld->fld_exports, exp_fld_chain) {
291 list_del(&fld_exp->exp_fld_chain);
292 class_export_get(fld_exp);
294 spin_unlock(&fld->fld_lock);
295 CDEBUG(D_INFO|D_WARNING, "Client FLD finalized\n");
298 EXPORT_SYMBOL(fld_client_fini);
301 fld_client_rpc(struct obd_export *exp,
302 struct md_fld *mf, __u32 fld_op)
304 int size[2] = {sizeof(__u32), sizeof(struct md_fld)}, rc;
305 int mf_size = sizeof(struct md_fld);
306 struct ptlrpc_request *req;
311 LASSERT(exp != NULL);
313 req = ptlrpc_prep_req(class_exp2cliimp(exp),
314 LUSTRE_MDS_VERSION, FLD_QUERY,
319 op = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*op));
322 pmf = lustre_msg_buf(req->rq_reqmsg, 1, sizeof (*pmf));
323 memcpy(pmf, mf, sizeof(*mf));
325 req->rq_replen = lustre_msg_size(1, &mf_size);
326 req->rq_request_portal = MDS_FLD_PORTAL;
328 rc = ptlrpc_queue_wait(req);
332 pmf = lustre_swab_repbuf(req, 0, sizeof(*pmf),
336 ptlrpc_req_finished(req);
341 fld_client_create(struct lu_client_fld *fld,
342 __u64 seq, mdsno_t mds)
344 struct obd_export *fld_exp;
345 struct md_fld md_fld;
349 fld_exp = fld_client_get_export(fld, seq);
355 rc = fld_client_rpc(fld_exp, &md_fld, FLD_CREATE);
359 rc = fld_cache_insert(fld_cache, seq, mds);
364 EXPORT_SYMBOL(fld_client_create);
367 fld_client_delete(struct lu_client_fld *fld,
370 struct obd_export *fld_exp;
371 struct md_fld md_fld;
375 fld_cache_delete(fld_cache, seq);
378 fld_exp = fld_client_get_export(fld, seq);
385 rc = fld_client_rpc(fld_exp, &md_fld, FLD_DELETE);
388 EXPORT_SYMBOL(fld_client_delete);
391 fld_client_get(struct lu_client_fld *fld,
392 __u64 seq, mdsno_t *mds)
394 struct obd_export *fld_exp;
395 struct md_fld md_fld;
399 fld_exp = fld_client_get_export(fld, seq);
404 rc = fld_client_rpc(fld_exp,
405 &md_fld, FLD_LOOKUP);
407 *mds = md_fld.mf_mds;
412 /* lookup fid in the namespace of pfid according to the name */
414 fld_client_lookup(struct lu_client_fld *fld,
415 __u64 seq, mdsno_t *mds)
418 struct fld_cache *fld_entry;
424 /* lookup it in the cache */
425 fld_entry = fld_cache_lookup(fld_cache, seq);
426 if (fld_entry != NULL) {
427 *mds = fld_entry->fld_mds;
432 /* can not find it in the cache */
433 rc = fld_client_get(fld, seq, mds);
439 rc = fld_cache_insert(fld_cache, seq, *mds);
444 EXPORT_SYMBOL(fld_client_lookup);