Whamcloud - gitweb
LU-1347 build: remove the vim/emacs modelines
[fs/lustre-release.git] / lustre / lmv / lmv_object.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
19  *
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
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, Whamcloud, Inc.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #ifndef EXPORT_SYMTAB
38 # define EXPORT_SYMTAB
39 #endif
40 #define DEBUG_SUBSYSTEM S_LMV
41 #ifdef __KERNEL__
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>
49 #else
50 #include <liblustre.h>
51 #endif
52
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"
61
62 extern cfs_mem_cache_t *lmv_object_cache;
63 extern cfs_atomic_t lmv_object_count;
64
65 static CFS_LIST_HEAD(obj_list);
66 static cfs_spinlock_t obj_list_lock = CFS_SPIN_LOCK_UNLOCKED;
67
68 struct lmv_object *lmv_object_alloc(struct obd_device *obd,
69                                     const struct lu_fid *fid,
70                                     struct lmv_stripe_md *mea)
71 {
72         struct lmv_obd          *lmv = &obd->u.lmv;
73         unsigned int             obj_size;
74         struct lmv_object       *obj;
75         int                      i;
76
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);
80
81         OBD_SLAB_ALLOC_PTR(obj, lmv_object_cache);
82         if (!obj)
83                 return NULL;
84
85         cfs_atomic_inc(&lmv_object_count);
86
87         obj->lo_fid = *fid;
88         obj->lo_obd = obd;
89         obj->lo_state = 0;
90         obj->lo_hashtype = mea->mea_magic;
91
92         cfs_mutex_init(&obj->lo_guard);
93         cfs_atomic_set(&obj->lo_count, 0);
94         obj->lo_objcount = mea->mea_count;
95
96         obj_size = sizeof(struct lmv_stripe) * 
97                 lmv->desc.ld_tgt_count;
98
99         OBD_ALLOC_LARGE(obj->lo_stripes, obj_size);
100         if (!obj->lo_stripes)
101                 goto err_obj;
102
103         CDEBUG(D_INODE, "Allocate object for "DFID"\n", 
104                PFID(fid));
105         for (i = 0; i < mea->mea_count; i++) {
106                 int rc;
107
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));
112
113                 /*
114                  * Cache slave mds number to use it in all cases it is needed
115                  * instead of constant lookup.
116                  */
117                 rc = lmv_fld_lookup(lmv, &obj->lo_stripes[i].ls_fid,
118                                     &obj->lo_stripes[i].ls_mds);
119                 if (rc)
120                         goto err_obj;
121         }
122
123         return obj;
124 err_obj:
125         OBD_FREE(obj, sizeof(*obj));
126         return NULL;
127 }
128
129 void lmv_object_free(struct lmv_object *obj)
130 {
131         struct lmv_obd          *lmv = &obj->lo_obd->u.lmv;
132         unsigned int             obj_size;
133
134         LASSERT(!cfs_atomic_read(&obj->lo_count));
135
136         obj_size = sizeof(struct lmv_stripe) *
137                 lmv->desc.ld_tgt_count;
138
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);
142 }
143
144 static void __lmv_object_add(struct lmv_object *obj)
145 {
146         cfs_atomic_inc(&obj->lo_count);
147         cfs_list_add(&obj->lo_list, &obj_list);
148 }
149
150 void lmv_object_add(struct lmv_object *obj)
151 {
152         cfs_spin_lock(&obj_list_lock);
153         __lmv_object_add(obj);
154         cfs_spin_unlock(&obj_list_lock);
155 }
156
157 static void __lmv_object_del(struct lmv_object *obj)
158 {
159         cfs_list_del(&obj->lo_list);
160         lmv_object_free(obj);
161 }
162
163 void lmv_object_del(struct lmv_object *obj)
164 {
165         cfs_spin_lock(&obj_list_lock);
166         __lmv_object_del(obj);
167         cfs_spin_unlock(&obj_list_lock);
168 }
169
170 static struct lmv_object *__lmv_object_get(struct lmv_object *obj)
171 {
172         LASSERT(obj != NULL);
173         cfs_atomic_inc(&obj->lo_count);
174         return obj;
175 }
176
177 struct lmv_object *lmv_object_get(struct lmv_object *obj)
178 {
179         cfs_spin_lock(&obj_list_lock);
180         __lmv_object_get(obj);
181         cfs_spin_unlock(&obj_list_lock);
182         return obj;
183 }
184
185 static void __lmv_object_put(struct lmv_object *obj)
186 {
187         LASSERT(obj);
188
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);
193         }
194 }
195
196 void lmv_object_put(struct lmv_object *obj)
197 {
198         cfs_spin_lock(&obj_list_lock);
199         __lmv_object_put(obj);
200         cfs_spin_unlock(&obj_list_lock);
201 }
202
203 void lmv_object_put_unlock(struct lmv_object *obj)
204 {
205         lmv_object_unlock(obj);
206         lmv_object_put(obj);
207 }
208
209 static struct lmv_object *__lmv_object_find(struct obd_device *obd, const struct lu_fid *fid)
210 {
211         struct lmv_object       *obj;
212         cfs_list_t              *cur;
213
214         cfs_list_for_each(cur, &obj_list) {
215                 obj = cfs_list_entry(cur, struct lmv_object, lo_list);
216
217                 /*
218                  * Check if object is in destroying phase. If so - skip
219                  * it.
220                  */
221                 if (obj->lo_state & O_FREEING)
222                         continue;
223
224                 /*
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.
230                  */
231                 if (obj->lo_obd != obd)
232                         continue;
233
234                 /*
235                  * Check if this is what we're looking for.
236                  */
237                 if (lu_fid_eq(&obj->lo_fid, fid))
238                         return __lmv_object_get(obj);
239         }
240
241         return NULL;
242 }
243
244 struct lmv_object *lmv_object_find(struct obd_device *obd,
245                                    const struct lu_fid *fid)
246 {
247         struct lmv_obd          *lmv = &obd->u.lmv;
248         struct lmv_object       *obj = NULL;
249         ENTRY;
250
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);
256         }
257
258         RETURN(obj);
259 }
260
261 struct lmv_object *lmv_object_find_lock(struct obd_device *obd, 
262                                         const struct lu_fid *fid)
263 {
264         struct lmv_object       *obj;
265         ENTRY;
266
267         obj = lmv_object_find(obd, fid);
268         if (obj)
269                 lmv_object_lock(obj);
270
271         RETURN(obj);
272 }
273
274 static struct lmv_object *__lmv_object_create(struct obd_device *obd, 
275                                               const struct lu_fid *fid,
276                                               struct lmv_stripe_md *mea)
277 {
278         struct lmv_object       *new;
279         struct lmv_object       *obj;
280         ENTRY;
281
282         obj = lmv_object_find(obd, fid);
283         if (obj)
284                 RETURN(obj);
285
286         new = lmv_object_alloc(obd, fid, mea);
287         if (!new)
288                 RETURN(NULL);
289
290         /* 
291          * Check if someone created it already while we were dealing with
292          * allocating @obj. 
293          */
294         cfs_spin_lock(&obj_list_lock);
295         obj = __lmv_object_find(obd, fid);
296         if (obj) {
297                 /* 
298                  * Someone created it already - put @obj and getting out. 
299                  */
300                 cfs_spin_unlock(&obj_list_lock);
301                 lmv_object_free(new);
302                 RETURN(obj);
303         }
304
305         __lmv_object_add(new);
306         __lmv_object_get(new);
307
308         cfs_spin_unlock(&obj_list_lock);
309
310         CDEBUG(D_INODE, "New obj in lmv cache: "DFID"\n",
311                PFID(fid));
312
313         RETURN(new);
314 }
315
316 struct lmv_object *lmv_object_create(struct obd_export *exp, 
317                                      const struct lu_fid *fid,
318                                      struct lmv_stripe_md *mea)
319 {
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;
325         struct lustre_md         md;
326         int                      mealen;
327         int                      rc;
328         ENTRY;
329
330         CDEBUG(D_INODE, "Get mea for "DFID" and create lmv obj\n",
331                PFID(fid));
332
333         md.mea = NULL;
334
335         if (mea == NULL) {
336                 struct md_op_data *op_data;
337                 __u64 valid;
338
339                 CDEBUG(D_INODE, "Mea isn't passed in, get it now\n");
340                 mealen = lmv_get_easize(lmv);
341
342                 /*
343                  * Time to update mea of parent fid.
344                  */
345                 md.mea = NULL;
346                 valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA | OBD_MD_MEA;
347
348                 tgt = lmv_find_target(lmv, fid);
349                 if (IS_ERR(tgt))
350                         GOTO(cleanup, obj = (void *)tgt);
351
352                 OBD_ALLOC_PTR(op_data);
353                 if (op_data == NULL)
354                         GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
355
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);
361                 if (rc) {
362                         CERROR("md_getattr() failed, error %d\n", rc);
363                         GOTO(cleanup, obj = ERR_PTR(rc));
364                 }
365
366                 rc = md_get_lustre_md(exp, req, NULL, exp, &md);
367                 if (rc) {
368                         CERROR("md_get_lustre_md() failed, error %d\n", rc);
369                         GOTO(cleanup, obj = ERR_PTR(rc));
370                 }
371
372                 if (md.mea == NULL)
373                         GOTO(cleanup, obj = ERR_PTR(-ENODATA));
374
375                 mea = md.mea;
376         }
377
378         /*
379          * Got mea, now create obj for it.
380          */
381         obj = __lmv_object_create(obd, fid, mea);
382         if (!obj) {
383                 CERROR("Can't create new object "DFID"\n",
384                        PFID(fid));
385                 GOTO(cleanup, obj = ERR_PTR(-ENOMEM));
386         }
387
388         if (md.mea != NULL)
389                 obd_free_memmd(exp, (void *)&md.mea);
390
391         EXIT;
392 cleanup:
393         if (req)
394                 ptlrpc_req_finished(req);
395         return obj;
396 }
397
398 int lmv_object_delete(struct obd_export *exp, const struct lu_fid *fid)
399 {
400         struct obd_device       *obd = exp->exp_obd;
401         struct lmv_object       *obj;
402         int                      rc = 0;
403         ENTRY;
404
405         cfs_spin_lock(&obj_list_lock);
406         obj = __lmv_object_find(obd, fid);
407         if (obj) {
408                 obj->lo_state |= O_FREEING;
409                 __lmv_object_put(obj);
410                 __lmv_object_put(obj);
411                 rc = 1;
412         }
413         cfs_spin_unlock(&obj_list_lock);
414         RETURN(rc);
415 }
416
417 int lmv_object_setup(struct obd_device *obd)
418 {
419         ENTRY;
420         LASSERT(obd != NULL);
421
422         CDEBUG(D_INFO, "LMV object manager setup (%s)\n",
423                obd->obd_uuid.uuid);
424
425         RETURN(0);
426 }
427
428 void lmv_object_cleanup(struct obd_device *obd)
429 {
430         cfs_list_t              *cur;
431         cfs_list_t              *tmp;
432         struct lmv_object       *obj;
433         ENTRY;
434
435         CDEBUG(D_INFO, "LMV object manager cleanup (%s)\n",
436                obd->obd_uuid.uuid);
437
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);
441
442                 if (obj->lo_obd != obd)
443                         continue;
444
445                 obj->lo_state |= O_FREEING;
446                 if (cfs_atomic_read(&obj->lo_count) > 1) {
447                         CERROR("Object "DFID" has count (%d)\n", 
448                                PFID(&obj->lo_fid),
449                                cfs_atomic_read(&obj->lo_count));
450                 }
451                 __lmv_object_put(obj);
452         }
453         cfs_spin_unlock(&obj_list_lock);
454         EXIT;
455 }