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
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
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 (c) 2007, 2010, Oracle and/or its affiliates. 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.
38 # define EXPORT_SYMTAB
40 #define DEBUG_SUBSYSTEM S_LMV
42 #include <linux/slab.h>
43 #include <linux/module.h>
44 #include <linux/init.h>
45 #include <linux/slab.h>
46 #include <linux/pagemap.h>
47 #include <asm/div64.h>
48 #include <linux/seq_file.h>
50 #include <liblustre.h>
53 #include <obd_support.h>
54 #include <lustre/lustre_idl.h>
55 #include <lustre_lib.h>
56 #include <lustre_net.h>
57 #include <lustre_dlm.h>
58 #include <obd_class.h>
59 #include <lprocfs_status.h>
60 #include "lmv_internal.h"
62 extern cfs_mem_cache_t *lmv_object_cache;
63 extern cfs_atomic_t lmv_object_count;
65 static CFS_LIST_HEAD(obj_list);
66 static cfs_spinlock_t obj_list_lock = CFS_SPIN_LOCK_UNLOCKED;
68 struct lmv_object *lmv_object_alloc(struct obd_device *obd,
69 const struct lu_fid *fid,
70 struct lmv_stripe_md *mea)
72 struct lmv_obd *lmv = &obd->u.lmv;
73 unsigned int obj_size;
74 struct lmv_object *obj;
77 LASSERT(mea->mea_magic == MEA_MAGIC_LAST_CHAR
78 || mea->mea_magic == MEA_MAGIC_ALL_CHARS
79 || mea->mea_magic == MEA_MAGIC_HASH_SEGMENT);
81 OBD_SLAB_ALLOC_PTR(obj, lmv_object_cache);
85 cfs_atomic_inc(&lmv_object_count);
90 obj->lo_hashtype = mea->mea_magic;
92 cfs_init_mutex(&obj->lo_guard);
93 cfs_atomic_set(&obj->lo_count, 0);
94 obj->lo_objcount = mea->mea_count;
96 obj_size = sizeof(struct lmv_stripe) *
97 lmv->desc.ld_tgt_count;
99 OBD_ALLOC(obj->lo_stripes, obj_size);
100 if (!obj->lo_stripes)
103 memset(obj->lo_stripes, 0, obj_size);
105 CDEBUG(D_INODE, "Allocate object for "DFID"\n",
107 for (i = 0; i < mea->mea_count; i++) {
110 CDEBUG(D_INODE, "Process subobject "DFID"\n",
111 PFID(&mea->mea_ids[i]));
112 obj->lo_stripes[i].ls_fid = mea->mea_ids[i];
113 LASSERT(fid_is_sane(&obj->lo_stripes[i].ls_fid));
116 * Cache slave mds number to use it in all cases it is needed
117 * instead of constant lookup.
119 rc = lmv_fld_lookup(lmv, &obj->lo_stripes[i].ls_fid,
120 &obj->lo_stripes[i].ls_mds);
127 OBD_FREE(obj, sizeof(*obj));
131 void lmv_object_free(struct lmv_object *obj)
133 struct lmv_obd *lmv = &obj->lo_obd->u.lmv;
134 unsigned int obj_size;
136 LASSERT(!cfs_atomic_read(&obj->lo_count));
138 obj_size = sizeof(struct lmv_stripe) *
139 lmv->desc.ld_tgt_count;
141 OBD_FREE(obj->lo_stripes, obj_size);
142 OBD_SLAB_FREE(obj, lmv_object_cache, sizeof(*obj));
143 cfs_atomic_dec(&lmv_object_count);
146 static void __lmv_object_add(struct lmv_object *obj)
148 cfs_atomic_inc(&obj->lo_count);
149 cfs_list_add(&obj->lo_list, &obj_list);
152 void lmv_object_add(struct lmv_object *obj)
154 cfs_spin_lock(&obj_list_lock);
155 __lmv_object_add(obj);
156 cfs_spin_unlock(&obj_list_lock);
159 static void __lmv_object_del(struct lmv_object *obj)
161 cfs_list_del(&obj->lo_list);
162 lmv_object_free(obj);
165 void lmv_object_del(struct lmv_object *obj)
167 cfs_spin_lock(&obj_list_lock);
168 __lmv_object_del(obj);
169 cfs_spin_unlock(&obj_list_lock);
172 static struct lmv_object *__lmv_object_get(struct lmv_object *obj)
174 LASSERT(obj != NULL);
175 cfs_atomic_inc(&obj->lo_count);
179 struct lmv_object *lmv_object_get(struct lmv_object *obj)
181 cfs_spin_lock(&obj_list_lock);
182 __lmv_object_get(obj);
183 cfs_spin_unlock(&obj_list_lock);
187 static void __lmv_object_put(struct lmv_object *obj)
191 if (cfs_atomic_dec_and_test(&obj->lo_count)) {
192 CDEBUG(D_INODE, "Last reference to "DFID" - "
193 "destroying\n", PFID(&obj->lo_fid));
194 __lmv_object_del(obj);
198 void lmv_object_put(struct lmv_object *obj)
200 cfs_spin_lock(&obj_list_lock);
201 __lmv_object_put(obj);
202 cfs_spin_unlock(&obj_list_lock);
205 void lmv_object_put_unlock(struct lmv_object *obj)
207 lmv_object_unlock(obj);
211 static struct lmv_object *__lmv_object_find(struct obd_device *obd, const struct lu_fid *fid)
213 struct lmv_object *obj;
216 cfs_list_for_each(cur, &obj_list) {
217 obj = cfs_list_entry(cur, struct lmv_object, lo_list);
220 * Check if object is in destroying phase. If so - skip
223 if (obj->lo_state & O_FREEING)
227 * We should make sure, that we have found object belong to
228 * passed obd. It is possible that, object manager will have two
229 * objects with the same fid belong to different obds, if client
230 * and mds runs on the same host. May be it is good idea to have
231 * objects list associated with obd.
233 if (obj->lo_obd != obd)
237 * Check if this is what we're looking for.
239 if (lu_fid_eq(&obj->lo_fid, fid))
240 return __lmv_object_get(obj);
246 struct lmv_object *lmv_object_find(struct obd_device *obd,
247 const struct lu_fid *fid)
249 struct lmv_object *obj;
252 cfs_spin_lock(&obj_list_lock);
253 obj = __lmv_object_find(obd, fid);
254 cfs_spin_unlock(&obj_list_lock);
259 struct lmv_object *lmv_object_find_lock(struct obd_device *obd,
260 const struct lu_fid *fid)
262 struct lmv_object *obj;
265 obj = lmv_object_find(obd, fid);
267 lmv_object_lock(obj);
272 static struct lmv_object *__lmv_object_create(struct obd_device *obd,
273 const struct lu_fid *fid,
274 struct lmv_stripe_md *mea)
276 struct lmv_object *new;
277 struct lmv_object *obj;
280 obj = lmv_object_find(obd, fid);
284 new = lmv_object_alloc(obd, fid, mea);
289 * Check if someone created it already while we were dealing with
292 cfs_spin_lock(&obj_list_lock);
293 obj = __lmv_object_find(obd, fid);
296 * Someone created it already - put @obj and getting out.
298 cfs_spin_unlock(&obj_list_lock);
299 lmv_object_free(new);
303 __lmv_object_add(new);
304 __lmv_object_get(new);
306 cfs_spin_unlock(&obj_list_lock);
308 CDEBUG(D_INODE, "New obj in lmv cache: "DFID"\n",
314 struct lmv_object *lmv_object_create(struct obd_export *exp,
315 const struct lu_fid *fid,
316 struct lmv_stripe_md *mea)
318 struct obd_device *obd = exp->exp_obd;
319 struct lmv_obd *lmv = &obd->u.lmv;
320 struct ptlrpc_request *req = NULL;
321 struct lmv_tgt_desc *tgt;
322 struct lmv_object *obj;
328 CDEBUG(D_INODE, "Get mea for "DFID" and create lmv obj\n",
334 struct md_op_data *op_data;
337 CDEBUG(D_INODE, "Mea isn't passed in, get it now\n");
338 mealen = lmv_get_easize(lmv);
341 * Time to update mea of parent fid.
344 valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA | OBD_MD_MEA;
346 tgt = lmv_find_target(lmv, fid);
348 GOTO(cleanup, obj = (void *)tgt);
350 OBD_ALLOC_PTR(op_data);
352 GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
354 op_data->op_fid1 = *fid;
355 op_data->op_mode = mealen;
356 op_data->op_valid = valid;
357 rc = md_getattr(tgt->ltd_exp, op_data, &req);
358 OBD_FREE_PTR(op_data);
360 CERROR("md_getattr() failed, error %d\n", rc);
361 GOTO(cleanup, obj = ERR_PTR(rc));
364 rc = md_get_lustre_md(exp, req, NULL, exp, &md);
366 CERROR("md_get_lustre_md() failed, error %d\n", rc);
367 GOTO(cleanup, obj = ERR_PTR(rc));
371 GOTO(cleanup, obj = ERR_PTR(-ENODATA));
377 * Got mea, now create obj for it.
379 obj = __lmv_object_create(obd, fid, mea);
381 CERROR("Can't create new object "DFID"\n",
383 GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
387 obd_free_memmd(exp, (void *)&md.mea);
392 ptlrpc_req_finished(req);
396 int lmv_object_delete(struct obd_export *exp, const struct lu_fid *fid)
398 struct obd_device *obd = exp->exp_obd;
399 struct lmv_object *obj;
403 cfs_spin_lock(&obj_list_lock);
404 obj = __lmv_object_find(obd, fid);
406 obj->lo_state |= O_FREEING;
407 __lmv_object_put(obj);
408 __lmv_object_put(obj);
411 cfs_spin_unlock(&obj_list_lock);
415 int lmv_object_setup(struct obd_device *obd)
418 LASSERT(obd != NULL);
420 CDEBUG(D_INFO, "LMV object manager setup (%s)\n",
426 void lmv_object_cleanup(struct obd_device *obd)
430 struct lmv_object *obj;
433 CDEBUG(D_INFO, "LMV object manager cleanup (%s)\n",
436 cfs_spin_lock(&obj_list_lock);
437 cfs_list_for_each_safe(cur, tmp, &obj_list) {
438 obj = cfs_list_entry(cur, struct lmv_object, lo_list);
440 if (obj->lo_obd != obd)
443 obj->lo_state |= O_FREEING;
444 if (cfs_atomic_read(&obj->lo_count) > 1) {
445 CERROR("Object "DFID" has count (%d)\n",
447 cfs_atomic_read(&obj->lo_count));
449 __lmv_object_put(obj);
451 cfs_spin_unlock(&obj_list_lock);