4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, Whamcloud, Inc.
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_mutex_init(&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_LARGE(obj->lo_stripes, obj_size);
100 if (!obj->lo_stripes)
103 CDEBUG(D_INODE, "Allocate object for "DFID"\n",
105 for (i = 0; i < mea->mea_count; i++) {
108 CDEBUG(D_INODE, "Process subobject "DFID"\n",
109 PFID(&mea->mea_ids[i]));
110 obj->lo_stripes[i].ls_fid = mea->mea_ids[i];
111 LASSERT(fid_is_sane(&obj->lo_stripes[i].ls_fid));
114 * Cache slave mds number to use it in all cases it is needed
115 * instead of constant lookup.
117 rc = lmv_fld_lookup(lmv, &obj->lo_stripes[i].ls_fid,
118 &obj->lo_stripes[i].ls_mds);
125 OBD_FREE(obj, sizeof(*obj));
129 void lmv_object_free(struct lmv_object *obj)
131 struct lmv_obd *lmv = &obj->lo_obd->u.lmv;
132 unsigned int obj_size;
134 LASSERT(!cfs_atomic_read(&obj->lo_count));
136 obj_size = sizeof(struct lmv_stripe) *
137 lmv->desc.ld_tgt_count;
139 OBD_FREE_LARGE(obj->lo_stripes, obj_size);
140 OBD_SLAB_FREE(obj, lmv_object_cache, sizeof(*obj));
141 cfs_atomic_dec(&lmv_object_count);
144 static void __lmv_object_add(struct lmv_object *obj)
146 cfs_atomic_inc(&obj->lo_count);
147 cfs_list_add(&obj->lo_list, &obj_list);
150 void lmv_object_add(struct lmv_object *obj)
152 cfs_spin_lock(&obj_list_lock);
153 __lmv_object_add(obj);
154 cfs_spin_unlock(&obj_list_lock);
157 static void __lmv_object_del(struct lmv_object *obj)
159 cfs_list_del(&obj->lo_list);
160 lmv_object_free(obj);
163 void lmv_object_del(struct lmv_object *obj)
165 cfs_spin_lock(&obj_list_lock);
166 __lmv_object_del(obj);
167 cfs_spin_unlock(&obj_list_lock);
170 static struct lmv_object *__lmv_object_get(struct lmv_object *obj)
172 LASSERT(obj != NULL);
173 cfs_atomic_inc(&obj->lo_count);
177 struct lmv_object *lmv_object_get(struct lmv_object *obj)
179 cfs_spin_lock(&obj_list_lock);
180 __lmv_object_get(obj);
181 cfs_spin_unlock(&obj_list_lock);
185 static void __lmv_object_put(struct lmv_object *obj)
189 if (cfs_atomic_dec_and_test(&obj->lo_count)) {
190 CDEBUG(D_INODE, "Last reference to "DFID" - "
191 "destroying\n", PFID(&obj->lo_fid));
192 __lmv_object_del(obj);
196 void lmv_object_put(struct lmv_object *obj)
198 cfs_spin_lock(&obj_list_lock);
199 __lmv_object_put(obj);
200 cfs_spin_unlock(&obj_list_lock);
203 void lmv_object_put_unlock(struct lmv_object *obj)
205 lmv_object_unlock(obj);
209 static struct lmv_object *__lmv_object_find(struct obd_device *obd, const struct lu_fid *fid)
211 struct lmv_object *obj;
214 cfs_list_for_each(cur, &obj_list) {
215 obj = cfs_list_entry(cur, struct lmv_object, lo_list);
218 * Check if object is in destroying phase. If so - skip
221 if (obj->lo_state & O_FREEING)
225 * We should make sure, that we have found object belong to
226 * passed obd. It is possible that, object manager will have two
227 * objects with the same fid belong to different obds, if client
228 * and mds runs on the same host. May be it is good idea to have
229 * objects list associated with obd.
231 if (obj->lo_obd != obd)
235 * Check if this is what we're looking for.
237 if (lu_fid_eq(&obj->lo_fid, fid))
238 return __lmv_object_get(obj);
244 struct lmv_object *lmv_object_find(struct obd_device *obd,
245 const struct lu_fid *fid)
247 struct lmv_obd *lmv = &obd->u.lmv;
248 struct lmv_object *obj = NULL;
251 /* For single MDT case, lmv_object list is always empty. */
252 if (lmv->desc.ld_tgt_count > 1) {
253 cfs_spin_lock(&obj_list_lock);
254 obj = __lmv_object_find(obd, fid);
255 cfs_spin_unlock(&obj_list_lock);
261 struct lmv_object *lmv_object_find_lock(struct obd_device *obd,
262 const struct lu_fid *fid)
264 struct lmv_object *obj;
267 obj = lmv_object_find(obd, fid);
269 lmv_object_lock(obj);
274 static struct lmv_object *__lmv_object_create(struct obd_device *obd,
275 const struct lu_fid *fid,
276 struct lmv_stripe_md *mea)
278 struct lmv_object *new;
279 struct lmv_object *obj;
282 obj = lmv_object_find(obd, fid);
286 new = lmv_object_alloc(obd, fid, mea);
291 * Check if someone created it already while we were dealing with
294 cfs_spin_lock(&obj_list_lock);
295 obj = __lmv_object_find(obd, fid);
298 * Someone created it already - put @obj and getting out.
300 cfs_spin_unlock(&obj_list_lock);
301 lmv_object_free(new);
305 __lmv_object_add(new);
306 __lmv_object_get(new);
308 cfs_spin_unlock(&obj_list_lock);
310 CDEBUG(D_INODE, "New obj in lmv cache: "DFID"\n",
316 struct lmv_object *lmv_object_create(struct obd_export *exp,
317 const struct lu_fid *fid,
318 struct lmv_stripe_md *mea)
320 struct obd_device *obd = exp->exp_obd;
321 struct lmv_obd *lmv = &obd->u.lmv;
322 struct ptlrpc_request *req = NULL;
323 struct lmv_tgt_desc *tgt;
324 struct lmv_object *obj;
330 CDEBUG(D_INODE, "Get mea for "DFID" and create lmv obj\n",
336 struct md_op_data *op_data;
339 CDEBUG(D_INODE, "Mea isn't passed in, get it now\n");
340 mealen = lmv_get_easize(lmv);
343 * Time to update mea of parent fid.
346 valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA | OBD_MD_MEA;
348 tgt = lmv_find_target(lmv, fid);
350 GOTO(cleanup, obj = (void *)tgt);
352 OBD_ALLOC_PTR(op_data);
354 GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
356 op_data->op_fid1 = *fid;
357 op_data->op_mode = mealen;
358 op_data->op_valid = valid;
359 rc = md_getattr(tgt->ltd_exp, op_data, &req);
360 OBD_FREE_PTR(op_data);
362 CERROR("md_getattr() failed, error %d\n", rc);
363 GOTO(cleanup, obj = ERR_PTR(rc));
366 rc = md_get_lustre_md(exp, req, NULL, exp, &md);
368 CERROR("md_get_lustre_md() failed, error %d\n", rc);
369 GOTO(cleanup, obj = ERR_PTR(rc));
373 GOTO(cleanup, obj = ERR_PTR(-ENODATA));
379 * Got mea, now create obj for it.
381 obj = __lmv_object_create(obd, fid, mea);
383 CERROR("Can't create new object "DFID"\n",
385 GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
389 obd_free_memmd(exp, (void *)&md.mea);
394 ptlrpc_req_finished(req);
398 int lmv_object_delete(struct obd_export *exp, const struct lu_fid *fid)
400 struct obd_device *obd = exp->exp_obd;
401 struct lmv_object *obj;
405 cfs_spin_lock(&obj_list_lock);
406 obj = __lmv_object_find(obd, fid);
408 obj->lo_state |= O_FREEING;
409 __lmv_object_put(obj);
410 __lmv_object_put(obj);
413 cfs_spin_unlock(&obj_list_lock);
417 int lmv_object_setup(struct obd_device *obd)
420 LASSERT(obd != NULL);
422 CDEBUG(D_INFO, "LMV object manager setup (%s)\n",
428 void lmv_object_cleanup(struct obd_device *obd)
432 struct lmv_object *obj;
435 CDEBUG(D_INFO, "LMV object manager cleanup (%s)\n",
438 cfs_spin_lock(&obj_list_lock);
439 cfs_list_for_each_safe(cur, tmp, &obj_list) {
440 obj = cfs_list_entry(cur, struct lmv_object, lo_list);
442 if (obj->lo_obd != obd)
445 obj->lo_state |= O_FREEING;
446 if (cfs_atomic_read(&obj->lo_count) > 1) {
447 CERROR("Object "DFID" has count (%d)\n",
449 cfs_atomic_read(&obj->lo_count));
451 __lmv_object_put(obj);
453 cfs_spin_unlock(&obj_list_lock);