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.
32 * Copyright (c) 2011, Whamcloud, Inc.
35 * This file is part of Lustre, http://www.lustre.org/
36 * Lustre is a trademark of Sun Microsystems, Inc.
40 # define EXPORT_SYMTAB
42 #define DEBUG_SUBSYSTEM S_LMV
44 #include <linux/slab.h>
45 #include <linux/module.h>
46 #include <linux/init.h>
47 #include <linux/slab.h>
48 #include <linux/pagemap.h>
49 #include <asm/div64.h>
50 #include <linux/seq_file.h>
52 #include <liblustre.h>
55 #include <obd_support.h>
56 #include <lustre/lustre_idl.h>
57 #include <lustre_lib.h>
58 #include <lustre_net.h>
59 #include <lustre_dlm.h>
60 #include <obd_class.h>
61 #include <lprocfs_status.h>
62 #include "lmv_internal.h"
64 extern cfs_mem_cache_t *lmv_object_cache;
65 extern cfs_atomic_t lmv_object_count;
67 static CFS_LIST_HEAD(obj_list);
68 static cfs_spinlock_t obj_list_lock = CFS_SPIN_LOCK_UNLOCKED;
70 struct lmv_object *lmv_object_alloc(struct obd_device *obd,
71 const struct lu_fid *fid,
72 struct lmv_stripe_md *mea)
74 struct lmv_obd *lmv = &obd->u.lmv;
75 unsigned int obj_size;
76 struct lmv_object *obj;
79 LASSERT(mea->mea_magic == MEA_MAGIC_LAST_CHAR
80 || mea->mea_magic == MEA_MAGIC_ALL_CHARS
81 || mea->mea_magic == MEA_MAGIC_HASH_SEGMENT);
83 OBD_SLAB_ALLOC_PTR(obj, lmv_object_cache);
87 cfs_atomic_inc(&lmv_object_count);
92 obj->lo_hashtype = mea->mea_magic;
94 cfs_init_mutex(&obj->lo_guard);
95 cfs_atomic_set(&obj->lo_count, 0);
96 obj->lo_objcount = mea->mea_count;
98 obj_size = sizeof(struct lmv_stripe) *
99 lmv->desc.ld_tgt_count;
101 OBD_ALLOC_LARGE(obj->lo_stripes, obj_size);
102 if (!obj->lo_stripes)
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_LARGE(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_obd *lmv = &obd->u.lmv;
250 struct lmv_object *obj = NULL;
253 /* For single MDT case, lmv_object list is always empty. */
254 if (lmv->desc.ld_tgt_count > 1) {
255 cfs_spin_lock(&obj_list_lock);
256 obj = __lmv_object_find(obd, fid);
257 cfs_spin_unlock(&obj_list_lock);
263 struct lmv_object *lmv_object_find_lock(struct obd_device *obd,
264 const struct lu_fid *fid)
266 struct lmv_object *obj;
269 obj = lmv_object_find(obd, fid);
271 lmv_object_lock(obj);
276 static struct lmv_object *__lmv_object_create(struct obd_device *obd,
277 const struct lu_fid *fid,
278 struct lmv_stripe_md *mea)
280 struct lmv_object *new;
281 struct lmv_object *obj;
284 obj = lmv_object_find(obd, fid);
288 new = lmv_object_alloc(obd, fid, mea);
293 * Check if someone created it already while we were dealing with
296 cfs_spin_lock(&obj_list_lock);
297 obj = __lmv_object_find(obd, fid);
300 * Someone created it already - put @obj and getting out.
302 cfs_spin_unlock(&obj_list_lock);
303 lmv_object_free(new);
307 __lmv_object_add(new);
308 __lmv_object_get(new);
310 cfs_spin_unlock(&obj_list_lock);
312 CDEBUG(D_INODE, "New obj in lmv cache: "DFID"\n",
318 struct lmv_object *lmv_object_create(struct obd_export *exp,
319 const struct lu_fid *fid,
320 struct lmv_stripe_md *mea)
322 struct obd_device *obd = exp->exp_obd;
323 struct lmv_obd *lmv = &obd->u.lmv;
324 struct ptlrpc_request *req = NULL;
325 struct lmv_tgt_desc *tgt;
326 struct lmv_object *obj;
332 CDEBUG(D_INODE, "Get mea for "DFID" and create lmv obj\n",
338 struct md_op_data *op_data;
341 CDEBUG(D_INODE, "Mea isn't passed in, get it now\n");
342 mealen = lmv_get_easize(lmv);
345 * Time to update mea of parent fid.
348 valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA | OBD_MD_MEA;
350 tgt = lmv_find_target(lmv, fid);
352 GOTO(cleanup, obj = (void *)tgt);
354 OBD_ALLOC_PTR(op_data);
356 GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
358 op_data->op_fid1 = *fid;
359 op_data->op_mode = mealen;
360 op_data->op_valid = valid;
361 rc = md_getattr(tgt->ltd_exp, op_data, &req);
362 OBD_FREE_PTR(op_data);
364 CERROR("md_getattr() failed, error %d\n", rc);
365 GOTO(cleanup, obj = ERR_PTR(rc));
368 rc = md_get_lustre_md(exp, req, NULL, exp, &md);
370 CERROR("md_get_lustre_md() failed, error %d\n", rc);
371 GOTO(cleanup, obj = ERR_PTR(rc));
375 GOTO(cleanup, obj = ERR_PTR(-ENODATA));
381 * Got mea, now create obj for it.
383 obj = __lmv_object_create(obd, fid, mea);
385 CERROR("Can't create new object "DFID"\n",
387 GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
391 obd_free_memmd(exp, (void *)&md.mea);
396 ptlrpc_req_finished(req);
400 int lmv_object_delete(struct obd_export *exp, const struct lu_fid *fid)
402 struct obd_device *obd = exp->exp_obd;
403 struct lmv_object *obj;
407 cfs_spin_lock(&obj_list_lock);
408 obj = __lmv_object_find(obd, fid);
410 obj->lo_state |= O_FREEING;
411 __lmv_object_put(obj);
412 __lmv_object_put(obj);
415 cfs_spin_unlock(&obj_list_lock);
419 int lmv_object_setup(struct obd_device *obd)
422 LASSERT(obd != NULL);
424 CDEBUG(D_INFO, "LMV object manager setup (%s)\n",
430 void lmv_object_cleanup(struct obd_device *obd)
434 struct lmv_object *obj;
437 CDEBUG(D_INFO, "LMV object manager cleanup (%s)\n",
440 cfs_spin_lock(&obj_list_lock);
441 cfs_list_for_each_safe(cur, tmp, &obj_list) {
442 obj = cfs_list_entry(cur, struct lmv_object, lo_list);
444 if (obj->lo_obd != obd)
447 obj->lo_state |= O_FREEING;
448 if (cfs_atomic_read(&obj->lo_count) > 1) {
449 CERROR("Object "DFID" has count (%d)\n",
451 cfs_atomic_read(&obj->lo_count));
453 __lmv_object_put(obj);
455 cfs_spin_unlock(&obj_list_lock);