1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002, 2003 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 # define EXPORT_SYMTAB
25 #define DEBUG_SUBSYSTEM S_LMV
27 #include <linux/slab.h>
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/slab.h>
31 #include <linux/pagemap.h>
32 #include <asm/div64.h>
33 #include <linux/seq_file.h>
35 #include <liblustre.h>
38 #include <linux/obd_support.h>
39 #include <linux/lustre_lib.h>
40 #include <linux/lustre_net.h>
41 #include <linux/lustre_idl.h>
42 #include <linux/lustre_dlm.h>
43 #include <linux/lustre_mds.h>
44 #include <linux/obd_class.h>
45 #include <linux/obd_ost.h>
46 #include <linux/lprocfs_status.h>
47 #include <linux/lustre_fsfilt.h>
48 #include <linux/obd_lmv.h>
49 #include "lmv_internal.h"
52 LIST_HEAD(lmv_obj_list);
53 spinlock_t lmv_obj_list_lock = SPIN_LOCK_UNLOCKED;
55 struct lmv_obj *lmv_grab_obj(struct obd_device *obd,
56 struct ll_fid *fid, int create)
58 struct lmv_obd *lmv = &obd->u.lmv;
59 struct list_head *cur;
60 struct lmv_obj *obj, *obj2;
62 spin_lock(&lmv_obj_list_lock);
63 list_for_each(cur, &lmv_obj_list) {
64 obj = list_entry(cur, struct lmv_obj, list);
65 if (obj->fid.mds == fid->mds && obj->fid.id == fid->id &&
66 obj->fid.generation == fid->generation) {
67 atomic_inc(&obj->count);
68 spin_unlock(&lmv_obj_list_lock);
72 spin_unlock(&lmv_obj_list_lock);
77 /* no such object yet, allocate and initialize them */
78 OBD_ALLOC(obj, sizeof(*obj));
81 atomic_set(&obj->count, 0);
85 OBD_ALLOC(obj->objs, sizeof(struct lmv_inode) * lmv->desc.ld_tgt_count);
87 OBD_FREE(obj, sizeof(*obj));
90 memset(obj->objs, 0, sizeof(struct lmv_inode) * lmv->desc.ld_tgt_count);
92 spin_lock(&lmv_obj_list_lock);
93 list_for_each(cur, &lmv_obj_list) {
94 obj2 = list_entry(cur, struct lmv_obj, list);
95 if (obj2->fid.mds == fid->mds && obj2->fid.id == fid->id &&
96 obj2->fid.generation == fid->generation) {
97 /* someone created it already */
99 sizeof(struct lmv_inode) * lmv->desc.ld_tgt_count);
100 OBD_FREE(obj, sizeof(*obj));
102 atomic_inc(&obj2->count);
103 spin_unlock(&lmv_obj_list_lock);
107 list_add(&obj->list, &lmv_obj_list);
108 CDEBUG(D_OTHER, "new obj in lmv cache: %lu/%lu/%lu\n",
109 (unsigned long) fid->mds, (unsigned long) fid->id,
110 (unsigned long) fid->generation);
111 spin_unlock(&lmv_obj_list_lock);
117 void lmv_put_obj(struct lmv_obj *obj)
121 if (atomic_dec_and_test(&obj->count)) {
122 CDEBUG(D_OTHER, "last reference to %lu/%lu/%lu\n",
123 (unsigned long) obj->fid.mds,
124 (unsigned long) obj->fid.id,
125 (unsigned long) obj->fid.generation);
129 void lmv_cleanup_objs(struct obd_device *obd)
131 struct lmv_obd *lmv = &obd->u.lmv;
132 struct list_head *cur, *tmp;
135 spin_lock(&lmv_obj_list_lock);
136 list_for_each_safe(cur, tmp, &lmv_obj_list) {
137 obj = list_entry(cur, struct lmv_obj, list);
141 list_del(&obj->list);
143 sizeof(struct lmv_inode) * lmv->desc.ld_tgt_count);
144 OBD_FREE(obj, sizeof(*obj));
146 spin_unlock(&lmv_obj_list_lock);
149 int lmv_create_obj_from_attrs(struct obd_export *exp,
150 struct ll_fid *fid, struct mea *mea)
152 struct obd_device *obd = exp->exp_obd;
153 struct lmv_obd *lmv = &obd->u.lmv;
154 struct ptlrpc_request *req = NULL;
157 int mealen, i, rc = 0;
160 CDEBUG(D_OTHER, "get mea for %lu/%lu/%lu and create lmv obj\n",
161 (unsigned long) fid->mds, (unsigned long) fid->id,
162 (unsigned long) fid->generation);
167 CDEBUG(D_OTHER, "mea isn't passed in, get it now\n");
168 mealen = MEA_SIZE_LMV(lmv);
170 /* time to update mea of parent fid */
174 valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
175 rc = md_getattr(lmv->tgts[fid->mds].ltd_exp, fid,
176 valid, mealen, &req);
178 CERROR("md_getattr() failed, rc = %d\n", rc);
182 rc = mdc_req2lustre_md(exp, req, 0, NULL, &md);
184 CERROR("mdc_req2lustre_md() failed, rc = %d\n", rc);
189 GOTO(cleanup, rc = -ENODATA);
194 /* got mea, now create obj for it */
195 obj = lmv_grab_obj(obd, fid, 1);
197 GOTO(cleanup, rc = -ENOMEM);
199 obj->objcount = mea->mea_count;
200 /* put all fids in */
201 for (i = 0; i < mea->mea_count; i++) {
202 CDEBUG(D_OTHER, "subobj %lu/%lu/%lu\n",
203 (unsigned long) mea->mea_fids[i].mds,
204 (unsigned long) mea->mea_fids[i].id,
205 (unsigned long) mea->mea_fids[i].generation);
206 obj->objs[i].fid = mea->mea_fids[i];
211 ptlrpc_req_finished(req);