Whamcloud - gitweb
ed5dba94e0e7009770aa8f891e6f7fe5d3a0dceb
[fs/lustre-release.git] / lustre / osp / lwp_dev.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, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 021110-1307, USA
20  *
21  * GPL HEADER END
22  */
23 /*
24  * Copyright (c) 2012 Intel Corporation
25  * Use is subject to license terms.
26  *
27  * lustre/osp/lwp_dev.c
28  *
29  * Light Weight Proxy, which is just for managing the connection established
30  * from OSTs/MDTs to MDT0.
31  *
32  * Author: <di.wang@intel.com>
33  * Author: <yawei.niu@intel.com>
34  */
35 #ifndef EXPORT_SYMTAB
36 # define EXPORT_SYMTAB
37 #endif
38 #define DEBUG_SUBSYSTEM S_OST
39
40 #include <obd_class.h>
41 #include <lustre_param.h>
42 #include <lustre_log.h>
43
44 struct lwp_device {
45         struct lu_device        lpd_dev;
46         struct obd_device       *lpd_obd;
47         struct obd_uuid         lpd_cluuid;
48         struct obd_export       *lpd_exp;
49         int                     lpd_connects;
50 };
51
52 static inline struct lwp_device *lu2lwp_dev(struct lu_device *d)
53 {
54         return container_of0(d, struct lwp_device, lpd_dev);
55 }
56
57 static inline struct lu_device *lwp2lu_dev(struct lwp_device *d)
58 {
59         return &d->lpd_dev;
60 }
61
62 static int lwp_name2fsname(char *lwpname, char *fsname)
63 {
64         char *ptr;
65
66         LASSERT(lwpname != NULL);
67         LASSERT(fsname != NULL);
68
69         sprintf(fsname, "-%s-", LUSTRE_LWP_NAME);
70
71         ptr = strstr(lwpname, fsname);
72         if (ptr == NULL)
73                 return -EINVAL;
74
75         while (*(--ptr) != '-') {
76                 if (ptr == lwpname)
77                         return -EINVAL;
78         }
79
80         strncpy(fsname, lwpname, ptr - lwpname);
81         fsname[ptr - lwpname] = '\0';
82
83         return 0;
84 }
85
86 static int lwp_setup(const struct lu_env *env, struct lwp_device *lwp,
87                      char *nidstring)
88 {
89         struct lustre_cfg_bufs  *bufs = NULL;
90         struct lustre_cfg       *lcfg = NULL;
91         char                    *lwpname = lwp->lpd_obd->obd_name;
92         char                    *fsname = NULL;
93         char                    *server_uuid = NULL;
94         class_uuid_t             uuid;
95         struct obd_import       *imp;
96         int                      rc;
97         ENTRY;
98
99         OBD_ALLOC_PTR(bufs);
100         if (bufs == NULL)
101                 RETURN(-ENOMEM);
102
103         OBD_ALLOC(fsname, strlen(lwpname));
104         if (fsname == NULL)
105                 GOTO(out, rc = -ENOMEM);
106
107         rc = lwp_name2fsname(lwpname, fsname);
108         if (rc) {
109                 CERROR("%s: failed to get fsname from lwpname. %d\n",
110                        lwpname, rc);
111                 GOTO(out, rc);
112         }
113
114         OBD_ALLOC(server_uuid, strlen(fsname) + 15);
115         if (server_uuid == NULL)
116                 GOTO(out, rc = -ENOMEM);
117
118         sprintf(server_uuid, "%s-MDT0000_UUID", fsname);
119         lustre_cfg_bufs_reset(bufs, lwpname);
120         lustre_cfg_bufs_set_string(bufs, 1, server_uuid);
121         lustre_cfg_bufs_set_string(bufs, 2, nidstring);
122         lcfg = lustre_cfg_new(LCFG_SETUP, bufs);
123         if (lcfg == NULL)
124                 GOTO(out, rc = -ENOMEM);
125
126         rc = client_obd_setup(lwp->lpd_obd, lcfg);
127         if (rc != 0) {
128                 CERROR("%s: client obd setup error: rc = %d\n",
129                        lwp->lpd_obd->obd_name, rc);
130                 GOTO(out, rc);
131         }
132
133         imp = lwp->lpd_obd->u.cli.cl_import;
134         rc = ptlrpc_init_import(imp);
135         if (rc)
136                 GOTO(out, rc);
137
138         ll_generate_random_uuid(uuid);
139         class_uuid_unparse(uuid, &lwp->lpd_cluuid);
140 out:
141         if (bufs != NULL)
142                 OBD_FREE_PTR(bufs);
143         if (server_uuid != NULL)
144                 OBD_FREE(server_uuid, strlen(fsname) + 15);
145         if (fsname != NULL)
146                 OBD_FREE(fsname, strlen(lwpname));
147         if (lcfg != NULL)
148                 lustre_cfg_free(lcfg);
149         if (rc)
150                 client_obd_cleanup(lwp->lpd_obd);
151         RETURN(rc);
152 }
153
154 int lwp_disconnect(struct lwp_device *d)
155 {
156         struct obd_import *imp;
157         int rc = 0;
158
159         imp = d->lpd_obd->u.cli.cl_import;
160
161         /* Mark import deactivated now, so we don't try to reconnect if any
162          * of the cleanup RPCs fails (e.g. ldlm cancel, etc).  We don't
163          * fully deactivate the import, or that would drop all requests. */
164         LASSERT(imp != NULL);
165         spin_lock(&imp->imp_lock);
166         imp->imp_deactive = 1;
167         spin_unlock(&imp->imp_lock);
168
169         ptlrpc_deactivate_import(imp);
170
171         /* Some non-replayable imports (MDS's OSCs) are pinged, so just
172          * delete it regardless.  (It's safe to delete an import that was
173          * never added.) */
174         (void)ptlrpc_pinger_del_import(imp);
175
176         rc = ptlrpc_disconnect_import(imp, 0);
177         if (rc && rc != -ETIMEDOUT)
178                 CERROR("%s: can't disconnect: rc = %d\n",
179                        d->lpd_obd->obd_name, rc);
180
181         ptlrpc_invalidate_import(imp);
182
183         RETURN(rc);
184 }
185
186 static int lwp_process_config(const struct lu_env *env,
187                               struct lu_device *dev, struct lustre_cfg *lcfg)
188 {
189         struct lwp_device               *d = lu2lwp_dev(dev);
190         int                              rc;
191         ENTRY;
192
193         switch (lcfg->lcfg_command) {
194         case LCFG_CLEANUP:
195                 rc = lwp_disconnect(d);
196                 break;
197         case LCFG_PARAM:
198                 rc = -ENOSYS;
199                 break;
200         default:
201                 CERROR("%s: unknown command %u\n",
202                        (char *)lustre_cfg_string(lcfg, 0), lcfg->lcfg_command);
203                 rc = 0;
204                 break;
205         }
206
207         RETURN(rc);
208 }
209
210 const struct lu_device_operations lwp_lu_ops = {
211         .ldo_process_config     = lwp_process_config,
212 };
213
214 static struct lprocfs_vars lprocfs_lwp_module_vars[] = {
215         { "num_refs",           lprocfs_rd_numrefs, 0, 0 },
216         { 0 }
217 };
218
219 static struct lprocfs_vars lprocfs_lwp_obd_vars[] = {
220         { 0 }
221 };
222
223 void lprocfs_lwp_init_vars(struct lprocfs_static_vars *lvars)
224 {
225         lvars->module_vars = lprocfs_lwp_module_vars;
226         lvars->obd_vars = lprocfs_lwp_obd_vars;
227 }
228
229 int lwp_init0(const struct lu_env *env, struct lwp_device *lwp,
230               struct lu_device_type *ldt, struct lustre_cfg *cfg)
231 {
232         struct lprocfs_static_vars lvars = { 0 };
233         int                        rc;
234         ENTRY;
235
236         lwp->lpd_obd = class_name2obd(lustre_cfg_string(cfg, 0));
237         if (lwp->lpd_obd == NULL) {
238                 CERROR("Cannot find obd with name %s\n",
239                        lustre_cfg_string(cfg, 0));
240                 RETURN(-ENODEV);
241         }
242
243         lwp->lpd_dev.ld_ops = &lwp_lu_ops;
244         lwp->lpd_obd->obd_lu_dev = &lwp->lpd_dev;
245
246         rc = ptlrpcd_addref();
247         if (rc) {
248                 CERROR("%s: ptlrpcd addref error: rc =%d\n",
249                        lwp->lpd_obd->obd_name, rc);
250                 RETURN(rc);
251         }
252
253         rc = lwp_setup(env, lwp, lustre_cfg_string(cfg, 1));
254         if (rc) {
255                 CERROR("%s: setup lwp failed. %d\n",
256                        lwp->lpd_obd->obd_name, rc);
257                 ptlrpcd_decref();
258                 RETURN(rc);
259         }
260
261         lprocfs_lwp_init_vars(&lvars);
262         if (lprocfs_obd_setup(lwp->lpd_obd, lvars.obd_vars) == 0)
263                 ptlrpc_lprocfs_register_obd(lwp->lpd_obd);
264
265         RETURN(0);
266 }
267
268 static struct lu_device *lwp_device_free(const struct lu_env *env,
269                                          struct lu_device *lu)
270 {
271         struct lwp_device *m = lu2lwp_dev(lu);
272         ENTRY;
273
274         if (cfs_atomic_read(&lu->ld_ref) && lu->ld_site) {
275                 LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_ERROR, NULL);
276                 lu_site_print(env, lu->ld_site, &msgdata, lu_cdebug_printer);
277         }
278         lu_device_fini(&m->lpd_dev);
279         OBD_FREE_PTR(m);
280         RETURN(NULL);
281 }
282
283 static struct lu_device *lwp_device_alloc(const struct lu_env *env,
284                                           struct lu_device_type *t,
285                                           struct lustre_cfg *lcfg)
286 {
287         struct lwp_device *lwp;
288         struct lu_device  *l;
289
290         OBD_ALLOC_PTR(lwp);
291         if (lwp == NULL) {
292                 l = ERR_PTR(-ENOMEM);
293         } else {
294                 int rc;
295
296                 l = lwp2lu_dev(lwp);
297                 lu_device_init(&lwp->lpd_dev, t);
298                 rc = lwp_init0(env, lwp, t, lcfg);
299                 if (rc != 0) {
300                         lwp_device_free(env, l);
301                         l = ERR_PTR(rc);
302                 }
303         }
304         return l;
305 }
306
307
308 static struct lu_device *lwp_device_fini(const struct lu_env *env,
309                                          struct lu_device *d)
310 {
311         struct lwp_device *m = lu2lwp_dev(d);
312         struct obd_import *imp;
313         int                rc;
314         ENTRY;
315
316         if (m->lpd_exp != NULL)
317                 class_disconnect(m->lpd_exp);
318
319         imp = m->lpd_obd->u.cli.cl_import;
320
321         if (imp->imp_rq_pool) {
322                 ptlrpc_free_rq_pool(imp->imp_rq_pool);
323                 imp->imp_rq_pool = NULL;
324         }
325
326         obd_cleanup_client_import(m->lpd_obd);
327
328         LASSERT(m->lpd_obd);
329         ptlrpc_lprocfs_unregister_obd(m->lpd_obd);
330         lprocfs_obd_cleanup(m->lpd_obd);
331
332         rc = client_obd_cleanup(m->lpd_obd);
333         LASSERTF(rc == 0, "error %d\n", rc);
334
335         ptlrpcd_decref();
336
337         RETURN(NULL);
338 }
339
340 static struct lu_device_type_operations lwp_device_type_ops = {
341         .ldto_device_alloc   = lwp_device_alloc,
342         .ldto_device_free    = lwp_device_free,
343         .ldto_device_fini    = lwp_device_fini
344 };
345
346 struct lu_device_type lwp_device_type = {
347         .ldt_tags     = LU_DEVICE_DT,
348         .ldt_name     = LUSTRE_LWP_NAME,
349         .ldt_ops      = &lwp_device_type_ops,
350         .ldt_ctx_tags = LCT_MD_THREAD
351 };
352
353 static int lwp_obd_connect(const struct lu_env *env, struct obd_export **exp,
354                            struct obd_device *obd, struct obd_uuid *cluuid,
355                            struct obd_connect_data *data, void *localdata)
356 {
357         struct lwp_device       *lwp = lu2lwp_dev(obd->obd_lu_dev);
358         struct obd_connect_data *ocd;
359         struct obd_import       *imp;
360         struct lustre_handle     conn;
361         int                      rc;
362
363         ENTRY;
364
365         CDEBUG(D_CONFIG, "connect #%d\n", lwp->lpd_connects);
366
367         rc = class_connect(&conn, obd, cluuid);
368         if (rc)
369                 RETURN(rc);
370
371         *exp = class_conn2export(&conn);
372         lwp->lpd_exp = *exp;
373
374         /* Why should there ever be more than 1 connect? */
375         lwp->lpd_connects++;
376         LASSERT(lwp->lpd_connects == 1);
377
378         imp = lwp->lpd_obd->u.cli.cl_import;
379         imp->imp_dlm_handle = conn;
380
381         LASSERT(data != NULL);
382         ocd = &imp->imp_connect_data;
383         *ocd = *data;
384
385         LASSERT(ocd->ocd_connect_flags & OBD_CONNECT_LIGHTWEIGHT);
386
387         ocd->ocd_version = LUSTRE_VERSION_CODE;
388         imp->imp_connect_flags_orig = ocd->ocd_connect_flags;
389
390         rc = ptlrpc_connect_import(imp);
391         if (rc) {
392                 CERROR("%s: can't connect obd: rc = %d\n", obd->obd_name, rc);
393                 GOTO(out, rc);
394         }
395
396         ptlrpc_pinger_add_import(imp);
397
398 out:
399         RETURN(rc);
400 }
401
402 static int lwp_obd_disconnect(struct obd_export *exp)
403 {
404         struct obd_device *obd = exp->exp_obd;
405         struct lwp_device *lwp = lu2lwp_dev(obd->obd_lu_dev);
406         int                rc;
407         ENTRY;
408
409         /* Only disconnect the underlying layers on the final disconnect. */
410         LASSERT(lwp->lpd_connects == 1);
411         lwp->lpd_connects--;
412
413         rc = class_disconnect(exp);
414         if (rc)
415                 CERROR("%s: class disconnect error: rc = %d\n",
416                        obd->obd_name, rc);
417
418         RETURN(rc);
419 }
420
421 static int lwp_import_event(struct obd_device *obd, struct obd_import *imp,
422                             enum obd_import_event event)
423 {
424         switch (event) {
425         case IMP_EVENT_DISCON:
426         case IMP_EVENT_INACTIVE:
427         case IMP_EVENT_ACTIVE:
428                 break;
429         case IMP_EVENT_INVALIDATE:
430                 if (obd->obd_namespace == NULL)
431                         break;
432                 ldlm_namespace_cleanup(obd->obd_namespace, LDLM_FL_LOCAL_ONLY);
433                 break;
434         case IMP_EVENT_OCD:
435                 break;
436         default:
437                 CERROR("%s: unsupported import event: %#x\n",
438                        obd->obd_name, event);
439         }
440         return 0;
441 }
442
443 struct obd_ops lwp_obd_device_ops = {
444         .o_owner        = THIS_MODULE,
445         .o_add_conn     = client_import_add_conn,
446         .o_del_conn     = client_import_del_conn,
447         .o_connect      = lwp_obd_connect,
448         .o_disconnect   = lwp_obd_disconnect,
449         .o_import_event = lwp_import_event,
450 };