Whamcloud - gitweb
- landing of b_fid after merge with b_hd_cleanup_merge.
[fs/lustre-release.git] / lustre / cmobd / cm_obd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
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.
11  *
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.
16  *
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.
20  */
21
22 #define DEBUG_SUBSYSTEM S_CMOBD
23
24 #include <linux/version.h>
25 #include <linux/init.h>
26 #include <linux/obd_support.h>
27 #include <linux/lustre_lib.h>
28 #include <linux/lustre_net.h>
29 #include <linux/lustre_idl.h>
30 #include <linux/obd_class.h>
31 #include <linux/lustre_mds.h>
32 #include <linux/lustre_cmobd.h>
33 #include <linux/lprocfs_status.h>
34 #include <linux/obd_lov.h>
35 #include <linux/obd_lmv.h>
36
37 #include "cm_internal.h"
38
39 static int cmobd_attach(struct obd_device *obd,
40                         obd_count len, void *data)
41 {
42         struct lprocfs_static_vars lvars;
43
44         lprocfs_init_vars(cmobd, &lvars);
45         return lprocfs_obd_attach(obd, lvars.obd_vars);
46 }
47
48 static int cmobd_detach(struct obd_device *obd)
49 {
50         return lprocfs_obd_detach(obd);
51 }
52
53 static struct obd_device *cmobd_find_master(struct obd_device *obd,
54                                             struct obd_uuid *uuid)
55 {
56         struct obd_device *master_obd;
57
58         CWARN("%s: looking for client obd %s\n",
59               obd->obd_uuid.uuid, uuid->uuid);
60          
61         master_obd = class_find_client_obd(NULL,
62                                            OBD_LOV_DEVICENAME,
63                                            uuid);
64         if (master_obd)
65                 return master_obd;
66         
67         master_obd = class_find_client_obd(NULL,
68                                            OBD_LMV_DEVICENAME,
69                                            uuid);
70         if (master_obd)
71                 return master_obd;
72         
73         master_obd = class_find_client_obd(NULL, LUSTRE_MDC_NAME, 
74                                            uuid);
75         return master_obd;
76 }
77
78 static inline int cmobd_lmv_obd(struct obd_device *obd)
79 {
80         if (!strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) ||
81             !strcmp(obd->obd_type->typ_name, OBD_LMV_DEVICENAME))
82                 return 1;
83
84         return 0;
85 }
86
87 static inline int cmobd_lov_obd(struct obd_device *obd)
88 {
89         if (!strcmp(obd->obd_type->typ_name, OBD_LOV_DEVICENAME))
90                 return 1;
91
92         return 0;
93 }
94
95 static void cmobd_init_ea_size(struct obd_device *obd)
96 {
97         int ost_count = 1, easize, cookiesize;
98         struct cm_obd *cmobd = &obd->u.cm;
99         ENTRY;
100
101         /* FIXME-UMKA: here we should also take into account that there is
102          * possible to have few OSTs. */
103         easize = lov_mds_md_size(ost_count);
104         cookiesize = ost_count * sizeof(struct llog_cookie);
105
106         obd_init_ea_size(cmobd->master_exp, easize, cookiesize);
107
108         cmobd->master_obd->u.cli.cl_max_mds_easize = easize;
109         cmobd->master_obd->u.cli.cl_max_mds_cookiesize = cookiesize;
110         
111         EXIT;
112 }
113
114 static int cmobd_setup(struct obd_device *obd, obd_count len, void *buf)
115 {
116         struct obd_uuid master_uuid, cache_uuid;
117         struct lustre_handle conn = { 0 };
118         struct cm_obd *cmobd = &obd->u.cm;
119         struct lustre_cfg* lcfg = buf;
120         struct lustre_id mid, lid;
121         int valsize, rc;
122         ENTRY;
123
124         if (lcfg->lcfg_inllen1 < 1 || !lcfg->lcfg_inlbuf1) {
125                 CERROR("CMOBD setup requires master uuid\n");
126                 RETURN(-EINVAL);
127         }
128         if (lcfg->lcfg_inllen2 < 1 || !lcfg->lcfg_inlbuf2) {
129                 CERROR("CMOBD setup requires cache uuid\n");
130                 RETURN(-EINVAL);
131         }
132         
133         obd_str2uuid(&master_uuid, lcfg->lcfg_inlbuf1);
134         obd_str2uuid(&cache_uuid, lcfg->lcfg_inlbuf2);
135
136         /* FIXME-WANGDI: saving client obds here is not correct as they may
137            become invalid due to refcounter exhausting on cleanup. The prefer
138            way seems to be getting them each time we need them. */
139         cmobd->master_obd = cmobd_find_master(obd, &master_uuid);
140         if (cmobd->master_obd == NULL) {
141                 CERROR("Can't find master obd %s\n", &master_uuid.uuid[0]);
142                 RETURN(-EINVAL);
143         }
144         
145         cmobd->cache_obd = class_uuid2obd(&cache_uuid);
146         if (cmobd->cache_obd == NULL) {
147                 CERROR("Can't find cache obd %s\n", &cache_uuid.uuid[0]);
148                 RETURN(-EINVAL);
149         }
150
151         rc = obd_connect(&conn, cmobd->master_obd, &obd->obd_uuid, 0);
152         if (rc)
153                 RETURN(rc);
154         cmobd->master_exp = class_conn2export(&conn);
155
156         memset(&conn, 0, sizeof(conn));
157         rc = class_connect(&conn, cmobd->cache_obd, &obd->obd_uuid);
158         if (rc)
159                 GOTO(put_master, rc);
160
161         cmobd->cache_exp = class_conn2export(&conn);
162         
163         if (cmobd_lov_obd(cmobd->master_obd)) {
164                 /* for master osc remove the recovery flag. */
165                 rc = obd_set_info(cmobd->master_exp, strlen("unrecovery"),
166                                   "unrecovery", 0, NULL); 
167                 if (rc)
168                         GOTO(put_master, rc);
169                 
170                 rc = cmobd_init_write_srv(obd);
171                 if (rc)
172                         GOTO(put_cache, rc);
173         } else {
174                 cmobd_init_ea_size(obd);
175                 cmobd->write_srv = NULL;
176         }
177
178         if (cmobd_lmv_obd(cmobd->master_obd)) {
179                 /* making sure, that both obds are ready. This is especially
180                  * important in the case of using LMV as master. */
181                 rc = obd_getready(cmobd->master_exp);
182                 if (rc) {
183                         CERROR("Can't make %s obd ready.\n",
184                                master_uuid.uuid);
185                         GOTO(put_cache, rc);
186                 }
187         
188                 rc = obd_getready(cmobd->cache_exp);
189                 if (rc) {
190                         CERROR("Can't make %s obd ready.\n",
191                                cache_uuid.uuid);
192                         GOTO(put_cache, rc);
193                 }
194         
195                 /* requesting master obd to have its root inode store cookie to
196                  * be able to save it to local root inode EA. */
197                 valsize = sizeof(struct lustre_id);
198         
199                 rc = obd_get_info(cmobd->master_exp, strlen("rootid"),
200                                   "rootid", &valsize, &mid);
201                 if (rc) {
202                         CERROR("Can't get rootid from master MDS %s, "
203                                "err= %d.\n", master_uuid.uuid, rc);
204                         GOTO(put_cache, rc);
205                 }
206
207                 /* getting rootid from cache MDS. It is needed to update local
208                  * (cache) root inode by rootid value from master obd. */
209                 rc = obd_get_info(cmobd->cache_exp, strlen("rootid"),
210                                   "rootid", &valsize, &lid);
211                 if (rc) {
212                         CERROR("Can't get rootid from local MDS %s, "
213                                "err= %d.\n", cache_uuid.uuid, rc);
214                         GOTO(put_cache, rc);
215                 }
216
217                 /* storing master MDS rootid to local root inode EA. */
218                 CWARN("storing "DLID4" to local inode "DLID4".\n",
219                       OLID4(&mid), OLID4(&lid));
220
221                 rc = mds_update_mid(cmobd->cache_obd, &lid,
222                                     &mid, sizeof(mid));
223                 if (rc) {
224                         CERROR("Can't update local root inode by ID "
225                                "from master MDS %s, err = %d.\n",
226                                master_uuid.uuid, rc);
227                         GOTO(put_cache, rc);
228                 }
229         }
230
231         RETURN(rc);
232 put_cache:
233         class_disconnect(cmobd->cache_exp, 0);
234 put_master:
235         obd_disconnect(cmobd->master_exp, 0);
236         RETURN(rc);
237 }
238
239 static int cmobd_cleanup(struct obd_device *obd, int flags)
240 {
241         struct cm_obd *cmobd = &obd->u.cm;
242         ENTRY;
243
244         if (cmobd->write_srv)
245                 cmobd_cleanup_write_srv(obd);
246
247         class_disconnect(cmobd->cache_exp, 0);
248         obd_disconnect(cmobd->master_exp, 0);
249         
250         RETURN(0);
251 }
252
253 static int cmobd_iocontrol(unsigned int cmd, struct obd_export *exp,
254                            int len, void *karg, void *uarg)
255 {
256         struct obd_device *obd = exp->exp_obd;
257         int rc = 0;
258         ENTRY;
259         
260         switch (cmd) {
261         case OBD_IOC_CMOBD_SYNC: /* trigger reintegration */
262                 rc = cmobd_reintegrate(obd);
263                 break;
264         default:
265                 CERROR("unrecognized ioctl %#x\n", cmd);
266                 rc = -EINVAL;
267                 break;
268         }
269                 
270         RETURN(rc);
271 }
272
273 static struct obd_ops cmobd_ops = {
274         o_owner:                THIS_MODULE,
275         o_attach:               cmobd_attach,
276         o_detach:               cmobd_detach,
277         o_setup:                cmobd_setup,
278         o_cleanup:              cmobd_cleanup,
279         o_iocontrol:            cmobd_iocontrol,
280 };
281
282 kmem_cache_t *cmobd_extent_slab;
283
284 static int __init cmobd_init(void)
285 {
286         struct lprocfs_static_vars lvars;
287         int rc;
288         ENTRY;
289
290         printk(KERN_INFO "Lustre: Cache Manager OBD driver; info@clusterfs.com\n");
291
292         lprocfs_init_vars(cmobd, &lvars);
293         rc = class_register_type(&cmobd_ops, NULL, lvars.module_vars,
294                                  LUSTRE_CMOBD_NAME);
295         if (rc)
296                 RETURN(rc);
297         cmobd_extent_slab = kmem_cache_create("cmobd_extents",
298                                                sizeof(struct cmobd_extent_info), 0,
299                                                SLAB_HWCACHE_ALIGN, NULL, NULL);
300         if (cmobd_extent_slab == NULL) {
301                 class_unregister_type(LUSTRE_CMOBD_NAME);
302                 RETURN(-ENOMEM);
303         }
304         RETURN(0);
305 }
306
307 static void /*__exit*/ cmobd_exit(void)
308 {
309         class_unregister_type(LUSTRE_CMOBD_NAME);
310         if (kmem_cache_destroy(cmobd_extent_slab) != 0)
311                 CERROR("couldn't free cmobd extent slab\n");
312 }
313
314 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
315 MODULE_DESCRIPTION("Lustre Cache Manager OBD driver");
316 MODULE_LICENSE("GPL");
317
318 module_init(cmobd_init);
319 module_exit(cmobd_exit);