blob: 37d6aefde5349cc921bac5b7d5dfccf056fc706c [file] [log] [blame]
Peng Taod7e09d02013-05-02 16:46:55 +08001/*
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) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
29 *
30 * Copyright (c) 2011, 2012, Intel Corporation.
31 */
32/*
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
35 *
36 * lustre/obdclass/genops.c
37 *
38 * These are the only exported functions, they provide some generic
39 * infrastructure for managing object devices
40 */
41
42#define DEBUG_SUBSYSTEM S_CLASS
Greg Kroah-Hartman610f7372014-07-11 22:15:24 -070043#include "../include/obd_class.h"
44#include "../include/lprocfs_status.h"
Peng Taod7e09d02013-05-02 16:46:55 +080045
Peng Taod7e09d02013-05-02 16:46:55 +080046spinlock_t obd_types_lock;
47
48struct kmem_cache *obd_device_cachep;
49struct kmem_cache *obdo_cachep;
50EXPORT_SYMBOL(obdo_cachep);
Haneen Mohammed052c5292015-03-21 10:51:42 +030051static struct kmem_cache *import_cachep;
Peng Taod7e09d02013-05-02 16:46:55 +080052
Haneen Mohammed052c5292015-03-21 10:51:42 +030053static struct list_head obd_zombie_imports;
54static struct list_head obd_zombie_exports;
55static spinlock_t obd_zombie_impexp_lock;
Peng Taod7e09d02013-05-02 16:46:55 +080056static void obd_zombie_impexp_notify(void);
57static void obd_zombie_export_add(struct obd_export *exp);
58static void obd_zombie_import_add(struct obd_import *imp);
59static void print_export_data(struct obd_export *exp,
60 const char *status, int locks);
61
62int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
63EXPORT_SYMBOL(ptlrpc_put_connection_superhack);
64
65/*
66 * support functions: we could use inter-module communication, but this
67 * is more portable to other OS's
68 */
69static struct obd_device *obd_device_alloc(void)
70{
71 struct obd_device *obd;
72
Ann Koehler0be19af2014-04-27 13:06:36 -040073 OBD_SLAB_ALLOC_PTR_GFP(obd, obd_device_cachep, GFP_NOFS);
Peng Taod7e09d02013-05-02 16:46:55 +080074 if (obd != NULL) {
75 obd->obd_magic = OBD_DEVICE_MAGIC;
76 }
77 return obd;
78}
79
80static void obd_device_free(struct obd_device *obd)
81{
82 LASSERT(obd != NULL);
83 LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "obd %p obd_magic %08x != %08x\n",
84 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
85 if (obd->obd_namespace != NULL) {
86 CERROR("obd %p: namespace %p was not properly cleaned up (obd_force=%d)!\n",
87 obd, obd->obd_namespace, obd->obd_force);
88 LBUG();
89 }
90 lu_ref_fini(&obd->obd_reference);
91 OBD_SLAB_FREE_PTR(obd, obd_device_cachep);
92}
93
94struct obd_type *class_search_type(const char *name)
95{
96 struct list_head *tmp;
97 struct obd_type *type;
98
99 spin_lock(&obd_types_lock);
100 list_for_each(tmp, &obd_types) {
101 type = list_entry(tmp, struct obd_type, typ_chain);
102 if (strcmp(type->typ_name, name) == 0) {
103 spin_unlock(&obd_types_lock);
104 return type;
105 }
106 }
107 spin_unlock(&obd_types_lock);
108 return NULL;
109}
110EXPORT_SYMBOL(class_search_type);
111
112struct obd_type *class_get_type(const char *name)
113{
114 struct obd_type *type = class_search_type(name);
115
116 if (!type) {
117 const char *modname = name;
118
119 if (strcmp(modname, "obdfilter") == 0)
120 modname = "ofd";
121
122 if (strcmp(modname, LUSTRE_LWP_NAME) == 0)
123 modname = LUSTRE_OSP_NAME;
124
125 if (!strncmp(modname, LUSTRE_MDS_NAME, strlen(LUSTRE_MDS_NAME)))
126 modname = LUSTRE_MDT_NAME;
127
128 if (!request_module("%s", modname)) {
129 CDEBUG(D_INFO, "Loaded module '%s'\n", modname);
130 type = class_search_type(name);
131 } else {
132 LCONSOLE_ERROR_MSG(0x158, "Can't load module '%s'\n",
133 modname);
134 }
135 }
136 if (type) {
137 spin_lock(&type->obd_type_lock);
138 type->typ_refcnt++;
139 try_module_get(type->typ_dt_ops->o_owner);
140 spin_unlock(&type->obd_type_lock);
141 }
142 return type;
143}
144EXPORT_SYMBOL(class_get_type);
145
146void class_put_type(struct obd_type *type)
147{
148 LASSERT(type);
149 spin_lock(&type->obd_type_lock);
150 type->typ_refcnt--;
151 module_put(type->typ_dt_ops->o_owner);
152 spin_unlock(&type->obd_type_lock);
153}
154EXPORT_SYMBOL(class_put_type);
155
156#define CLASS_MAX_NAME 1024
157
158int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
159 struct lprocfs_vars *vars, const char *name,
160 struct lu_device_type *ldt)
161{
162 struct obd_type *type;
163 int rc = 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800164
165 /* sanity check */
166 LASSERT(strnlen(name, CLASS_MAX_NAME) < CLASS_MAX_NAME);
167
168 if (class_search_type(name)) {
169 CDEBUG(D_IOCTL, "Type %s already registered\n", name);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800170 return -EEXIST;
Peng Taod7e09d02013-05-02 16:46:55 +0800171 }
172
173 rc = -ENOMEM;
Julia Lawalld7279042015-05-01 17:51:15 +0200174 type = kzalloc(sizeof(*type), GFP_NOFS);
Peng Taod7e09d02013-05-02 16:46:55 +0800175 if (type == NULL)
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800176 return rc;
Peng Taod7e09d02013-05-02 16:46:55 +0800177
Julia Lawalld7279042015-05-01 17:51:15 +0200178 type->typ_dt_ops = kzalloc(sizeof(*type->typ_dt_ops), GFP_NOFS);
179 type->typ_md_ops = kzalloc(sizeof(*type->typ_md_ops), GFP_NOFS);
180 type->typ_name = kzalloc(strlen(name) + 1, GFP_NOFS);
Peng Taod7e09d02013-05-02 16:46:55 +0800181
182 if (type->typ_dt_ops == NULL ||
183 type->typ_md_ops == NULL ||
184 type->typ_name == NULL)
Julia Lawalld212afd2014-09-07 18:18:35 +0200185 goto failed;
Peng Taod7e09d02013-05-02 16:46:55 +0800186
187 *(type->typ_dt_ops) = *dt_ops;
188 /* md_ops is optional */
189 if (md_ops)
190 *(type->typ_md_ops) = *md_ops;
191 strcpy(type->typ_name, name);
192 spin_lock_init(&type->obd_type_lock);
193
Peng Taod7e09d02013-05-02 16:46:55 +0800194 type->typ_procroot = lprocfs_register(type->typ_name, proc_lustre_root,
195 vars, type);
196 if (IS_ERR(type->typ_procroot)) {
197 rc = PTR_ERR(type->typ_procroot);
198 type->typ_procroot = NULL;
Julia Lawalld212afd2014-09-07 18:18:35 +0200199 goto failed;
Peng Taod7e09d02013-05-02 16:46:55 +0800200 }
Peng Tao8cc420d2013-12-03 22:41:59 +0800201
Peng Taod7e09d02013-05-02 16:46:55 +0800202 if (ldt != NULL) {
203 type->typ_lu = ldt;
204 rc = lu_device_type_init(ldt);
205 if (rc != 0)
Julia Lawalld212afd2014-09-07 18:18:35 +0200206 goto failed;
Peng Taod7e09d02013-05-02 16:46:55 +0800207 }
208
209 spin_lock(&obd_types_lock);
210 list_add(&type->typ_chain, &obd_types);
211 spin_unlock(&obd_types_lock);
212
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800213 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800214
215 failed:
Julia Lawallba99a0a2015-05-01 21:37:55 +0200216 kfree(type->typ_name);
217 kfree(type->typ_md_ops);
218 kfree(type->typ_dt_ops);
Julia Lawalld7279042015-05-01 17:51:15 +0200219 kfree(type);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800220 return rc;
Peng Taod7e09d02013-05-02 16:46:55 +0800221}
222EXPORT_SYMBOL(class_register_type);
223
224int class_unregister_type(const char *name)
225{
226 struct obd_type *type = class_search_type(name);
Peng Taod7e09d02013-05-02 16:46:55 +0800227
228 if (!type) {
229 CERROR("unknown obd type\n");
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800230 return -EINVAL;
Peng Taod7e09d02013-05-02 16:46:55 +0800231 }
232
233 if (type->typ_refcnt) {
234 CERROR("type %s has refcount (%d)\n", name, type->typ_refcnt);
235 /* This is a bad situation, let's make the best of it */
236 /* Remove ops, but leave the name for debugging */
Julia Lawalld7279042015-05-01 17:51:15 +0200237 kfree(type->typ_dt_ops);
238 kfree(type->typ_md_ops);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800239 return -EBUSY;
Peng Taod7e09d02013-05-02 16:46:55 +0800240 }
241
Peng Tao73bb1da2013-05-29 21:40:55 +0800242 if (type->typ_procroot) {
243 lprocfs_remove(&type->typ_procroot);
244 }
Peng Taod7e09d02013-05-02 16:46:55 +0800245
246 if (type->typ_lu)
247 lu_device_type_fini(type->typ_lu);
248
249 spin_lock(&obd_types_lock);
250 list_del(&type->typ_chain);
251 spin_unlock(&obd_types_lock);
Julia Lawalld7279042015-05-01 17:51:15 +0200252 kfree(type->typ_name);
Julia Lawallba99a0a2015-05-01 21:37:55 +0200253 kfree(type->typ_dt_ops);
254 kfree(type->typ_md_ops);
Julia Lawalld7279042015-05-01 17:51:15 +0200255 kfree(type);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800256 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800257} /* class_unregister_type */
258EXPORT_SYMBOL(class_unregister_type);
259
260/**
261 * Create a new obd device.
262 *
263 * Find an empty slot in ::obd_devs[], create a new obd device in it.
264 *
265 * \param[in] type_name obd device type string.
266 * \param[in] name obd device name.
267 *
268 * \retval NULL if create fails, otherwise return the obd device
269 * pointer created.
270 */
271struct obd_device *class_newdev(const char *type_name, const char *name)
272{
273 struct obd_device *result = NULL;
274 struct obd_device *newdev;
275 struct obd_type *type = NULL;
276 int i;
277 int new_obd_minor = 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800278
279 if (strlen(name) >= MAX_OBD_NAME) {
280 CERROR("name/uuid must be < %u bytes long\n", MAX_OBD_NAME);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800281 return ERR_PTR(-EINVAL);
Peng Taod7e09d02013-05-02 16:46:55 +0800282 }
283
284 type = class_get_type(type_name);
285 if (type == NULL){
286 CERROR("OBD: unknown type: %s\n", type_name);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800287 return ERR_PTR(-ENODEV);
Peng Taod7e09d02013-05-02 16:46:55 +0800288 }
289
290 newdev = obd_device_alloc();
Julia Lawalld212afd2014-09-07 18:18:35 +0200291 if (newdev == NULL) {
292 result = ERR_PTR(-ENOMEM);
293 goto out_type;
294 }
Peng Taod7e09d02013-05-02 16:46:55 +0800295
296 LASSERT(newdev->obd_magic == OBD_DEVICE_MAGIC);
297
298 write_lock(&obd_dev_lock);
299 for (i = 0; i < class_devno_max(); i++) {
300 struct obd_device *obd = class_num2obd(i);
301
302 if (obd && (strcmp(name, obd->obd_name) == 0)) {
303 CERROR("Device %s already exists at %d, won't add\n",
304 name, i);
305 if (result) {
306 LASSERTF(result->obd_magic == OBD_DEVICE_MAGIC,
307 "%p obd_magic %08x != %08x\n", result,
308 result->obd_magic, OBD_DEVICE_MAGIC);
309 LASSERTF(result->obd_minor == new_obd_minor,
310 "%p obd_minor %d != %d\n", result,
311 result->obd_minor, new_obd_minor);
312
313 obd_devs[result->obd_minor] = NULL;
Greg Donald31e72132014-10-20 11:42:36 -0500314 result->obd_name[0] = '\0';
Peng Taod7e09d02013-05-02 16:46:55 +0800315 }
316 result = ERR_PTR(-EEXIST);
317 break;
318 }
319 if (!result && !obd) {
320 result = newdev;
321 result->obd_minor = i;
322 new_obd_minor = i;
323 result->obd_type = type;
324 strncpy(result->obd_name, name,
325 sizeof(result->obd_name) - 1);
326 obd_devs[i] = result;
327 }
328 }
329 write_unlock(&obd_dev_lock);
330
331 if (result == NULL && i >= class_devno_max()) {
332 CERROR("all %u OBD devices used, increase MAX_OBD_DEVICES\n",
333 class_devno_max());
Julia Lawalld212afd2014-09-07 18:18:35 +0200334 result = ERR_PTR(-EOVERFLOW);
335 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800336 }
337
338 if (IS_ERR(result))
Julia Lawalld212afd2014-09-07 18:18:35 +0200339 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800340
341 CDEBUG(D_IOCTL, "Adding new device %s (%p)\n",
342 result->obd_name, result);
343
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800344 return result;
Peng Taod7e09d02013-05-02 16:46:55 +0800345out:
346 obd_device_free(newdev);
347out_type:
348 class_put_type(type);
349 return result;
350}
351
352void class_release_dev(struct obd_device *obd)
353{
354 struct obd_type *obd_type = obd->obd_type;
355
356 LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "%p obd_magic %08x != %08x\n",
357 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
358 LASSERTF(obd == obd_devs[obd->obd_minor], "obd %p != obd_devs[%d] %p\n",
359 obd, obd->obd_minor, obd_devs[obd->obd_minor]);
360 LASSERT(obd_type != NULL);
361
362 CDEBUG(D_INFO, "Release obd device %s at %d obd_type name =%s\n",
363 obd->obd_name, obd->obd_minor, obd->obd_type->typ_name);
364
365 write_lock(&obd_dev_lock);
366 obd_devs[obd->obd_minor] = NULL;
367 write_unlock(&obd_dev_lock);
368 obd_device_free(obd);
369
370 class_put_type(obd_type);
371}
372
373int class_name2dev(const char *name)
374{
375 int i;
376
377 if (!name)
378 return -1;
379
380 read_lock(&obd_dev_lock);
381 for (i = 0; i < class_devno_max(); i++) {
382 struct obd_device *obd = class_num2obd(i);
383
384 if (obd && strcmp(name, obd->obd_name) == 0) {
385 /* Make sure we finished attaching before we give
386 out any references */
387 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
388 if (obd->obd_attached) {
389 read_unlock(&obd_dev_lock);
390 return i;
391 }
392 break;
393 }
394 }
395 read_unlock(&obd_dev_lock);
396
397 return -1;
398}
399EXPORT_SYMBOL(class_name2dev);
400
401struct obd_device *class_name2obd(const char *name)
402{
403 int dev = class_name2dev(name);
404
405 if (dev < 0 || dev > class_devno_max())
406 return NULL;
407 return class_num2obd(dev);
408}
409EXPORT_SYMBOL(class_name2obd);
410
411int class_uuid2dev(struct obd_uuid *uuid)
412{
413 int i;
414
415 read_lock(&obd_dev_lock);
416 for (i = 0; i < class_devno_max(); i++) {
417 struct obd_device *obd = class_num2obd(i);
418
419 if (obd && obd_uuid_equals(uuid, &obd->obd_uuid)) {
420 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
421 read_unlock(&obd_dev_lock);
422 return i;
423 }
424 }
425 read_unlock(&obd_dev_lock);
426
427 return -1;
428}
429EXPORT_SYMBOL(class_uuid2dev);
430
431struct obd_device *class_uuid2obd(struct obd_uuid *uuid)
432{
433 int dev = class_uuid2dev(uuid);
434 if (dev < 0)
435 return NULL;
436 return class_num2obd(dev);
437}
438EXPORT_SYMBOL(class_uuid2obd);
439
440/**
441 * Get obd device from ::obd_devs[]
442 *
443 * \param num [in] array index
444 *
445 * \retval NULL if ::obd_devs[\a num] does not contains an obd device
446 * otherwise return the obd device there.
447 */
448struct obd_device *class_num2obd(int num)
449{
450 struct obd_device *obd = NULL;
451
452 if (num < class_devno_max()) {
453 obd = obd_devs[num];
454 if (obd == NULL)
455 return NULL;
456
457 LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
458 "%p obd_magic %08x != %08x\n",
459 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
460 LASSERTF(obd->obd_minor == num,
461 "%p obd_minor %0d != %0d\n",
462 obd, obd->obd_minor, num);
463 }
464
465 return obd;
466}
467EXPORT_SYMBOL(class_num2obd);
468
469/**
470 * Get obd devices count. Device in any
471 * state are counted
472 * \retval obd device count
473 */
474int get_devices_count(void)
475{
476 int index, max_index = class_devno_max(), dev_count = 0;
477
478 read_lock(&obd_dev_lock);
479 for (index = 0; index <= max_index; index++) {
480 struct obd_device *obd = class_num2obd(index);
481 if (obd != NULL)
482 dev_count++;
483 }
484 read_unlock(&obd_dev_lock);
485
486 return dev_count;
487}
488EXPORT_SYMBOL(get_devices_count);
489
490void class_obd_list(void)
491{
492 char *status;
493 int i;
494
495 read_lock(&obd_dev_lock);
496 for (i = 0; i < class_devno_max(); i++) {
497 struct obd_device *obd = class_num2obd(i);
498
499 if (obd == NULL)
500 continue;
501 if (obd->obd_stopping)
502 status = "ST";
503 else if (obd->obd_set_up)
504 status = "UP";
505 else if (obd->obd_attached)
506 status = "AT";
507 else
508 status = "--";
509 LCONSOLE(D_CONFIG, "%3d %s %s %s %s %d\n",
510 i, status, obd->obd_type->typ_name,
511 obd->obd_name, obd->obd_uuid.uuid,
512 atomic_read(&obd->obd_refcount));
513 }
514 read_unlock(&obd_dev_lock);
515 return;
516}
517
518/* Search for a client OBD connected to tgt_uuid. If grp_uuid is
519 specified, then only the client with that uuid is returned,
520 otherwise any client connected to the tgt is returned. */
Greg Donald54442612014-10-20 11:18:12 -0500521struct obd_device *class_find_client_obd(struct obd_uuid *tgt_uuid,
522 const char *typ_name,
Peng Taod7e09d02013-05-02 16:46:55 +0800523 struct obd_uuid *grp_uuid)
524{
525 int i;
526
527 read_lock(&obd_dev_lock);
528 for (i = 0; i < class_devno_max(); i++) {
529 struct obd_device *obd = class_num2obd(i);
530
531 if (obd == NULL)
532 continue;
533 if ((strncmp(obd->obd_type->typ_name, typ_name,
534 strlen(typ_name)) == 0)) {
535 if (obd_uuid_equals(tgt_uuid,
536 &obd->u.cli.cl_target_uuid) &&
537 ((grp_uuid)? obd_uuid_equals(grp_uuid,
538 &obd->obd_uuid) : 1)) {
539 read_unlock(&obd_dev_lock);
540 return obd;
541 }
542 }
543 }
544 read_unlock(&obd_dev_lock);
545
546 return NULL;
547}
548EXPORT_SYMBOL(class_find_client_obd);
549
550/* Iterate the obd_device list looking devices have grp_uuid. Start
551 searching at *next, and if a device is found, the next index to look
552 at is saved in *next. If next is NULL, then the first matching device
553 will always be returned. */
Greg Donald54442612014-10-20 11:18:12 -0500554struct obd_device *class_devices_in_group(struct obd_uuid *grp_uuid, int *next)
Peng Taod7e09d02013-05-02 16:46:55 +0800555{
556 int i;
557
558 if (next == NULL)
559 i = 0;
560 else if (*next >= 0 && *next < class_devno_max())
561 i = *next;
562 else
563 return NULL;
564
565 read_lock(&obd_dev_lock);
566 for (; i < class_devno_max(); i++) {
567 struct obd_device *obd = class_num2obd(i);
568
569 if (obd == NULL)
570 continue;
571 if (obd_uuid_equals(grp_uuid, &obd->obd_uuid)) {
572 if (next != NULL)
573 *next = i+1;
574 read_unlock(&obd_dev_lock);
575 return obd;
576 }
577 }
578 read_unlock(&obd_dev_lock);
579
580 return NULL;
581}
582EXPORT_SYMBOL(class_devices_in_group);
583
584/**
585 * to notify sptlrpc log for \a fsname has changed, let every relevant OBD
586 * adjust sptlrpc settings accordingly.
587 */
588int class_notify_sptlrpc_conf(const char *fsname, int namelen)
589{
590 struct obd_device *obd;
591 const char *type;
592 int i, rc = 0, rc2;
593
594 LASSERT(namelen > 0);
595
596 read_lock(&obd_dev_lock);
597 for (i = 0; i < class_devno_max(); i++) {
598 obd = class_num2obd(i);
599
600 if (obd == NULL || obd->obd_set_up == 0 || obd->obd_stopping)
601 continue;
602
603 /* only notify mdc, osc, mdt, ost */
604 type = obd->obd_type->typ_name;
605 if (strcmp(type, LUSTRE_MDC_NAME) != 0 &&
606 strcmp(type, LUSTRE_OSC_NAME) != 0 &&
607 strcmp(type, LUSTRE_MDT_NAME) != 0 &&
608 strcmp(type, LUSTRE_OST_NAME) != 0)
609 continue;
610
611 if (strncmp(obd->obd_name, fsname, namelen))
612 continue;
613
Christoph Jaegerf9bd9c12014-03-28 00:21:07 +0100614 class_incref(obd, __func__, obd);
Peng Taod7e09d02013-05-02 16:46:55 +0800615 read_unlock(&obd_dev_lock);
616 rc2 = obd_set_info_async(NULL, obd->obd_self_export,
617 sizeof(KEY_SPTLRPC_CONF),
618 KEY_SPTLRPC_CONF, 0, NULL, NULL);
619 rc = rc ? rc : rc2;
Christoph Jaegerf9bd9c12014-03-28 00:21:07 +0100620 class_decref(obd, __func__, obd);
Peng Taod7e09d02013-05-02 16:46:55 +0800621 read_lock(&obd_dev_lock);
622 }
623 read_unlock(&obd_dev_lock);
624 return rc;
625}
626EXPORT_SYMBOL(class_notify_sptlrpc_conf);
627
628void obd_cleanup_caches(void)
629{
Peng Taod7e09d02013-05-02 16:46:55 +0800630 if (obd_device_cachep) {
631 kmem_cache_destroy(obd_device_cachep);
632 obd_device_cachep = NULL;
633 }
634 if (obdo_cachep) {
635 kmem_cache_destroy(obdo_cachep);
636 obdo_cachep = NULL;
637 }
638 if (import_cachep) {
639 kmem_cache_destroy(import_cachep);
640 import_cachep = NULL;
641 }
642 if (capa_cachep) {
643 kmem_cache_destroy(capa_cachep);
644 capa_cachep = NULL;
645 }
Peng Taod7e09d02013-05-02 16:46:55 +0800646}
647
648int obd_init_caches(void)
649{
Peng Taod7e09d02013-05-02 16:46:55 +0800650 LASSERT(obd_device_cachep == NULL);
651 obd_device_cachep = kmem_cache_create("ll_obd_dev_cache",
652 sizeof(struct obd_device),
653 0, 0, NULL);
654 if (!obd_device_cachep)
Julia Lawalld212afd2014-09-07 18:18:35 +0200655 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800656
657 LASSERT(obdo_cachep == NULL);
658 obdo_cachep = kmem_cache_create("ll_obdo_cache", sizeof(struct obdo),
659 0, 0, NULL);
660 if (!obdo_cachep)
Julia Lawalld212afd2014-09-07 18:18:35 +0200661 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800662
663 LASSERT(import_cachep == NULL);
664 import_cachep = kmem_cache_create("ll_import_cache",
665 sizeof(struct obd_import),
666 0, 0, NULL);
667 if (!import_cachep)
Julia Lawalld212afd2014-09-07 18:18:35 +0200668 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800669
670 LASSERT(capa_cachep == NULL);
671 capa_cachep = kmem_cache_create("capa_cache",
672 sizeof(struct obd_capa), 0, 0, NULL);
673 if (!capa_cachep)
Julia Lawalld212afd2014-09-07 18:18:35 +0200674 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800675
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800676 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800677 out:
678 obd_cleanup_caches();
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800679 return -ENOMEM;
Peng Taod7e09d02013-05-02 16:46:55 +0800680
681}
682
683/* map connection to client */
684struct obd_export *class_conn2export(struct lustre_handle *conn)
685{
686 struct obd_export *export;
Peng Taod7e09d02013-05-02 16:46:55 +0800687
688 if (!conn) {
689 CDEBUG(D_CACHE, "looking for null handle\n");
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800690 return NULL;
Peng Taod7e09d02013-05-02 16:46:55 +0800691 }
692
693 if (conn->cookie == -1) { /* this means assign a new connection */
694 CDEBUG(D_CACHE, "want a new connection\n");
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800695 return NULL;
Peng Taod7e09d02013-05-02 16:46:55 +0800696 }
697
Greg Kroah-Hartman55f5a822014-07-12 20:26:07 -0700698 CDEBUG(D_INFO, "looking for export cookie %#llx\n", conn->cookie);
Peng Taod7e09d02013-05-02 16:46:55 +0800699 export = class_handle2object(conn->cookie);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800700 return export;
Peng Taod7e09d02013-05-02 16:46:55 +0800701}
702EXPORT_SYMBOL(class_conn2export);
703
704struct obd_device *class_exp2obd(struct obd_export *exp)
705{
706 if (exp)
707 return exp->exp_obd;
708 return NULL;
709}
710EXPORT_SYMBOL(class_exp2obd);
711
712struct obd_device *class_conn2obd(struct lustre_handle *conn)
713{
714 struct obd_export *export;
715 export = class_conn2export(conn);
716 if (export) {
717 struct obd_device *obd = export->exp_obd;
718 class_export_put(export);
719 return obd;
720 }
721 return NULL;
722}
723EXPORT_SYMBOL(class_conn2obd);
724
725struct obd_import *class_exp2cliimp(struct obd_export *exp)
726{
727 struct obd_device *obd = exp->exp_obd;
728 if (obd == NULL)
729 return NULL;
730 return obd->u.cli.cl_import;
731}
732EXPORT_SYMBOL(class_exp2cliimp);
733
734struct obd_import *class_conn2cliimp(struct lustre_handle *conn)
735{
736 struct obd_device *obd = class_conn2obd(conn);
737 if (obd == NULL)
738 return NULL;
739 return obd->u.cli.cl_import;
740}
741EXPORT_SYMBOL(class_conn2cliimp);
742
743/* Export management functions */
744static void class_export_destroy(struct obd_export *exp)
745{
746 struct obd_device *obd = exp->exp_obd;
Peng Taod7e09d02013-05-02 16:46:55 +0800747
748 LASSERT_ATOMIC_ZERO(&exp->exp_refcount);
749 LASSERT(obd != NULL);
750
751 CDEBUG(D_IOCTL, "destroying export %p/%s for %s\n", exp,
752 exp->exp_client_uuid.uuid, obd->obd_name);
753
754 /* "Local" exports (lctl, LOV->{mdc,osc}) have no connection. */
755 if (exp->exp_connection)
756 ptlrpc_put_connection_superhack(exp->exp_connection);
757
758 LASSERT(list_empty(&exp->exp_outstanding_replies));
759 LASSERT(list_empty(&exp->exp_uncommitted_replies));
760 LASSERT(list_empty(&exp->exp_req_replay_queue));
761 LASSERT(list_empty(&exp->exp_hp_rpcs));
762 obd_destroy_export(exp);
763 class_decref(obd, "export", exp);
764
765 OBD_FREE_RCU(exp, sizeof(*exp), &exp->exp_handle);
Peng Taod7e09d02013-05-02 16:46:55 +0800766}
767
768static void export_handle_addref(void *export)
769{
770 class_export_get(export);
771}
772
773static struct portals_handle_ops export_handle_ops = {
774 .hop_addref = export_handle_addref,
775 .hop_free = NULL,
776};
777
778struct obd_export *class_export_get(struct obd_export *exp)
779{
780 atomic_inc(&exp->exp_refcount);
781 CDEBUG(D_INFO, "GETting export %p : new refcount %d\n", exp,
782 atomic_read(&exp->exp_refcount));
783 return exp;
784}
785EXPORT_SYMBOL(class_export_get);
786
787void class_export_put(struct obd_export *exp)
788{
789 LASSERT(exp != NULL);
790 LASSERT_ATOMIC_GT_LT(&exp->exp_refcount, 0, LI_POISON);
791 CDEBUG(D_INFO, "PUTting export %p : new refcount %d\n", exp,
792 atomic_read(&exp->exp_refcount) - 1);
793
794 if (atomic_dec_and_test(&exp->exp_refcount)) {
795 LASSERT(!list_empty(&exp->exp_obd_chain));
796 CDEBUG(D_IOCTL, "final put %p/%s\n",
797 exp, exp->exp_client_uuid.uuid);
798
799 /* release nid stat refererence */
800 lprocfs_exp_cleanup(exp);
801
802 obd_zombie_export_add(exp);
803 }
804}
805EXPORT_SYMBOL(class_export_put);
806
807/* Creates a new export, adds it to the hash table, and returns a
808 * pointer to it. The refcount is 2: one for the hash reference, and
809 * one for the pointer returned by this function. */
810struct obd_export *class_new_export(struct obd_device *obd,
811 struct obd_uuid *cluuid)
812{
813 struct obd_export *export;
Lisa Nguyen6da6eab2013-10-21 18:16:26 -0700814 struct cfs_hash *hash = NULL;
Peng Taod7e09d02013-05-02 16:46:55 +0800815 int rc = 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800816
Julia Lawalld7279042015-05-01 17:51:15 +0200817 export = kzalloc(sizeof(*export), GFP_NOFS);
Peng Taod7e09d02013-05-02 16:46:55 +0800818 if (!export)
819 return ERR_PTR(-ENOMEM);
820
821 export->exp_conn_cnt = 0;
822 export->exp_lock_hash = NULL;
823 export->exp_flock_hash = NULL;
824 atomic_set(&export->exp_refcount, 2);
825 atomic_set(&export->exp_rpc_count, 0);
826 atomic_set(&export->exp_cb_count, 0);
827 atomic_set(&export->exp_locks_count, 0);
828#if LUSTRE_TRACKS_LOCK_EXP_REFS
829 INIT_LIST_HEAD(&export->exp_locks_list);
830 spin_lock_init(&export->exp_locks_list_guard);
831#endif
832 atomic_set(&export->exp_replay_count, 0);
833 export->exp_obd = obd;
834 INIT_LIST_HEAD(&export->exp_outstanding_replies);
835 spin_lock_init(&export->exp_uncommitted_replies_lock);
836 INIT_LIST_HEAD(&export->exp_uncommitted_replies);
837 INIT_LIST_HEAD(&export->exp_req_replay_queue);
838 INIT_LIST_HEAD(&export->exp_handle.h_link);
839 INIT_LIST_HEAD(&export->exp_hp_rpcs);
840 class_handle_hash(&export->exp_handle, &export_handle_ops);
Greg Kroah-Hartman7264b8a2014-07-12 00:38:48 -0700841 export->exp_last_request_time = get_seconds();
Peng Taod7e09d02013-05-02 16:46:55 +0800842 spin_lock_init(&export->exp_lock);
843 spin_lock_init(&export->exp_rpc_lock);
844 INIT_HLIST_NODE(&export->exp_uuid_hash);
845 INIT_HLIST_NODE(&export->exp_nid_hash);
846 spin_lock_init(&export->exp_bl_list_lock);
847 INIT_LIST_HEAD(&export->exp_bl_list);
848
849 export->exp_sp_peer = LUSTRE_SP_ANY;
850 export->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
851 export->exp_client_uuid = *cluuid;
852 obd_init_export(export);
853
854 spin_lock(&obd->obd_dev_lock);
855 /* shouldn't happen, but might race */
Julia Lawalld212afd2014-09-07 18:18:35 +0200856 if (obd->obd_stopping) {
857 rc = -ENODEV;
858 goto exit_unlock;
859 }
Peng Taod7e09d02013-05-02 16:46:55 +0800860
861 hash = cfs_hash_getref(obd->obd_uuid_hash);
Julia Lawalld212afd2014-09-07 18:18:35 +0200862 if (hash == NULL) {
863 rc = -ENODEV;
864 goto exit_unlock;
865 }
Peng Taod7e09d02013-05-02 16:46:55 +0800866 spin_unlock(&obd->obd_dev_lock);
867
868 if (!obd_uuid_equals(cluuid, &obd->obd_uuid)) {
869 rc = cfs_hash_add_unique(hash, cluuid, &export->exp_uuid_hash);
870 if (rc != 0) {
871 LCONSOLE_WARN("%s: denying duplicate export for %s, %d\n",
872 obd->obd_name, cluuid->uuid, rc);
Julia Lawalld212afd2014-09-07 18:18:35 +0200873 rc = -EALREADY;
874 goto exit_err;
Peng Taod7e09d02013-05-02 16:46:55 +0800875 }
876 }
877
878 spin_lock(&obd->obd_dev_lock);
879 if (obd->obd_stopping) {
880 cfs_hash_del(hash, cluuid, &export->exp_uuid_hash);
Julia Lawalld212afd2014-09-07 18:18:35 +0200881 rc = -ENODEV;
882 goto exit_unlock;
Peng Taod7e09d02013-05-02 16:46:55 +0800883 }
884
885 class_incref(obd, "export", export);
886 list_add(&export->exp_obd_chain, &export->exp_obd->obd_exports);
887 list_add_tail(&export->exp_obd_chain_timed,
888 &export->exp_obd->obd_exports_timed);
889 export->exp_obd->obd_num_exports++;
890 spin_unlock(&obd->obd_dev_lock);
891 cfs_hash_putref(hash);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800892 return export;
Peng Taod7e09d02013-05-02 16:46:55 +0800893
894exit_unlock:
895 spin_unlock(&obd->obd_dev_lock);
896exit_err:
897 if (hash)
898 cfs_hash_putref(hash);
899 class_handle_unhash(&export->exp_handle);
900 LASSERT(hlist_unhashed(&export->exp_uuid_hash));
901 obd_destroy_export(export);
Julia Lawalld7279042015-05-01 17:51:15 +0200902 kfree(export);
Peng Taod7e09d02013-05-02 16:46:55 +0800903 return ERR_PTR(rc);
904}
905EXPORT_SYMBOL(class_new_export);
906
907void class_unlink_export(struct obd_export *exp)
908{
909 class_handle_unhash(&exp->exp_handle);
910
911 spin_lock(&exp->exp_obd->obd_dev_lock);
912 /* delete an uuid-export hashitem from hashtables */
913 if (!hlist_unhashed(&exp->exp_uuid_hash))
914 cfs_hash_del(exp->exp_obd->obd_uuid_hash,
915 &exp->exp_client_uuid,
916 &exp->exp_uuid_hash);
917
918 list_move(&exp->exp_obd_chain, &exp->exp_obd->obd_unlinked_exports);
919 list_del_init(&exp->exp_obd_chain_timed);
920 exp->exp_obd->obd_num_exports--;
921 spin_unlock(&exp->exp_obd->obd_dev_lock);
922 class_export_put(exp);
923}
924EXPORT_SYMBOL(class_unlink_export);
925
926/* Import management functions */
Haneen Mohammed052c5292015-03-21 10:51:42 +0300927static void class_import_destroy(struct obd_import *imp)
Peng Taod7e09d02013-05-02 16:46:55 +0800928{
Peng Taod7e09d02013-05-02 16:46:55 +0800929 CDEBUG(D_IOCTL, "destroying import %p for %s\n", imp,
930 imp->imp_obd->obd_name);
931
932 LASSERT_ATOMIC_ZERO(&imp->imp_refcount);
933
934 ptlrpc_put_connection_superhack(imp->imp_connection);
935
936 while (!list_empty(&imp->imp_conn_list)) {
937 struct obd_import_conn *imp_conn;
938
939 imp_conn = list_entry(imp->imp_conn_list.next,
940 struct obd_import_conn, oic_item);
941 list_del_init(&imp_conn->oic_item);
942 ptlrpc_put_connection_superhack(imp_conn->oic_conn);
Julia Lawalld7279042015-05-01 17:51:15 +0200943 kfree(imp_conn);
Peng Taod7e09d02013-05-02 16:46:55 +0800944 }
945
946 LASSERT(imp->imp_sec == NULL);
947 class_decref(imp->imp_obd, "import", imp);
948 OBD_FREE_RCU(imp, sizeof(*imp), &imp->imp_handle);
Peng Taod7e09d02013-05-02 16:46:55 +0800949}
950
951static void import_handle_addref(void *import)
952{
953 class_import_get(import);
954}
955
956static struct portals_handle_ops import_handle_ops = {
957 .hop_addref = import_handle_addref,
958 .hop_free = NULL,
959};
960
961struct obd_import *class_import_get(struct obd_import *import)
962{
963 atomic_inc(&import->imp_refcount);
964 CDEBUG(D_INFO, "import %p refcount=%d obd=%s\n", import,
965 atomic_read(&import->imp_refcount),
966 import->imp_obd->obd_name);
967 return import;
968}
969EXPORT_SYMBOL(class_import_get);
970
971void class_import_put(struct obd_import *imp)
972{
Peng Taod7e09d02013-05-02 16:46:55 +0800973 LASSERT(list_empty(&imp->imp_zombie_chain));
974 LASSERT_ATOMIC_GT_LT(&imp->imp_refcount, 0, LI_POISON);
975
976 CDEBUG(D_INFO, "import %p refcount=%d obd=%s\n", imp,
977 atomic_read(&imp->imp_refcount) - 1,
978 imp->imp_obd->obd_name);
979
980 if (atomic_dec_and_test(&imp->imp_refcount)) {
981 CDEBUG(D_INFO, "final put import %p\n", imp);
982 obd_zombie_import_add(imp);
983 }
984
985 /* catch possible import put race */
986 LASSERT_ATOMIC_GE_LT(&imp->imp_refcount, 0, LI_POISON);
Peng Taod7e09d02013-05-02 16:46:55 +0800987}
988EXPORT_SYMBOL(class_import_put);
989
990static void init_imp_at(struct imp_at *at) {
991 int i;
992 at_init(&at->iat_net_latency, 0, 0);
993 for (i = 0; i < IMP_AT_MAX_PORTALS; i++) {
994 /* max service estimates are tracked on the server side, so
995 don't use the AT history here, just use the last reported
996 val. (But keep hist for proc histogram, worst_ever) */
997 at_init(&at->iat_service_estimate[i], INITIAL_CONNECT_TIMEOUT,
998 AT_FLG_NOHIST);
999 }
1000}
1001
1002struct obd_import *class_new_import(struct obd_device *obd)
1003{
1004 struct obd_import *imp;
1005
Julia Lawalld7279042015-05-01 17:51:15 +02001006 imp = kzalloc(sizeof(*imp), GFP_NOFS);
Peng Taod7e09d02013-05-02 16:46:55 +08001007 if (imp == NULL)
1008 return NULL;
1009
1010 INIT_LIST_HEAD(&imp->imp_pinger_chain);
1011 INIT_LIST_HEAD(&imp->imp_zombie_chain);
1012 INIT_LIST_HEAD(&imp->imp_replay_list);
1013 INIT_LIST_HEAD(&imp->imp_sending_list);
1014 INIT_LIST_HEAD(&imp->imp_delayed_list);
Hongchao Zhang63d42572014-02-28 21:16:37 -05001015 INIT_LIST_HEAD(&imp->imp_committed_list);
1016 imp->imp_replay_cursor = &imp->imp_committed_list;
Peng Taod7e09d02013-05-02 16:46:55 +08001017 spin_lock_init(&imp->imp_lock);
1018 imp->imp_last_success_conn = 0;
1019 imp->imp_state = LUSTRE_IMP_NEW;
1020 imp->imp_obd = class_incref(obd, "import", imp);
1021 mutex_init(&imp->imp_sec_mutex);
1022 init_waitqueue_head(&imp->imp_recovery_waitq);
1023
1024 atomic_set(&imp->imp_refcount, 2);
1025 atomic_set(&imp->imp_unregistering, 0);
1026 atomic_set(&imp->imp_inflight, 0);
1027 atomic_set(&imp->imp_replay_inflight, 0);
1028 atomic_set(&imp->imp_inval_count, 0);
1029 INIT_LIST_HEAD(&imp->imp_conn_list);
1030 INIT_LIST_HEAD(&imp->imp_handle.h_link);
1031 class_handle_hash(&imp->imp_handle, &import_handle_ops);
1032 init_imp_at(&imp->imp_at);
1033
1034 /* the default magic is V2, will be used in connect RPC, and
1035 * then adjusted according to the flags in request/reply. */
1036 imp->imp_msg_magic = LUSTRE_MSG_MAGIC_V2;
1037
1038 return imp;
1039}
1040EXPORT_SYMBOL(class_new_import);
1041
1042void class_destroy_import(struct obd_import *import)
1043{
1044 LASSERT(import != NULL);
1045 LASSERT(import != LP_POISON);
1046
1047 class_handle_unhash(&import->imp_handle);
1048
1049 spin_lock(&import->imp_lock);
1050 import->imp_generation++;
1051 spin_unlock(&import->imp_lock);
1052 class_import_put(import);
1053}
1054EXPORT_SYMBOL(class_destroy_import);
1055
1056#if LUSTRE_TRACKS_LOCK_EXP_REFS
1057
1058void __class_export_add_lock_ref(struct obd_export *exp, struct ldlm_lock *lock)
1059{
1060 spin_lock(&exp->exp_locks_list_guard);
1061
1062 LASSERT(lock->l_exp_refs_nr >= 0);
1063
1064 if (lock->l_exp_refs_target != NULL &&
1065 lock->l_exp_refs_target != exp) {
1066 LCONSOLE_WARN("setting export %p for lock %p which already has export %p\n",
1067 exp, lock, lock->l_exp_refs_target);
1068 }
1069 if ((lock->l_exp_refs_nr ++) == 0) {
1070 list_add(&lock->l_exp_refs_link, &exp->exp_locks_list);
1071 lock->l_exp_refs_target = exp;
1072 }
1073 CDEBUG(D_INFO, "lock = %p, export = %p, refs = %u\n",
1074 lock, exp, lock->l_exp_refs_nr);
1075 spin_unlock(&exp->exp_locks_list_guard);
1076}
1077EXPORT_SYMBOL(__class_export_add_lock_ref);
1078
1079void __class_export_del_lock_ref(struct obd_export *exp, struct ldlm_lock *lock)
1080{
1081 spin_lock(&exp->exp_locks_list_guard);
1082 LASSERT(lock->l_exp_refs_nr > 0);
1083 if (lock->l_exp_refs_target != exp) {
Joe Perches2d00bd12014-11-23 11:28:50 -08001084 LCONSOLE_WARN("lock %p, mismatching export pointers: %p, %p\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001085 lock, lock->l_exp_refs_target, exp);
1086 }
1087 if (-- lock->l_exp_refs_nr == 0) {
1088 list_del_init(&lock->l_exp_refs_link);
1089 lock->l_exp_refs_target = NULL;
1090 }
1091 CDEBUG(D_INFO, "lock = %p, export = %p, refs = %u\n",
1092 lock, exp, lock->l_exp_refs_nr);
1093 spin_unlock(&exp->exp_locks_list_guard);
1094}
1095EXPORT_SYMBOL(__class_export_del_lock_ref);
1096#endif
1097
1098/* A connection defines an export context in which preallocation can
1099 be managed. This releases the export pointer reference, and returns
1100 the export handle, so the export refcount is 1 when this function
1101 returns. */
1102int class_connect(struct lustre_handle *conn, struct obd_device *obd,
1103 struct obd_uuid *cluuid)
1104{
1105 struct obd_export *export;
1106 LASSERT(conn != NULL);
1107 LASSERT(obd != NULL);
1108 LASSERT(cluuid != NULL);
Peng Taod7e09d02013-05-02 16:46:55 +08001109
1110 export = class_new_export(obd, cluuid);
1111 if (IS_ERR(export))
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001112 return PTR_ERR(export);
Peng Taod7e09d02013-05-02 16:46:55 +08001113
1114 conn->cookie = export->exp_handle.h_cookie;
1115 class_export_put(export);
1116
Greg Kroah-Hartman55f5a822014-07-12 20:26:07 -07001117 CDEBUG(D_IOCTL, "connect: client %s, cookie %#llx\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001118 cluuid->uuid, conn->cookie);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001119 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001120}
1121EXPORT_SYMBOL(class_connect);
1122
1123/* if export is involved in recovery then clean up related things */
Haneen Mohammed052c5292015-03-21 10:51:42 +03001124static void class_export_recovery_cleanup(struct obd_export *exp)
Peng Taod7e09d02013-05-02 16:46:55 +08001125{
1126 struct obd_device *obd = exp->exp_obd;
1127
1128 spin_lock(&obd->obd_recovery_task_lock);
1129 if (exp->exp_delayed)
1130 obd->obd_delayed_clients--;
1131 if (obd->obd_recovering) {
1132 if (exp->exp_in_recovery) {
1133 spin_lock(&exp->exp_lock);
1134 exp->exp_in_recovery = 0;
1135 spin_unlock(&exp->exp_lock);
1136 LASSERT_ATOMIC_POS(&obd->obd_connected_clients);
1137 atomic_dec(&obd->obd_connected_clients);
1138 }
1139
1140 /* if called during recovery then should update
1141 * obd_stale_clients counter,
1142 * lightweight exports are not counted */
1143 if (exp->exp_failed &&
1144 (exp_connect_flags(exp) & OBD_CONNECT_LIGHTWEIGHT) == 0)
1145 exp->exp_obd->obd_stale_clients++;
1146 }
1147 spin_unlock(&obd->obd_recovery_task_lock);
Hongchao Zhang62e49412015-02-01 21:52:04 -05001148
1149 spin_lock(&exp->exp_lock);
Peng Taod7e09d02013-05-02 16:46:55 +08001150 /** Cleanup req replay fields */
1151 if (exp->exp_req_replay_needed) {
Peng Taod7e09d02013-05-02 16:46:55 +08001152 exp->exp_req_replay_needed = 0;
Hongchao Zhang62e49412015-02-01 21:52:04 -05001153
Peng Taod7e09d02013-05-02 16:46:55 +08001154 LASSERT(atomic_read(&obd->obd_req_replay_clients));
1155 atomic_dec(&obd->obd_req_replay_clients);
1156 }
Hongchao Zhang62e49412015-02-01 21:52:04 -05001157
Peng Taod7e09d02013-05-02 16:46:55 +08001158 /** Cleanup lock replay data */
1159 if (exp->exp_lock_replay_needed) {
Peng Taod7e09d02013-05-02 16:46:55 +08001160 exp->exp_lock_replay_needed = 0;
Hongchao Zhang62e49412015-02-01 21:52:04 -05001161
Peng Taod7e09d02013-05-02 16:46:55 +08001162 LASSERT(atomic_read(&obd->obd_lock_replay_clients));
1163 atomic_dec(&obd->obd_lock_replay_clients);
1164 }
Hongchao Zhang62e49412015-02-01 21:52:04 -05001165 spin_unlock(&exp->exp_lock);
Peng Taod7e09d02013-05-02 16:46:55 +08001166}
1167
1168/* This function removes 1-3 references from the export:
1169 * 1 - for export pointer passed
1170 * and if disconnect really need
1171 * 2 - removing from hash
1172 * 3 - in client_unlink_export
1173 * The export pointer passed to this function can destroyed */
1174int class_disconnect(struct obd_export *export)
1175{
1176 int already_disconnected;
Peng Taod7e09d02013-05-02 16:46:55 +08001177
1178 if (export == NULL) {
1179 CWARN("attempting to free NULL export %p\n", export);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001180 return -EINVAL;
Peng Taod7e09d02013-05-02 16:46:55 +08001181 }
1182
1183 spin_lock(&export->exp_lock);
1184 already_disconnected = export->exp_disconnected;
1185 export->exp_disconnected = 1;
1186 spin_unlock(&export->exp_lock);
1187
1188 /* class_cleanup(), abort_recovery(), and class_fail_export()
1189 * all end up in here, and if any of them race we shouldn't
1190 * call extra class_export_puts(). */
1191 if (already_disconnected) {
1192 LASSERT(hlist_unhashed(&export->exp_nid_hash));
Julia Lawalld212afd2014-09-07 18:18:35 +02001193 goto no_disconn;
Peng Taod7e09d02013-05-02 16:46:55 +08001194 }
1195
Greg Kroah-Hartman55f5a822014-07-12 20:26:07 -07001196 CDEBUG(D_IOCTL, "disconnect: cookie %#llx\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001197 export->exp_handle.h_cookie);
1198
1199 if (!hlist_unhashed(&export->exp_nid_hash))
1200 cfs_hash_del(export->exp_obd->obd_nid_hash,
1201 &export->exp_connection->c_peer.nid,
1202 &export->exp_nid_hash);
1203
1204 class_export_recovery_cleanup(export);
1205 class_unlink_export(export);
1206no_disconn:
1207 class_export_put(export);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001208 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001209}
1210EXPORT_SYMBOL(class_disconnect);
1211
1212/* Return non-zero for a fully connected export */
1213int class_connected_export(struct obd_export *exp)
1214{
1215 if (exp) {
1216 int connected;
1217 spin_lock(&exp->exp_lock);
Haneen Mohammedb6ee3822015-03-13 20:48:53 +03001218 connected = exp->exp_conn_cnt > 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001219 spin_unlock(&exp->exp_lock);
1220 return connected;
1221 }
1222 return 0;
1223}
1224EXPORT_SYMBOL(class_connected_export);
1225
1226static void class_disconnect_export_list(struct list_head *list,
1227 enum obd_option flags)
1228{
1229 int rc;
1230 struct obd_export *exp;
Peng Taod7e09d02013-05-02 16:46:55 +08001231
1232 /* It's possible that an export may disconnect itself, but
1233 * nothing else will be added to this list. */
1234 while (!list_empty(list)) {
1235 exp = list_entry(list->next, struct obd_export,
1236 exp_obd_chain);
1237 /* need for safe call CDEBUG after obd_disconnect */
1238 class_export_get(exp);
1239
1240 spin_lock(&exp->exp_lock);
1241 exp->exp_flags = flags;
1242 spin_unlock(&exp->exp_lock);
1243
1244 if (obd_uuid_equals(&exp->exp_client_uuid,
1245 &exp->exp_obd->obd_uuid)) {
1246 CDEBUG(D_HA,
1247 "exp %p export uuid == obd uuid, don't discon\n",
1248 exp);
1249 /* Need to delete this now so we don't end up pointing
1250 * to work_list later when this export is cleaned up. */
1251 list_del_init(&exp->exp_obd_chain);
1252 class_export_put(exp);
1253 continue;
1254 }
1255
1256 class_export_get(exp);
Joe Perches2d00bd12014-11-23 11:28:50 -08001257 CDEBUG(D_HA, "%s: disconnecting export at %s (%p), last request at " CFS_TIME_T "\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001258 exp->exp_obd->obd_name, obd_export_nid2str(exp),
1259 exp, exp->exp_last_request_time);
1260 /* release one export reference anyway */
1261 rc = obd_disconnect(exp);
1262
1263 CDEBUG(D_HA, "disconnected export at %s (%p): rc %d\n",
1264 obd_export_nid2str(exp), exp, rc);
1265 class_export_put(exp);
1266 }
Peng Taod7e09d02013-05-02 16:46:55 +08001267}
1268
1269void class_disconnect_exports(struct obd_device *obd)
1270{
1271 struct list_head work_list;
Peng Taod7e09d02013-05-02 16:46:55 +08001272
1273 /* Move all of the exports from obd_exports to a work list, en masse. */
1274 INIT_LIST_HEAD(&work_list);
1275 spin_lock(&obd->obd_dev_lock);
1276 list_splice_init(&obd->obd_exports, &work_list);
1277 list_splice_init(&obd->obd_delayed_exports, &work_list);
1278 spin_unlock(&obd->obd_dev_lock);
1279
1280 if (!list_empty(&work_list)) {
Joe Perches2d00bd12014-11-23 11:28:50 -08001281 CDEBUG(D_HA, "OBD device %d (%p) has exports, disconnecting them\n",
1282 obd->obd_minor, obd);
Peng Taod7e09d02013-05-02 16:46:55 +08001283 class_disconnect_export_list(&work_list,
1284 exp_flags_from_obd(obd));
1285 } else
1286 CDEBUG(D_HA, "OBD device %d (%p) has no exports\n",
1287 obd->obd_minor, obd);
Peng Taod7e09d02013-05-02 16:46:55 +08001288}
1289EXPORT_SYMBOL(class_disconnect_exports);
1290
1291/* Remove exports that have not completed recovery.
1292 */
1293void class_disconnect_stale_exports(struct obd_device *obd,
1294 int (*test_export)(struct obd_export *))
1295{
1296 struct list_head work_list;
1297 struct obd_export *exp, *n;
1298 int evicted = 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001299
1300 INIT_LIST_HEAD(&work_list);
1301 spin_lock(&obd->obd_dev_lock);
1302 list_for_each_entry_safe(exp, n, &obd->obd_exports,
1303 exp_obd_chain) {
1304 /* don't count self-export as client */
1305 if (obd_uuid_equals(&exp->exp_client_uuid,
1306 &exp->exp_obd->obd_uuid))
1307 continue;
1308
1309 /* don't evict clients which have no slot in last_rcvd
1310 * (e.g. lightweight connection) */
1311 if (exp->exp_target_data.ted_lr_idx == -1)
1312 continue;
1313
1314 spin_lock(&exp->exp_lock);
1315 if (exp->exp_failed || test_export(exp)) {
1316 spin_unlock(&exp->exp_lock);
1317 continue;
1318 }
1319 exp->exp_failed = 1;
1320 spin_unlock(&exp->exp_lock);
1321
1322 list_move(&exp->exp_obd_chain, &work_list);
1323 evicted++;
1324 CDEBUG(D_HA, "%s: disconnect stale client %s@%s\n",
1325 obd->obd_name, exp->exp_client_uuid.uuid,
1326 exp->exp_connection == NULL ? "<unknown>" :
1327 libcfs_nid2str(exp->exp_connection->c_peer.nid));
1328 print_export_data(exp, "EVICTING", 0);
1329 }
1330 spin_unlock(&obd->obd_dev_lock);
1331
1332 if (evicted)
1333 LCONSOLE_WARN("%s: disconnecting %d stale clients\n",
1334 obd->obd_name, evicted);
1335
1336 class_disconnect_export_list(&work_list, exp_flags_from_obd(obd) |
1337 OBD_OPT_ABORT_RECOV);
Peng Taod7e09d02013-05-02 16:46:55 +08001338}
1339EXPORT_SYMBOL(class_disconnect_stale_exports);
1340
1341void class_fail_export(struct obd_export *exp)
1342{
1343 int rc, already_failed;
1344
1345 spin_lock(&exp->exp_lock);
1346 already_failed = exp->exp_failed;
1347 exp->exp_failed = 1;
1348 spin_unlock(&exp->exp_lock);
1349
1350 if (already_failed) {
1351 CDEBUG(D_HA, "disconnecting dead export %p/%s; skipping\n",
1352 exp, exp->exp_client_uuid.uuid);
1353 return;
1354 }
1355
1356 CDEBUG(D_HA, "disconnecting export %p/%s\n",
1357 exp, exp->exp_client_uuid.uuid);
1358
1359 if (obd_dump_on_timeout)
1360 libcfs_debug_dumplog();
1361
1362 /* need for safe call CDEBUG after obd_disconnect */
1363 class_export_get(exp);
1364
1365 /* Most callers into obd_disconnect are removing their own reference
1366 * (request, for example) in addition to the one from the hash table.
1367 * We don't have such a reference here, so make one. */
1368 class_export_get(exp);
1369 rc = obd_disconnect(exp);
1370 if (rc)
1371 CERROR("disconnecting export %p failed: %d\n", exp, rc);
1372 else
1373 CDEBUG(D_HA, "disconnected export %p/%s\n",
1374 exp, exp->exp_client_uuid.uuid);
1375 class_export_put(exp);
1376}
1377EXPORT_SYMBOL(class_fail_export);
1378
1379char *obd_export_nid2str(struct obd_export *exp)
1380{
1381 if (exp->exp_connection != NULL)
1382 return libcfs_nid2str(exp->exp_connection->c_peer.nid);
1383
1384 return "(no nid)";
1385}
1386EXPORT_SYMBOL(obd_export_nid2str);
1387
1388int obd_export_evict_by_nid(struct obd_device *obd, const char *nid)
1389{
Lisa Nguyen6da6eab2013-10-21 18:16:26 -07001390 struct cfs_hash *nid_hash;
Peng Taod7e09d02013-05-02 16:46:55 +08001391 struct obd_export *doomed_exp = NULL;
1392 int exports_evicted = 0;
1393
1394 lnet_nid_t nid_key = libcfs_str2nid((char *)nid);
1395
1396 spin_lock(&obd->obd_dev_lock);
1397 /* umount has run already, so evict thread should leave
1398 * its task to umount thread now */
1399 if (obd->obd_stopping) {
1400 spin_unlock(&obd->obd_dev_lock);
1401 return exports_evicted;
1402 }
1403 nid_hash = obd->obd_nid_hash;
1404 cfs_hash_getref(nid_hash);
1405 spin_unlock(&obd->obd_dev_lock);
1406
1407 do {
1408 doomed_exp = cfs_hash_lookup(nid_hash, &nid_key);
1409 if (doomed_exp == NULL)
1410 break;
1411
1412 LASSERTF(doomed_exp->exp_connection->c_peer.nid == nid_key,
1413 "nid %s found, wanted nid %s, requested nid %s\n",
1414 obd_export_nid2str(doomed_exp),
1415 libcfs_nid2str(nid_key), nid);
1416 LASSERTF(doomed_exp != obd->obd_self_export,
1417 "self-export is hashed by NID?\n");
1418 exports_evicted++;
Joe Perches2d00bd12014-11-23 11:28:50 -08001419 LCONSOLE_WARN("%s: evicting %s (at %s) by administrative request\n",
1420 obd->obd_name,
Peng Taod7e09d02013-05-02 16:46:55 +08001421 obd_uuid2str(&doomed_exp->exp_client_uuid),
1422 obd_export_nid2str(doomed_exp));
1423 class_fail_export(doomed_exp);
1424 class_export_put(doomed_exp);
1425 } while (1);
1426
1427 cfs_hash_putref(nid_hash);
1428
1429 if (!exports_evicted)
Greg Donald1d8cb702014-08-25 20:07:19 -05001430 CDEBUG(D_HA,
1431 "%s: can't disconnect NID '%s': no exports found\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001432 obd->obd_name, nid);
1433 return exports_evicted;
1434}
1435EXPORT_SYMBOL(obd_export_evict_by_nid);
1436
1437int obd_export_evict_by_uuid(struct obd_device *obd, const char *uuid)
1438{
Lisa Nguyen6da6eab2013-10-21 18:16:26 -07001439 struct cfs_hash *uuid_hash;
Peng Taod7e09d02013-05-02 16:46:55 +08001440 struct obd_export *doomed_exp = NULL;
1441 struct obd_uuid doomed_uuid;
1442 int exports_evicted = 0;
1443
1444 spin_lock(&obd->obd_dev_lock);
1445 if (obd->obd_stopping) {
1446 spin_unlock(&obd->obd_dev_lock);
1447 return exports_evicted;
1448 }
1449 uuid_hash = obd->obd_uuid_hash;
1450 cfs_hash_getref(uuid_hash);
1451 spin_unlock(&obd->obd_dev_lock);
1452
1453 obd_str2uuid(&doomed_uuid, uuid);
1454 if (obd_uuid_equals(&doomed_uuid, &obd->obd_uuid)) {
1455 CERROR("%s: can't evict myself\n", obd->obd_name);
1456 cfs_hash_putref(uuid_hash);
1457 return exports_evicted;
1458 }
1459
1460 doomed_exp = cfs_hash_lookup(uuid_hash, &doomed_uuid);
1461
1462 if (doomed_exp == NULL) {
1463 CERROR("%s: can't disconnect %s: no exports found\n",
1464 obd->obd_name, uuid);
1465 } else {
Masanari Iidac4f395532013-07-21 03:38:08 +09001466 CWARN("%s: evicting %s at administrative request\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001467 obd->obd_name, doomed_exp->exp_client_uuid.uuid);
1468 class_fail_export(doomed_exp);
1469 class_export_put(doomed_exp);
1470 exports_evicted++;
1471 }
1472 cfs_hash_putref(uuid_hash);
1473
1474 return exports_evicted;
1475}
1476EXPORT_SYMBOL(obd_export_evict_by_uuid);
1477
1478#if LUSTRE_TRACKS_LOCK_EXP_REFS
1479void (*class_export_dump_hook)(struct obd_export*) = NULL;
1480EXPORT_SYMBOL(class_export_dump_hook);
1481#endif
1482
1483static void print_export_data(struct obd_export *exp, const char *status,
1484 int locks)
1485{
1486 struct ptlrpc_reply_state *rs;
1487 struct ptlrpc_reply_state *first_reply = NULL;
1488 int nreplies = 0;
1489
1490 spin_lock(&exp->exp_lock);
1491 list_for_each_entry(rs, &exp->exp_outstanding_replies,
1492 rs_exp_list) {
1493 if (nreplies == 0)
1494 first_reply = rs;
1495 nreplies++;
1496 }
1497 spin_unlock(&exp->exp_lock);
1498
Greg Kroah-Hartmanb0f5aad2014-07-12 20:06:04 -07001499 CDEBUG(D_HA, "%s: %s %p %s %s %d (%d %d %d) %d %d %d %d: %p %s %llu\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001500 exp->exp_obd->obd_name, status, exp, exp->exp_client_uuid.uuid,
1501 obd_export_nid2str(exp), atomic_read(&exp->exp_refcount),
1502 atomic_read(&exp->exp_rpc_count),
1503 atomic_read(&exp->exp_cb_count),
1504 atomic_read(&exp->exp_locks_count),
1505 exp->exp_disconnected, exp->exp_delayed, exp->exp_failed,
1506 nreplies, first_reply, nreplies > 3 ? "..." : "",
1507 exp->exp_last_committed);
1508#if LUSTRE_TRACKS_LOCK_EXP_REFS
1509 if (locks && class_export_dump_hook != NULL)
1510 class_export_dump_hook(exp);
1511#endif
1512}
1513
1514void dump_exports(struct obd_device *obd, int locks)
1515{
1516 struct obd_export *exp;
1517
1518 spin_lock(&obd->obd_dev_lock);
1519 list_for_each_entry(exp, &obd->obd_exports, exp_obd_chain)
1520 print_export_data(exp, "ACTIVE", locks);
1521 list_for_each_entry(exp, &obd->obd_unlinked_exports, exp_obd_chain)
1522 print_export_data(exp, "UNLINKED", locks);
1523 list_for_each_entry(exp, &obd->obd_delayed_exports, exp_obd_chain)
1524 print_export_data(exp, "DELAYED", locks);
1525 spin_unlock(&obd->obd_dev_lock);
1526 spin_lock(&obd_zombie_impexp_lock);
1527 list_for_each_entry(exp, &obd_zombie_exports, exp_obd_chain)
1528 print_export_data(exp, "ZOMBIE", locks);
1529 spin_unlock(&obd_zombie_impexp_lock);
1530}
1531EXPORT_SYMBOL(dump_exports);
1532
1533void obd_exports_barrier(struct obd_device *obd)
1534{
1535 int waited = 2;
1536 LASSERT(list_empty(&obd->obd_exports));
1537 spin_lock(&obd->obd_dev_lock);
1538 while (!list_empty(&obd->obd_unlinked_exports)) {
1539 spin_unlock(&obd->obd_dev_lock);
Peng Tao18fd5ba2014-03-18 21:05:55 +08001540 set_current_state(TASK_UNINTERRUPTIBLE);
1541 schedule_timeout(cfs_time_seconds(waited));
Peng Taod7e09d02013-05-02 16:46:55 +08001542 if (waited > 5 && IS_PO2(waited)) {
Joe Perches2d00bd12014-11-23 11:28:50 -08001543 LCONSOLE_WARN("%s is waiting for obd_unlinked_exports more than %d seconds. The obd refcount = %d. Is it stuck?\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001544 obd->obd_name, waited,
1545 atomic_read(&obd->obd_refcount));
1546 dump_exports(obd, 1);
1547 }
1548 waited *= 2;
1549 spin_lock(&obd->obd_dev_lock);
1550 }
1551 spin_unlock(&obd->obd_dev_lock);
1552}
1553EXPORT_SYMBOL(obd_exports_barrier);
1554
1555/* Total amount of zombies to be destroyed */
Supriya Karanth225f5972015-03-03 23:48:21 +09001556static int zombies_count;
Peng Taod7e09d02013-05-02 16:46:55 +08001557
1558/**
1559 * kill zombie imports and exports
1560 */
1561void obd_zombie_impexp_cull(void)
1562{
1563 struct obd_import *import;
1564 struct obd_export *export;
Peng Taod7e09d02013-05-02 16:46:55 +08001565
1566 do {
1567 spin_lock(&obd_zombie_impexp_lock);
1568
1569 import = NULL;
1570 if (!list_empty(&obd_zombie_imports)) {
1571 import = list_entry(obd_zombie_imports.next,
1572 struct obd_import,
1573 imp_zombie_chain);
1574 list_del_init(&import->imp_zombie_chain);
1575 }
1576
1577 export = NULL;
1578 if (!list_empty(&obd_zombie_exports)) {
1579 export = list_entry(obd_zombie_exports.next,
1580 struct obd_export,
1581 exp_obd_chain);
1582 list_del_init(&export->exp_obd_chain);
1583 }
1584
1585 spin_unlock(&obd_zombie_impexp_lock);
1586
1587 if (import != NULL) {
1588 class_import_destroy(import);
1589 spin_lock(&obd_zombie_impexp_lock);
1590 zombies_count--;
1591 spin_unlock(&obd_zombie_impexp_lock);
1592 }
1593
1594 if (export != NULL) {
1595 class_export_destroy(export);
1596 spin_lock(&obd_zombie_impexp_lock);
1597 zombies_count--;
1598 spin_unlock(&obd_zombie_impexp_lock);
1599 }
1600
1601 cond_resched();
1602 } while (import != NULL || export != NULL);
Peng Taod7e09d02013-05-02 16:46:55 +08001603}
1604
1605static struct completion obd_zombie_start;
1606static struct completion obd_zombie_stop;
1607static unsigned long obd_zombie_flags;
1608static wait_queue_head_t obd_zombie_waitq;
1609static pid_t obd_zombie_pid;
1610
1611enum {
1612 OBD_ZOMBIE_STOP = 0x0001,
1613};
1614
1615/**
1616 * check for work for kill zombie import/export thread.
1617 */
1618static int obd_zombie_impexp_check(void *arg)
1619{
1620 int rc;
1621
1622 spin_lock(&obd_zombie_impexp_lock);
1623 rc = (zombies_count == 0) &&
1624 !test_bit(OBD_ZOMBIE_STOP, &obd_zombie_flags);
1625 spin_unlock(&obd_zombie_impexp_lock);
1626
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001627 return rc;
Peng Taod7e09d02013-05-02 16:46:55 +08001628}
1629
1630/**
Masanari Iida52cf6ac2014-02-15 01:11:17 +09001631 * Add export to the obd_zombie thread and notify it.
Peng Taod7e09d02013-05-02 16:46:55 +08001632 */
1633static void obd_zombie_export_add(struct obd_export *exp) {
1634 spin_lock(&exp->exp_obd->obd_dev_lock);
1635 LASSERT(!list_empty(&exp->exp_obd_chain));
1636 list_del_init(&exp->exp_obd_chain);
1637 spin_unlock(&exp->exp_obd->obd_dev_lock);
1638 spin_lock(&obd_zombie_impexp_lock);
1639 zombies_count++;
1640 list_add(&exp->exp_obd_chain, &obd_zombie_exports);
1641 spin_unlock(&obd_zombie_impexp_lock);
1642
1643 obd_zombie_impexp_notify();
1644}
1645
1646/**
Masanari Iida52cf6ac2014-02-15 01:11:17 +09001647 * Add import to the obd_zombie thread and notify it.
Peng Taod7e09d02013-05-02 16:46:55 +08001648 */
1649static void obd_zombie_import_add(struct obd_import *imp) {
1650 LASSERT(imp->imp_sec == NULL);
1651 LASSERT(imp->imp_rq_pool == NULL);
1652 spin_lock(&obd_zombie_impexp_lock);
1653 LASSERT(list_empty(&imp->imp_zombie_chain));
1654 zombies_count++;
1655 list_add(&imp->imp_zombie_chain, &obd_zombie_imports);
1656 spin_unlock(&obd_zombie_impexp_lock);
1657
1658 obd_zombie_impexp_notify();
1659}
1660
1661/**
1662 * notify import/export destroy thread about new zombie.
1663 */
1664static void obd_zombie_impexp_notify(void)
1665{
1666 /*
Masanari Iida52cf6ac2014-02-15 01:11:17 +09001667 * Make sure obd_zombie_impexp_thread get this notification.
Peng Taod7e09d02013-05-02 16:46:55 +08001668 * It is possible this signal only get by obd_zombie_barrier, and
1669 * barrier gulps this notification and sleeps away and hangs ensues
1670 */
1671 wake_up_all(&obd_zombie_waitq);
1672}
1673
1674/**
1675 * check whether obd_zombie is idle
1676 */
1677static int obd_zombie_is_idle(void)
1678{
1679 int rc;
1680
1681 LASSERT(!test_bit(OBD_ZOMBIE_STOP, &obd_zombie_flags));
1682 spin_lock(&obd_zombie_impexp_lock);
1683 rc = (zombies_count == 0);
1684 spin_unlock(&obd_zombie_impexp_lock);
1685 return rc;
1686}
1687
1688/**
1689 * wait when obd_zombie import/export queues become empty
1690 */
1691void obd_zombie_barrier(void)
1692{
1693 struct l_wait_info lwi = { 0 };
1694
1695 if (obd_zombie_pid == current_pid())
1696 /* don't wait for myself */
1697 return;
1698 l_wait_event(obd_zombie_waitq, obd_zombie_is_idle(), &lwi);
1699}
1700EXPORT_SYMBOL(obd_zombie_barrier);
1701
1702
1703/**
1704 * destroy zombie export/import thread.
1705 */
1706static int obd_zombie_impexp_thread(void *unused)
1707{
1708 unshare_fs_struct();
1709 complete(&obd_zombie_start);
1710
1711 obd_zombie_pid = current_pid();
1712
1713 while (!test_bit(OBD_ZOMBIE_STOP, &obd_zombie_flags)) {
1714 struct l_wait_info lwi = { 0 };
1715
1716 l_wait_event(obd_zombie_waitq,
1717 !obd_zombie_impexp_check(NULL), &lwi);
1718 obd_zombie_impexp_cull();
1719
1720 /*
1721 * Notify obd_zombie_barrier callers that queues
1722 * may be empty.
1723 */
1724 wake_up(&obd_zombie_waitq);
1725 }
1726
1727 complete(&obd_zombie_stop);
1728
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001729 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001730}
1731
1732
1733/**
1734 * start destroy zombie import/export thread
1735 */
1736int obd_zombie_impexp_init(void)
1737{
Greg Kroah-Hartman68b636b2013-08-04 08:56:42 +08001738 struct task_struct *task;
Peng Taod7e09d02013-05-02 16:46:55 +08001739
1740 INIT_LIST_HEAD(&obd_zombie_imports);
1741 INIT_LIST_HEAD(&obd_zombie_exports);
1742 spin_lock_init(&obd_zombie_impexp_lock);
1743 init_completion(&obd_zombie_start);
1744 init_completion(&obd_zombie_stop);
1745 init_waitqueue_head(&obd_zombie_waitq);
1746 obd_zombie_pid = 0;
1747
1748 task = kthread_run(obd_zombie_impexp_thread, NULL, "obd_zombid");
1749 if (IS_ERR(task))
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001750 return PTR_ERR(task);
Peng Taod7e09d02013-05-02 16:46:55 +08001751
1752 wait_for_completion(&obd_zombie_start);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001753 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001754}
1755/**
1756 * stop destroy zombie import/export thread
1757 */
1758void obd_zombie_impexp_stop(void)
1759{
1760 set_bit(OBD_ZOMBIE_STOP, &obd_zombie_flags);
1761 obd_zombie_impexp_notify();
1762 wait_for_completion(&obd_zombie_stop);
1763}
1764
1765/***** Kernel-userspace comm helpers *******/
1766
1767/* Get length of entire message, including header */
1768int kuc_len(int payload_len)
1769{
1770 return sizeof(struct kuc_hdr) + payload_len;
1771}
1772EXPORT_SYMBOL(kuc_len);
1773
1774/* Get a pointer to kuc header, given a ptr to the payload
1775 * @param p Pointer to payload area
1776 * @returns Pointer to kuc header
1777 */
Greg Donald54442612014-10-20 11:18:12 -05001778struct kuc_hdr *kuc_ptr(void *p)
Peng Taod7e09d02013-05-02 16:46:55 +08001779{
1780 struct kuc_hdr *lh = ((struct kuc_hdr *)p) - 1;
1781 LASSERT(lh->kuc_magic == KUC_MAGIC);
1782 return lh;
1783}
1784EXPORT_SYMBOL(kuc_ptr);
1785
1786/* Test if payload is part of kuc message
1787 * @param p Pointer to payload area
1788 * @returns boolean
1789 */
1790int kuc_ispayload(void *p)
1791{
1792 struct kuc_hdr *kh = ((struct kuc_hdr *)p) - 1;
1793
1794 if (kh->kuc_magic == KUC_MAGIC)
1795 return 1;
1796 else
1797 return 0;
1798}
1799EXPORT_SYMBOL(kuc_ispayload);
1800
1801/* Alloc space for a message, and fill in header
1802 * @return Pointer to payload area
1803 */
1804void *kuc_alloc(int payload_len, int transport, int type)
1805{
1806 struct kuc_hdr *lh;
1807 int len = kuc_len(payload_len);
1808
Julia Lawalld7279042015-05-01 17:51:15 +02001809 lh = kzalloc(len, GFP_NOFS);
Peng Taod7e09d02013-05-02 16:46:55 +08001810 if (lh == NULL)
1811 return ERR_PTR(-ENOMEM);
1812
1813 lh->kuc_magic = KUC_MAGIC;
1814 lh->kuc_transport = transport;
1815 lh->kuc_msgtype = type;
1816 lh->kuc_msglen = len;
1817
1818 return (void *)(lh + 1);
1819}
1820EXPORT_SYMBOL(kuc_alloc);
1821
1822/* Takes pointer to payload area */
1823inline void kuc_free(void *p, int payload_len)
1824{
1825 struct kuc_hdr *lh = kuc_ptr(p);
Julia Lawalld7279042015-05-01 17:51:15 +02001826 kfree(lh);
Peng Taod7e09d02013-05-02 16:46:55 +08001827}
1828EXPORT_SYMBOL(kuc_free);