Whamcloud - gitweb
LU-3030 build: Update Master Copyrights pre 2.4 split
[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) 2013, 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_PRE_CLEANUP:
195         case LCFG_CLEANUP:
196                 rc = lwp_disconnect(d);
197                 break;
198         case LCFG_PARAM:
199                 rc = -ENOSYS;
200                 break;
201         default:
202                 CERROR("%s: unknown command %u\n",
203                        (char *)lustre_cfg_string(lcfg, 0), lcfg->lcfg_command);
204                 rc = 0;
205                 break;
206         }
207
208         RETURN(rc);
209 }
210
211 const struct lu_device_operations lwp_lu_ops = {
212         .ldo_process_config     = lwp_process_config,
213 };
214
215 static struct lprocfs_vars lprocfs_lwp_module_vars[] = {
216         { "num_refs",           lprocfs_rd_numrefs, 0, 0 },
217         { 0 }
218 };
219
220 static struct lprocfs_vars lprocfs_lwp_obd_vars[] = {
221         { 0 }
222 };
223
224 void lprocfs_lwp_init_vars(struct lprocfs_static_vars *lvars)
225 {
226         lvars->module_vars = lprocfs_lwp_module_vars;
227         lvars->obd_vars = lprocfs_lwp_obd_vars;
228 }
229
230 int lwp_init0(const struct lu_env *env, struct lwp_device *lwp,
231               struct lu_device_type *ldt, struct lustre_cfg *cfg)
232 {
233         struct lprocfs_static_vars lvars = { 0 };
234         int                        rc;
235         ENTRY;
236
237         lwp->lpd_obd = class_name2obd(lustre_cfg_string(cfg, 0));
238         if (lwp->lpd_obd == NULL) {
239                 CERROR("Cannot find obd with name %s\n",
240                        lustre_cfg_string(cfg, 0));
241                 RETURN(-ENODEV);
242         }
243
244         lwp->lpd_dev.ld_ops = &lwp_lu_ops;
245         lwp->lpd_obd->obd_lu_dev = &lwp->lpd_dev;
246
247         rc = ptlrpcd_addref();
248         if (rc) {
249                 CERROR("%s: ptlrpcd addref error: rc =%d\n",
250                        lwp->lpd_obd->obd_name, rc);
251                 RETURN(rc);
252         }
253
254         rc = lwp_setup(env, lwp, lustre_cfg_string(cfg, 1));
255         if (rc) {
256                 CERROR("%s: setup lwp failed. %d\n",
257                        lwp->lpd_obd->obd_name, rc);
258                 ptlrpcd_decref();
259                 RETURN(rc);
260         }
261
262         lprocfs_lwp_init_vars(&lvars);
263         if (lprocfs_obd_setup(lwp->lpd_obd, lvars.obd_vars) == 0)
264                 ptlrpc_lprocfs_register_obd(lwp->lpd_obd);
265
266         RETURN(0);
267 }
268
269 static struct lu_device *lwp_device_free(const struct lu_env *env,
270                                          struct lu_device *lu)
271 {
272         struct lwp_device *m = lu2lwp_dev(lu);
273         ENTRY;
274
275         if (cfs_atomic_read(&lu->ld_ref) && lu->ld_site) {
276                 LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_ERROR, NULL);
277                 lu_site_print(env, lu->ld_site, &msgdata, lu_cdebug_printer);
278         }
279         lu_device_fini(&m->lpd_dev);
280         OBD_FREE_PTR(m);
281         RETURN(NULL);
282 }
283
284 static struct lu_device *lwp_device_alloc(const struct lu_env *env,
285                                           struct lu_device_type *t,
286                                           struct lustre_cfg *lcfg)
287 {
288         struct lwp_device *lwp;
289         struct lu_device  *l;
290
291         OBD_ALLOC_PTR(lwp);
292         if (lwp == NULL) {
293                 l = ERR_PTR(-ENOMEM);
294         } else {
295                 int rc;
296
297                 l = lwp2lu_dev(lwp);
298                 lu_device_init(&lwp->lpd_dev, t);
299                 rc = lwp_init0(env, lwp, t, lcfg);
300                 if (rc != 0) {
301                         lwp_device_free(env, l);
302                         l = ERR_PTR(rc);
303                 }
304         }
305         return l;
306 }
307
308
309 static struct lu_device *lwp_device_fini(const struct lu_env *env,
310                                          struct lu_device *d)
311 {
312         struct lwp_device *m = lu2lwp_dev(d);
313         struct obd_import *imp;
314         int                rc;
315         ENTRY;
316
317         if (m->lpd_exp != NULL)
318                 class_disconnect(m->lpd_exp);
319
320         imp = m->lpd_obd->u.cli.cl_import;
321
322         if (imp->imp_rq_pool) {
323                 ptlrpc_free_rq_pool(imp->imp_rq_pool);
324                 imp->imp_rq_pool = NULL;
325         }
326
327         obd_cleanup_client_import(m->lpd_obd);
328
329         LASSERT(m->lpd_obd);
330         ptlrpc_lprocfs_unregister_obd(m->lpd_obd);
331         lprocfs_obd_cleanup(m->lpd_obd);
332
333         rc = client_obd_cleanup(m->lpd_obd);
334         LASSERTF(rc == 0, "error %d\n", rc);
335
336         ptlrpcd_decref();
337
338         RETURN(NULL);
339 }
340
341 static struct lu_device_type_operations lwp_device_type_ops = {
342         .ldto_device_alloc   = lwp_device_alloc,
343         .ldto_device_free    = lwp_device_free,
344         .ldto_device_fini    = lwp_device_fini
345 };
346
347 struct lu_device_type lwp_device_type = {
348         .ldt_tags     = LU_DEVICE_DT,
349         .ldt_name     = LUSTRE_LWP_NAME,
350         .ldt_ops      = &lwp_device_type_ops,
351         .ldt_ctx_tags = LCT_MD_THREAD
352 };
353
354 static int lwp_obd_connect(const struct lu_env *env, struct obd_export **exp,
355                            struct obd_device *obd, struct obd_uuid *cluuid,
356                            struct obd_connect_data *data, void *localdata)
357 {
358         struct lwp_device       *lwp = lu2lwp_dev(obd->obd_lu_dev);
359         struct obd_connect_data *ocd;
360         struct obd_import       *imp;
361         struct lustre_handle     conn;
362         int                      rc;
363
364         ENTRY;
365
366         CDEBUG(D_CONFIG, "connect #%d\n", lwp->lpd_connects);
367
368         rc = class_connect(&conn, obd, cluuid);
369         if (rc)
370                 RETURN(rc);
371
372         *exp = class_conn2export(&conn);
373         lwp->lpd_exp = *exp;
374
375         /* Why should there ever be more than 1 connect? */
376         lwp->lpd_connects++;
377         LASSERT(lwp->lpd_connects == 1);
378
379         imp = lwp->lpd_obd->u.cli.cl_import;
380         imp->imp_dlm_handle = conn;
381
382         LASSERT(data != NULL);
383         ocd = &imp->imp_connect_data;
384         *ocd = *data;
385
386         LASSERT(ocd->ocd_connect_flags & OBD_CONNECT_LIGHTWEIGHT);
387
388         ocd->ocd_version = LUSTRE_VERSION_CODE;
389         imp->imp_connect_flags_orig = ocd->ocd_connect_flags;
390
391         rc = ptlrpc_connect_import(imp);
392         if (rc) {
393                 CERROR("%s: can't connect obd: rc = %d\n", obd->obd_name, rc);
394                 GOTO(out, rc);
395         }
396
397         ptlrpc_pinger_add_import(imp);
398
399 out:
400         RETURN(rc);
401 }
402
403 static int lwp_obd_disconnect(struct obd_export *exp)
404 {
405         struct obd_device *obd = exp->exp_obd;
406         struct lwp_device *lwp = lu2lwp_dev(obd->obd_lu_dev);
407         int                rc;
408         ENTRY;
409
410         /* Only disconnect the underlying layers on the final disconnect. */
411         LASSERT(lwp->lpd_connects == 1);
412         lwp->lpd_connects--;
413
414         rc = class_disconnect(exp);
415         if (rc)
416                 CERROR("%s: class disconnect error: rc = %d\n",
417                        obd->obd_name, rc);
418
419         RETURN(rc);
420 }
421
422 static int lwp_import_event(struct obd_device *obd, struct obd_import *imp,
423                             enum obd_import_event event)
424 {
425         switch (event) {
426         case IMP_EVENT_DISCON:
427         case IMP_EVENT_INACTIVE:
428         case IMP_EVENT_ACTIVE:
429                 break;
430         case IMP_EVENT_INVALIDATE:
431                 if (obd->obd_namespace == NULL)
432                         break;
433                 ldlm_namespace_cleanup(obd->obd_namespace, LDLM_FL_LOCAL_ONLY);
434                 break;
435         case IMP_EVENT_OCD:
436                 break;
437         default:
438                 CERROR("%s: unsupported import event: %#x\n",
439                        obd->obd_name, event);
440         }
441         return 0;
442 }
443
444 struct obd_ops lwp_obd_device_ops = {
445         .o_owner        = THIS_MODULE,
446         .o_add_conn     = client_import_add_conn,
447         .o_del_conn     = client_import_del_conn,
448         .o_connect      = lwp_obd_connect,
449         .o_disconnect   = lwp_obd_disconnect,
450         .o_import_event = lwp_import_event,
451 };