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_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_object *obj;
250 cfs_spin_lock(&obj_list_lock);
251 obj = __lmv_object_find(obd, fid);
252 cfs_spin_unlock(&obj_list_lock);
257 struct lmv_object *lmv_object_find_lock(struct obd_device *obd,
258 const struct lu_fid *fid)
260 struct lmv_object *obj;
263 obj = lmv_object_find(obd, fid);
265 lmv_object_lock(obj);
270 static struct lmv_object *__lmv_object_create(struct obd_device *obd,
271 const struct lu_fid *fid,
272 struct lmv_stripe_md *mea)
274 struct lmv_object *new;
275 struct lmv_object *obj;
278 obj = lmv_object_find(obd, fid);
282 new = lmv_object_alloc(obd, fid, mea);
287 * Check if someone created it already while we were dealing with
290 cfs_spin_lock(&obj_list_lock);
291 obj = __lmv_object_find(obd, fid);
294 * Someone created it already - put @obj and getting out.
296 cfs_spin_unlock(&obj_list_lock);
297 lmv_object_free(new);
301 __lmv_object_add(new);
302 __lmv_object_get(new);
304 cfs_spin_unlock(&obj_list_lock);
306 CDEBUG(D_INODE, "New obj in lmv cache: "DFID"\n",
312 struct lmv_object *lmv_object_create(struct obd_export *exp,
313 const struct lu_fid *fid,
314 struct lmv_stripe_md *mea)
316 struct obd_device *obd = exp->exp_obd;
317 struct lmv_obd *lmv = &obd->u.lmv;
318 struct ptlrpc_request *req = NULL;
319 struct lmv_tgt_desc *tgt;
320 struct lmv_object *obj;
326 CDEBUG(D_INODE, "Get mea for "DFID" and create lmv obj\n",
332 struct md_op_data *op_data;
335 CDEBUG(D_INODE, "Mea isn't passed in, get it now\n");
336 mealen = lmv_get_easize(lmv);
339 * Time to update mea of parent fid.
342 valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA | OBD_MD_MEA;
344 tgt = lmv_find_target(lmv, fid);
346 GOTO(cleanup, obj = (void *)tgt);
348 OBD_ALLOC_PTR(op_data);
350 GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
352 op_data->op_fid1 = *fid;
353 op_data->op_mode = mealen;
354 op_data->op_valid = valid;
355 rc = md_getattr(tgt->ltd_exp, op_data, &req);
356 OBD_FREE_PTR(op_data);
358 CERROR("md_getattr() failed, error %d\n", rc);
359 GOTO(cleanup, obj = ERR_PTR(rc));
362 rc = md_get_lustre_md(exp, req, NULL, exp, &md);
364 CERROR("md_get_lustre_md() failed, error %d\n", rc);
365 GOTO(cleanup, obj = ERR_PTR(rc));
369 GOTO(cleanup, obj = ERR_PTR(-ENODATA));
375 * Got mea, now create obj for it.
377 obj = __lmv_object_create(obd, fid, mea);
379 CERROR("Can't create new object "DFID"\n",
381 GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
385 obd_free_memmd(exp, (void *)&md.mea);
390 ptlrpc_req_finished(req);
394 int lmv_object_delete(struct obd_export *exp, const struct lu_fid *fid)
396 struct obd_device *obd = exp->exp_obd;
397 struct lmv_object *obj;
401 cfs_spin_lock(&obj_list_lock);
402 obj = __lmv_object_find(obd, fid);
404 obj->lo_state |= O_FREEING;
405 __lmv_object_put(obj);
406 __lmv_object_put(obj);
409 cfs_spin_unlock(&obj_list_lock);
413 int lmv_object_setup(struct obd_device *obd)
416 LASSERT(obd != NULL);
418 CDEBUG(D_INFO, "LMV object manager setup (%s)\n",
424 void lmv_object_cleanup(struct obd_device *obd)
428 struct lmv_object *obj;
431 CDEBUG(D_INFO, "LMV object manager cleanup (%s)\n",
434 cfs_spin_lock(&obj_list_lock);
435 cfs_list_for_each_safe(cur, tmp, &obj_list) {
436 obj = cfs_list_entry(cur, struct lmv_object, lo_list);
438 if (obj->lo_obd != obd)
441 obj->lo_state |= O_FREEING;
442 if (cfs_atomic_read(&obj->lo_count) > 1) {
443 CERROR("Object "DFID" has count (%d)\n",
445 cfs_atomic_read(&obj->lo_count));
447 __lmv_object_put(obj);
449 cfs_spin_unlock(&obj_list_lock);