blob: cf97b8f067640132f87a722c5415c5a14df7b60a [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 *
Andreas Dilger1dc563a2015-11-08 18:09:37 -050030 * Copyright (c) 2011, 2015, Intel Corporation.
Peng Taod7e09d02013-05-02 16:46:55 +080031 */
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"
frank zagoe2780472015-12-23 16:24:43 -050045#include "../include/lustre_kernelcomm.h"
Peng Taod7e09d02013-05-02 16:46:55 +080046
Peng Taod7e09d02013-05-02 16:46:55 +080047spinlock_t obd_types_lock;
48
Pedro Marzo Perez315c9282015-07-16 20:50:00 +020049static struct kmem_cache *obd_device_cachep;
Peng Taod7e09d02013-05-02 16:46:55 +080050struct kmem_cache *obdo_cachep;
51EXPORT_SYMBOL(obdo_cachep);
Haneen Mohammed052c5292015-03-21 10:51:42 +030052static struct kmem_cache *import_cachep;
Peng Taod7e09d02013-05-02 16:46:55 +080053
Haneen Mohammed052c5292015-03-21 10:51:42 +030054static struct list_head obd_zombie_imports;
55static struct list_head obd_zombie_exports;
56static spinlock_t obd_zombie_impexp_lock;
Peng Taod7e09d02013-05-02 16:46:55 +080057static void obd_zombie_impexp_notify(void);
58static void obd_zombie_export_add(struct obd_export *exp);
59static void obd_zombie_import_add(struct obd_import *imp);
Peng Taod7e09d02013-05-02 16:46:55 +080060
61int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
62EXPORT_SYMBOL(ptlrpc_put_connection_superhack);
63
64/*
65 * support functions: we could use inter-module communication, but this
66 * is more portable to other OS's
67 */
68static struct obd_device *obd_device_alloc(void)
69{
70 struct obd_device *obd;
71
Amitoj Kaur Chawla99815cb2016-02-26 14:24:27 +053072 obd = kmem_cache_zalloc(obd_device_cachep, GFP_NOFS);
Oleg Drokincce3c2d2016-02-16 00:46:55 -050073 if (obd)
Peng Taod7e09d02013-05-02 16:46:55 +080074 obd->obd_magic = OBD_DEVICE_MAGIC;
Peng Taod7e09d02013-05-02 16:46:55 +080075 return obd;
76}
77
78static void obd_device_free(struct obd_device *obd)
79{
Peng Taod7e09d02013-05-02 16:46:55 +080080 LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "obd %p obd_magic %08x != %08x\n",
81 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
Oleg Drokincce3c2d2016-02-16 00:46:55 -050082 if (obd->obd_namespace) {
Peng Taod7e09d02013-05-02 16:46:55 +080083 CERROR("obd %p: namespace %p was not properly cleaned up (obd_force=%d)!\n",
84 obd, obd->obd_namespace, obd->obd_force);
85 LBUG();
86 }
87 lu_ref_fini(&obd->obd_reference);
Mike Rapoport50d30362015-10-20 12:39:51 +030088 kmem_cache_free(obd_device_cachep, obd);
Peng Taod7e09d02013-05-02 16:46:55 +080089}
90
Shraddha Barkecbe32722015-10-02 23:19:13 +053091static struct obd_type *class_search_type(const char *name)
Peng Taod7e09d02013-05-02 16:46:55 +080092{
93 struct list_head *tmp;
94 struct obd_type *type;
95
96 spin_lock(&obd_types_lock);
97 list_for_each(tmp, &obd_types) {
98 type = list_entry(tmp, struct obd_type, typ_chain);
99 if (strcmp(type->typ_name, name) == 0) {
100 spin_unlock(&obd_types_lock);
101 return type;
102 }
103 }
104 spin_unlock(&obd_types_lock);
105 return NULL;
106}
Peng Taod7e09d02013-05-02 16:46:55 +0800107
Shraddha Barkecbe32722015-10-02 23:19:13 +0530108static struct obd_type *class_get_type(const char *name)
Peng Taod7e09d02013-05-02 16:46:55 +0800109{
110 struct obd_type *type = class_search_type(name);
111
112 if (!type) {
113 const char *modname = name;
114
Peng Taod7e09d02013-05-02 16:46:55 +0800115 if (!request_module("%s", modname)) {
116 CDEBUG(D_INFO, "Loaded module '%s'\n", modname);
117 type = class_search_type(name);
118 } else {
119 LCONSOLE_ERROR_MSG(0x158, "Can't load module '%s'\n",
120 modname);
121 }
122 }
123 if (type) {
124 spin_lock(&type->obd_type_lock);
125 type->typ_refcnt++;
Dan Carpentera13b1f32015-10-29 12:24:40 +0300126 try_module_get(type->typ_dt_ops->owner);
Peng Taod7e09d02013-05-02 16:46:55 +0800127 spin_unlock(&type->obd_type_lock);
128 }
129 return type;
130}
Peng Taod7e09d02013-05-02 16:46:55 +0800131
132void class_put_type(struct obd_type *type)
133{
134 LASSERT(type);
135 spin_lock(&type->obd_type_lock);
136 type->typ_refcnt--;
Dan Carpentera13b1f32015-10-29 12:24:40 +0300137 module_put(type->typ_dt_ops->owner);
Peng Taod7e09d02013-05-02 16:46:55 +0800138 spin_unlock(&type->obd_type_lock);
139}
140EXPORT_SYMBOL(class_put_type);
141
142#define CLASS_MAX_NAME 1024
143
144int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
Oleg Drokin2962b442015-05-21 15:32:13 -0400145 const char *name,
Peng Taod7e09d02013-05-02 16:46:55 +0800146 struct lu_device_type *ldt)
147{
148 struct obd_type *type;
Markus Elfring14e384c2015-11-05 10:55:16 +0100149 int rc;
Peng Taod7e09d02013-05-02 16:46:55 +0800150
151 /* sanity check */
152 LASSERT(strnlen(name, CLASS_MAX_NAME) < CLASS_MAX_NAME);
153
154 if (class_search_type(name)) {
155 CDEBUG(D_IOCTL, "Type %s already registered\n", name);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800156 return -EEXIST;
Peng Taod7e09d02013-05-02 16:46:55 +0800157 }
158
159 rc = -ENOMEM;
Julia Lawalld7279042015-05-01 17:51:15 +0200160 type = kzalloc(sizeof(*type), GFP_NOFS);
Julia Lawall485640b2015-06-20 18:59:07 +0200161 if (!type)
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800162 return rc;
Peng Taod7e09d02013-05-02 16:46:55 +0800163
Julia Lawalld7279042015-05-01 17:51:15 +0200164 type->typ_dt_ops = kzalloc(sizeof(*type->typ_dt_ops), GFP_NOFS);
165 type->typ_md_ops = kzalloc(sizeof(*type->typ_md_ops), GFP_NOFS);
166 type->typ_name = kzalloc(strlen(name) + 1, GFP_NOFS);
Peng Taod7e09d02013-05-02 16:46:55 +0800167
Shraddha Barke11d5c782015-09-11 11:09:26 +0530168 if (!type->typ_dt_ops ||
169 !type->typ_md_ops ||
170 !type->typ_name)
Julia Lawalld212afd2014-09-07 18:18:35 +0200171 goto failed;
Peng Taod7e09d02013-05-02 16:46:55 +0800172
173 *(type->typ_dt_ops) = *dt_ops;
174 /* md_ops is optional */
175 if (md_ops)
176 *(type->typ_md_ops) = *md_ops;
177 strcpy(type->typ_name, name);
178 spin_lock_init(&type->obd_type_lock);
179
Dmitry Eremin61e87ab2015-05-21 15:32:27 -0400180 type->typ_debugfs_entry = ldebugfs_register(type->typ_name,
181 debugfs_lustre_root,
182 NULL, type);
183 if (IS_ERR_OR_NULL(type->typ_debugfs_entry)) {
184 rc = type->typ_debugfs_entry ? PTR_ERR(type->typ_debugfs_entry)
185 : -ENOMEM;
186 type->typ_debugfs_entry = NULL;
Julia Lawalld212afd2014-09-07 18:18:35 +0200187 goto failed;
Peng Taod7e09d02013-05-02 16:46:55 +0800188 }
Peng Tao8cc420d2013-12-03 22:41:59 +0800189
Oleg Drokin9b801302015-05-21 15:32:16 -0400190 type->typ_kobj = kobject_create_and_add(type->typ_name, lustre_kobj);
191 if (!type->typ_kobj) {
192 rc = -ENOMEM;
193 goto failed;
194 }
195
Oleg Drokincce3c2d2016-02-16 00:46:55 -0500196 if (ldt) {
Peng Taod7e09d02013-05-02 16:46:55 +0800197 type->typ_lu = ldt;
198 rc = lu_device_type_init(ldt);
199 if (rc != 0)
Julia Lawalld212afd2014-09-07 18:18:35 +0200200 goto failed;
Peng Taod7e09d02013-05-02 16:46:55 +0800201 }
202
203 spin_lock(&obd_types_lock);
204 list_add(&type->typ_chain, &obd_types);
205 spin_unlock(&obd_types_lock);
206
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800207 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800208
209 failed:
Oleg Drokin9b801302015-05-21 15:32:16 -0400210 if (type->typ_kobj)
211 kobject_put(type->typ_kobj);
Julia Lawallba99a0a2015-05-01 21:37:55 +0200212 kfree(type->typ_name);
213 kfree(type->typ_md_ops);
214 kfree(type->typ_dt_ops);
Julia Lawalld7279042015-05-01 17:51:15 +0200215 kfree(type);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800216 return rc;
Peng Taod7e09d02013-05-02 16:46:55 +0800217}
218EXPORT_SYMBOL(class_register_type);
219
220int class_unregister_type(const char *name)
221{
222 struct obd_type *type = class_search_type(name);
Peng Taod7e09d02013-05-02 16:46:55 +0800223
224 if (!type) {
225 CERROR("unknown obd type\n");
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800226 return -EINVAL;
Peng Taod7e09d02013-05-02 16:46:55 +0800227 }
228
229 if (type->typ_refcnt) {
230 CERROR("type %s has refcount (%d)\n", name, type->typ_refcnt);
231 /* This is a bad situation, let's make the best of it */
232 /* Remove ops, but leave the name for debugging */
Julia Lawalld7279042015-05-01 17:51:15 +0200233 kfree(type->typ_dt_ops);
234 kfree(type->typ_md_ops);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800235 return -EBUSY;
Peng Taod7e09d02013-05-02 16:46:55 +0800236 }
237
Oleg Drokin9b801302015-05-21 15:32:16 -0400238 if (type->typ_kobj)
239 kobject_put(type->typ_kobj);
240
Dmitry Eremin61e87ab2015-05-21 15:32:27 -0400241 if (!IS_ERR_OR_NULL(type->typ_debugfs_entry))
242 ldebugfs_remove(&type->typ_debugfs_entry);
Peng Taod7e09d02013-05-02 16:46:55 +0800243
244 if (type->typ_lu)
245 lu_device_type_fini(type->typ_lu);
246
247 spin_lock(&obd_types_lock);
248 list_del(&type->typ_chain);
249 spin_unlock(&obd_types_lock);
Julia Lawalld7279042015-05-01 17:51:15 +0200250 kfree(type->typ_name);
Julia Lawallba99a0a2015-05-01 21:37:55 +0200251 kfree(type->typ_dt_ops);
252 kfree(type->typ_md_ops);
Julia Lawalld7279042015-05-01 17:51:15 +0200253 kfree(type);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800254 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800255} /* class_unregister_type */
256EXPORT_SYMBOL(class_unregister_type);
257
258/**
259 * Create a new obd device.
260 *
261 * Find an empty slot in ::obd_devs[], create a new obd device in it.
262 *
263 * \param[in] type_name obd device type string.
264 * \param[in] name obd device name.
265 *
266 * \retval NULL if create fails, otherwise return the obd device
267 * pointer created.
268 */
269struct obd_device *class_newdev(const char *type_name, const char *name)
270{
271 struct obd_device *result = NULL;
272 struct obd_device *newdev;
273 struct obd_type *type = NULL;
274 int i;
275 int new_obd_minor = 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800276
277 if (strlen(name) >= MAX_OBD_NAME) {
278 CERROR("name/uuid must be < %u bytes long\n", MAX_OBD_NAME);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800279 return ERR_PTR(-EINVAL);
Peng Taod7e09d02013-05-02 16:46:55 +0800280 }
281
282 type = class_get_type(type_name);
Shraddha Barke11d5c782015-09-11 11:09:26 +0530283 if (!type) {
Peng Taod7e09d02013-05-02 16:46:55 +0800284 CERROR("OBD: unknown type: %s\n", type_name);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800285 return ERR_PTR(-ENODEV);
Peng Taod7e09d02013-05-02 16:46:55 +0800286 }
287
288 newdev = obd_device_alloc();
Shraddha Barke11d5c782015-09-11 11:09:26 +0530289 if (!newdev) {
Julia Lawalld212afd2014-09-07 18:18:35 +0200290 result = ERR_PTR(-ENOMEM);
291 goto out_type;
292 }
Peng Taod7e09d02013-05-02 16:46:55 +0800293
294 LASSERT(newdev->obd_magic == OBD_DEVICE_MAGIC);
295
296 write_lock(&obd_dev_lock);
297 for (i = 0; i < class_devno_max(); i++) {
298 struct obd_device *obd = class_num2obd(i);
299
300 if (obd && (strcmp(name, obd->obd_name) == 0)) {
301 CERROR("Device %s already exists at %d, won't add\n",
302 name, i);
303 if (result) {
304 LASSERTF(result->obd_magic == OBD_DEVICE_MAGIC,
305 "%p obd_magic %08x != %08x\n", result,
306 result->obd_magic, OBD_DEVICE_MAGIC);
307 LASSERTF(result->obd_minor == new_obd_minor,
308 "%p obd_minor %d != %d\n", result,
309 result->obd_minor, new_obd_minor);
310
311 obd_devs[result->obd_minor] = NULL;
Greg Donald31e72132014-10-20 11:42:36 -0500312 result->obd_name[0] = '\0';
Peng Taod7e09d02013-05-02 16:46:55 +0800313 }
314 result = ERR_PTR(-EEXIST);
315 break;
316 }
317 if (!result && !obd) {
318 result = newdev;
319 result->obd_minor = i;
320 new_obd_minor = i;
321 result->obd_type = type;
322 strncpy(result->obd_name, name,
323 sizeof(result->obd_name) - 1);
324 obd_devs[i] = result;
325 }
326 }
327 write_unlock(&obd_dev_lock);
328
Shraddha Barke11d5c782015-09-11 11:09:26 +0530329 if (!result && i >= class_devno_max()) {
Peng Taod7e09d02013-05-02 16:46:55 +0800330 CERROR("all %u OBD devices used, increase MAX_OBD_DEVICES\n",
331 class_devno_max());
Julia Lawalld212afd2014-09-07 18:18:35 +0200332 result = ERR_PTR(-EOVERFLOW);
333 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800334 }
335
336 if (IS_ERR(result))
Julia Lawalld212afd2014-09-07 18:18:35 +0200337 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800338
339 CDEBUG(D_IOCTL, "Adding new device %s (%p)\n",
340 result->obd_name, result);
341
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800342 return result;
Peng Taod7e09d02013-05-02 16:46:55 +0800343out:
344 obd_device_free(newdev);
345out_type:
346 class_put_type(type);
347 return result;
348}
349
350void class_release_dev(struct obd_device *obd)
351{
352 struct obd_type *obd_type = obd->obd_type;
353
354 LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "%p obd_magic %08x != %08x\n",
355 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
356 LASSERTF(obd == obd_devs[obd->obd_minor], "obd %p != obd_devs[%d] %p\n",
357 obd, obd->obd_minor, obd_devs[obd->obd_minor]);
Oleg Drokincce3c2d2016-02-16 00:46:55 -0500358 LASSERT(obd_type);
Peng Taod7e09d02013-05-02 16:46:55 +0800359
360 CDEBUG(D_INFO, "Release obd device %s at %d obd_type name =%s\n",
361 obd->obd_name, obd->obd_minor, obd->obd_type->typ_name);
362
363 write_lock(&obd_dev_lock);
364 obd_devs[obd->obd_minor] = NULL;
365 write_unlock(&obd_dev_lock);
366 obd_device_free(obd);
367
368 class_put_type(obd_type);
369}
370
371int class_name2dev(const char *name)
372{
373 int i;
374
375 if (!name)
376 return -1;
377
378 read_lock(&obd_dev_lock);
379 for (i = 0; i < class_devno_max(); i++) {
380 struct obd_device *obd = class_num2obd(i);
381
382 if (obd && strcmp(name, obd->obd_name) == 0) {
383 /* Make sure we finished attaching before we give
Oleg Drokin6ba59172016-02-24 22:00:35 -0500384 * out any references
385 */
Peng Taod7e09d02013-05-02 16:46:55 +0800386 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
387 if (obd->obd_attached) {
388 read_unlock(&obd_dev_lock);
389 return i;
390 }
391 break;
392 }
393 }
394 read_unlock(&obd_dev_lock);
395
396 return -1;
397}
398EXPORT_SYMBOL(class_name2dev);
399
400struct obd_device *class_name2obd(const char *name)
401{
402 int dev = class_name2dev(name);
403
404 if (dev < 0 || dev > class_devno_max())
405 return NULL;
406 return class_num2obd(dev);
407}
408EXPORT_SYMBOL(class_name2obd);
409
410int class_uuid2dev(struct obd_uuid *uuid)
411{
412 int i;
413
414 read_lock(&obd_dev_lock);
415 for (i = 0; i < class_devno_max(); i++) {
416 struct obd_device *obd = class_num2obd(i);
417
418 if (obd && obd_uuid_equals(uuid, &obd->obd_uuid)) {
419 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
420 read_unlock(&obd_dev_lock);
421 return i;
422 }
423 }
424 read_unlock(&obd_dev_lock);
425
426 return -1;
427}
428EXPORT_SYMBOL(class_uuid2dev);
429
Peng Taod7e09d02013-05-02 16:46:55 +0800430/**
431 * Get obd device from ::obd_devs[]
432 *
433 * \param num [in] array index
434 *
435 * \retval NULL if ::obd_devs[\a num] does not contains an obd device
436 * otherwise return the obd device there.
437 */
438struct obd_device *class_num2obd(int num)
439{
440 struct obd_device *obd = NULL;
441
442 if (num < class_devno_max()) {
443 obd = obd_devs[num];
Shraddha Barke11d5c782015-09-11 11:09:26 +0530444 if (!obd)
Peng Taod7e09d02013-05-02 16:46:55 +0800445 return NULL;
446
447 LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
448 "%p obd_magic %08x != %08x\n",
449 obd, obd->obd_magic, OBD_DEVICE_MAGIC);
450 LASSERTF(obd->obd_minor == num,
451 "%p obd_minor %0d != %0d\n",
452 obd, obd->obd_minor, num);
453 }
454
455 return obd;
456}
457EXPORT_SYMBOL(class_num2obd);
458
Peng Taod7e09d02013-05-02 16:46:55 +0800459/* Search for a client OBD connected to tgt_uuid. If grp_uuid is
Oleg Drokin6ba59172016-02-24 22:00:35 -0500460 * specified, then only the client with that uuid is returned,
461 * otherwise any client connected to the tgt is returned.
462 */
Greg Donald54442612014-10-20 11:18:12 -0500463struct obd_device *class_find_client_obd(struct obd_uuid *tgt_uuid,
Oleg Drokin926d6fb2016-02-26 01:50:04 -0500464 const char *typ_name,
465 struct obd_uuid *grp_uuid)
Peng Taod7e09d02013-05-02 16:46:55 +0800466{
467 int i;
468
469 read_lock(&obd_dev_lock);
470 for (i = 0; i < class_devno_max(); i++) {
471 struct obd_device *obd = class_num2obd(i);
472
Shraddha Barke11d5c782015-09-11 11:09:26 +0530473 if (!obd)
Peng Taod7e09d02013-05-02 16:46:55 +0800474 continue;
475 if ((strncmp(obd->obd_type->typ_name, typ_name,
476 strlen(typ_name)) == 0)) {
477 if (obd_uuid_equals(tgt_uuid,
478 &obd->u.cli.cl_target_uuid) &&
Mike Rapoportb2952d62015-09-03 11:49:13 +0300479 ((grp_uuid) ? obd_uuid_equals(grp_uuid,
Peng Taod7e09d02013-05-02 16:46:55 +0800480 &obd->obd_uuid) : 1)) {
481 read_unlock(&obd_dev_lock);
482 return obd;
483 }
484 }
485 }
486 read_unlock(&obd_dev_lock);
487
488 return NULL;
489}
490EXPORT_SYMBOL(class_find_client_obd);
491
492/* Iterate the obd_device list looking devices have grp_uuid. Start
Oleg Drokin6ba59172016-02-24 22:00:35 -0500493 * searching at *next, and if a device is found, the next index to look
494 * at is saved in *next. If next is NULL, then the first matching device
495 * will always be returned.
496 */
Greg Donald54442612014-10-20 11:18:12 -0500497struct obd_device *class_devices_in_group(struct obd_uuid *grp_uuid, int *next)
Peng Taod7e09d02013-05-02 16:46:55 +0800498{
499 int i;
500
Shraddha Barke11d5c782015-09-11 11:09:26 +0530501 if (!next)
Peng Taod7e09d02013-05-02 16:46:55 +0800502 i = 0;
503 else if (*next >= 0 && *next < class_devno_max())
504 i = *next;
505 else
506 return NULL;
507
508 read_lock(&obd_dev_lock);
509 for (; i < class_devno_max(); i++) {
510 struct obd_device *obd = class_num2obd(i);
511
Shraddha Barke11d5c782015-09-11 11:09:26 +0530512 if (!obd)
Peng Taod7e09d02013-05-02 16:46:55 +0800513 continue;
514 if (obd_uuid_equals(grp_uuid, &obd->obd_uuid)) {
Shraddha Barke11d5c782015-09-11 11:09:26 +0530515 if (next)
Peng Taod7e09d02013-05-02 16:46:55 +0800516 *next = i+1;
517 read_unlock(&obd_dev_lock);
518 return obd;
519 }
520 }
521 read_unlock(&obd_dev_lock);
522
523 return NULL;
524}
525EXPORT_SYMBOL(class_devices_in_group);
526
527/**
528 * to notify sptlrpc log for \a fsname has changed, let every relevant OBD
529 * adjust sptlrpc settings accordingly.
530 */
531int class_notify_sptlrpc_conf(const char *fsname, int namelen)
532{
533 struct obd_device *obd;
534 const char *type;
535 int i, rc = 0, rc2;
536
537 LASSERT(namelen > 0);
538
539 read_lock(&obd_dev_lock);
540 for (i = 0; i < class_devno_max(); i++) {
541 obd = class_num2obd(i);
542
Shraddha Barke11d5c782015-09-11 11:09:26 +0530543 if (!obd || obd->obd_set_up == 0 || obd->obd_stopping)
Peng Taod7e09d02013-05-02 16:46:55 +0800544 continue;
545
546 /* only notify mdc, osc, mdt, ost */
547 type = obd->obd_type->typ_name;
548 if (strcmp(type, LUSTRE_MDC_NAME) != 0 &&
549 strcmp(type, LUSTRE_OSC_NAME) != 0 &&
550 strcmp(type, LUSTRE_MDT_NAME) != 0 &&
551 strcmp(type, LUSTRE_OST_NAME) != 0)
552 continue;
553
554 if (strncmp(obd->obd_name, fsname, namelen))
555 continue;
556
Christoph Jaegerf9bd9c12014-03-28 00:21:07 +0100557 class_incref(obd, __func__, obd);
Peng Taod7e09d02013-05-02 16:46:55 +0800558 read_unlock(&obd_dev_lock);
559 rc2 = obd_set_info_async(NULL, obd->obd_self_export,
560 sizeof(KEY_SPTLRPC_CONF),
561 KEY_SPTLRPC_CONF, 0, NULL, NULL);
562 rc = rc ? rc : rc2;
Christoph Jaegerf9bd9c12014-03-28 00:21:07 +0100563 class_decref(obd, __func__, obd);
Peng Taod7e09d02013-05-02 16:46:55 +0800564 read_lock(&obd_dev_lock);
565 }
566 read_unlock(&obd_dev_lock);
567 return rc;
568}
569EXPORT_SYMBOL(class_notify_sptlrpc_conf);
570
571void obd_cleanup_caches(void)
572{
Julia Lawallce85ed42015-09-13 14:15:06 +0200573 kmem_cache_destroy(obd_device_cachep);
574 obd_device_cachep = NULL;
575 kmem_cache_destroy(obdo_cachep);
576 obdo_cachep = NULL;
577 kmem_cache_destroy(import_cachep);
578 import_cachep = NULL;
Peng Taod7e09d02013-05-02 16:46:55 +0800579}
580
581int obd_init_caches(void)
582{
Shraddha Barke11d5c782015-09-11 11:09:26 +0530583 LASSERT(!obd_device_cachep);
Peng Taod7e09d02013-05-02 16:46:55 +0800584 obd_device_cachep = kmem_cache_create("ll_obd_dev_cache",
Oleg Drokin926d6fb2016-02-26 01:50:04 -0500585 sizeof(struct obd_device),
586 0, 0, NULL);
Peng Taod7e09d02013-05-02 16:46:55 +0800587 if (!obd_device_cachep)
Julia Lawalld212afd2014-09-07 18:18:35 +0200588 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800589
Shraddha Barke11d5c782015-09-11 11:09:26 +0530590 LASSERT(!obdo_cachep);
Peng Taod7e09d02013-05-02 16:46:55 +0800591 obdo_cachep = kmem_cache_create("ll_obdo_cache", sizeof(struct obdo),
Oleg Drokin926d6fb2016-02-26 01:50:04 -0500592 0, 0, NULL);
Peng Taod7e09d02013-05-02 16:46:55 +0800593 if (!obdo_cachep)
Julia Lawalld212afd2014-09-07 18:18:35 +0200594 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800595
Shraddha Barke11d5c782015-09-11 11:09:26 +0530596 LASSERT(!import_cachep);
Peng Taod7e09d02013-05-02 16:46:55 +0800597 import_cachep = kmem_cache_create("ll_import_cache",
Oleg Drokin926d6fb2016-02-26 01:50:04 -0500598 sizeof(struct obd_import),
599 0, 0, NULL);
Peng Taod7e09d02013-05-02 16:46:55 +0800600 if (!import_cachep)
Julia Lawalld212afd2014-09-07 18:18:35 +0200601 goto out;
Peng Taod7e09d02013-05-02 16:46:55 +0800602
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800603 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800604 out:
605 obd_cleanup_caches();
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800606 return -ENOMEM;
Peng Taod7e09d02013-05-02 16:46:55 +0800607
608}
609
610/* map connection to client */
611struct obd_export *class_conn2export(struct lustre_handle *conn)
612{
613 struct obd_export *export;
Peng Taod7e09d02013-05-02 16:46:55 +0800614
615 if (!conn) {
616 CDEBUG(D_CACHE, "looking for null handle\n");
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800617 return NULL;
Peng Taod7e09d02013-05-02 16:46:55 +0800618 }
619
620 if (conn->cookie == -1) { /* this means assign a new connection */
621 CDEBUG(D_CACHE, "want a new connection\n");
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800622 return NULL;
Peng Taod7e09d02013-05-02 16:46:55 +0800623 }
624
Greg Kroah-Hartman55f5a822014-07-12 20:26:07 -0700625 CDEBUG(D_INFO, "looking for export cookie %#llx\n", conn->cookie);
Peng Taod7e09d02013-05-02 16:46:55 +0800626 export = class_handle2object(conn->cookie);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800627 return export;
Peng Taod7e09d02013-05-02 16:46:55 +0800628}
629EXPORT_SYMBOL(class_conn2export);
630
631struct obd_device *class_exp2obd(struct obd_export *exp)
632{
633 if (exp)
634 return exp->exp_obd;
635 return NULL;
636}
637EXPORT_SYMBOL(class_exp2obd);
638
Peng Taod7e09d02013-05-02 16:46:55 +0800639struct obd_import *class_exp2cliimp(struct obd_export *exp)
640{
641 struct obd_device *obd = exp->exp_obd;
Shraddha Barkefd6f9a42015-09-04 12:08:48 +0530642
Shraddha Barke11d5c782015-09-11 11:09:26 +0530643 if (!obd)
Peng Taod7e09d02013-05-02 16:46:55 +0800644 return NULL;
645 return obd->u.cli.cl_import;
646}
647EXPORT_SYMBOL(class_exp2cliimp);
648
Peng Taod7e09d02013-05-02 16:46:55 +0800649/* Export management functions */
650static void class_export_destroy(struct obd_export *exp)
651{
652 struct obd_device *obd = exp->exp_obd;
Peng Taod7e09d02013-05-02 16:46:55 +0800653
654 LASSERT_ATOMIC_ZERO(&exp->exp_refcount);
Oleg Drokincce3c2d2016-02-16 00:46:55 -0500655 LASSERT(obd);
Peng Taod7e09d02013-05-02 16:46:55 +0800656
657 CDEBUG(D_IOCTL, "destroying export %p/%s for %s\n", exp,
658 exp->exp_client_uuid.uuid, obd->obd_name);
659
660 /* "Local" exports (lctl, LOV->{mdc,osc}) have no connection. */
661 if (exp->exp_connection)
662 ptlrpc_put_connection_superhack(exp->exp_connection);
663
664 LASSERT(list_empty(&exp->exp_outstanding_replies));
665 LASSERT(list_empty(&exp->exp_uncommitted_replies));
666 LASSERT(list_empty(&exp->exp_req_replay_queue));
667 LASSERT(list_empty(&exp->exp_hp_rpcs));
668 obd_destroy_export(exp);
669 class_decref(obd, "export", exp);
670
671 OBD_FREE_RCU(exp, sizeof(*exp), &exp->exp_handle);
Peng Taod7e09d02013-05-02 16:46:55 +0800672}
673
674static void export_handle_addref(void *export)
675{
676 class_export_get(export);
677}
678
679static struct portals_handle_ops export_handle_ops = {
680 .hop_addref = export_handle_addref,
681 .hop_free = NULL,
682};
683
684struct obd_export *class_export_get(struct obd_export *exp)
685{
686 atomic_inc(&exp->exp_refcount);
687 CDEBUG(D_INFO, "GETting export %p : new refcount %d\n", exp,
688 atomic_read(&exp->exp_refcount));
689 return exp;
690}
691EXPORT_SYMBOL(class_export_get);
692
693void class_export_put(struct obd_export *exp)
694{
Peng Taod7e09d02013-05-02 16:46:55 +0800695 LASSERT_ATOMIC_GT_LT(&exp->exp_refcount, 0, LI_POISON);
696 CDEBUG(D_INFO, "PUTting export %p : new refcount %d\n", exp,
697 atomic_read(&exp->exp_refcount) - 1);
698
699 if (atomic_dec_and_test(&exp->exp_refcount)) {
700 LASSERT(!list_empty(&exp->exp_obd_chain));
701 CDEBUG(D_IOCTL, "final put %p/%s\n",
702 exp, exp->exp_client_uuid.uuid);
703
704 /* release nid stat refererence */
705 lprocfs_exp_cleanup(exp);
706
707 obd_zombie_export_add(exp);
708 }
709}
710EXPORT_SYMBOL(class_export_put);
711
712/* Creates a new export, adds it to the hash table, and returns a
713 * pointer to it. The refcount is 2: one for the hash reference, and
Oleg Drokin6ba59172016-02-24 22:00:35 -0500714 * one for the pointer returned by this function.
715 */
Peng Taod7e09d02013-05-02 16:46:55 +0800716struct obd_export *class_new_export(struct obd_device *obd,
717 struct obd_uuid *cluuid)
718{
719 struct obd_export *export;
Lisa Nguyen6da6eab2013-10-21 18:16:26 -0700720 struct cfs_hash *hash = NULL;
Peng Taod7e09d02013-05-02 16:46:55 +0800721 int rc = 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800722
Julia Lawalld7279042015-05-01 17:51:15 +0200723 export = kzalloc(sizeof(*export), GFP_NOFS);
Peng Taod7e09d02013-05-02 16:46:55 +0800724 if (!export)
725 return ERR_PTR(-ENOMEM);
726
727 export->exp_conn_cnt = 0;
728 export->exp_lock_hash = NULL;
729 export->exp_flock_hash = NULL;
730 atomic_set(&export->exp_refcount, 2);
731 atomic_set(&export->exp_rpc_count, 0);
732 atomic_set(&export->exp_cb_count, 0);
733 atomic_set(&export->exp_locks_count, 0);
734#if LUSTRE_TRACKS_LOCK_EXP_REFS
735 INIT_LIST_HEAD(&export->exp_locks_list);
736 spin_lock_init(&export->exp_locks_list_guard);
737#endif
738 atomic_set(&export->exp_replay_count, 0);
739 export->exp_obd = obd;
740 INIT_LIST_HEAD(&export->exp_outstanding_replies);
741 spin_lock_init(&export->exp_uncommitted_replies_lock);
742 INIT_LIST_HEAD(&export->exp_uncommitted_replies);
743 INIT_LIST_HEAD(&export->exp_req_replay_queue);
744 INIT_LIST_HEAD(&export->exp_handle.h_link);
745 INIT_LIST_HEAD(&export->exp_hp_rpcs);
746 class_handle_hash(&export->exp_handle, &export_handle_ops);
Peng Taod7e09d02013-05-02 16:46:55 +0800747 spin_lock_init(&export->exp_lock);
748 spin_lock_init(&export->exp_rpc_lock);
749 INIT_HLIST_NODE(&export->exp_uuid_hash);
Peng Taod7e09d02013-05-02 16:46:55 +0800750 spin_lock_init(&export->exp_bl_list_lock);
751 INIT_LIST_HEAD(&export->exp_bl_list);
752
753 export->exp_sp_peer = LUSTRE_SP_ANY;
754 export->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
755 export->exp_client_uuid = *cluuid;
756 obd_init_export(export);
757
758 spin_lock(&obd->obd_dev_lock);
759 /* shouldn't happen, but might race */
Julia Lawalld212afd2014-09-07 18:18:35 +0200760 if (obd->obd_stopping) {
761 rc = -ENODEV;
762 goto exit_unlock;
763 }
Peng Taod7e09d02013-05-02 16:46:55 +0800764
765 hash = cfs_hash_getref(obd->obd_uuid_hash);
Shraddha Barke11d5c782015-09-11 11:09:26 +0530766 if (!hash) {
Julia Lawalld212afd2014-09-07 18:18:35 +0200767 rc = -ENODEV;
768 goto exit_unlock;
769 }
Peng Taod7e09d02013-05-02 16:46:55 +0800770 spin_unlock(&obd->obd_dev_lock);
771
772 if (!obd_uuid_equals(cluuid, &obd->obd_uuid)) {
773 rc = cfs_hash_add_unique(hash, cluuid, &export->exp_uuid_hash);
774 if (rc != 0) {
775 LCONSOLE_WARN("%s: denying duplicate export for %s, %d\n",
776 obd->obd_name, cluuid->uuid, rc);
Julia Lawalld212afd2014-09-07 18:18:35 +0200777 rc = -EALREADY;
778 goto exit_err;
Peng Taod7e09d02013-05-02 16:46:55 +0800779 }
780 }
781
782 spin_lock(&obd->obd_dev_lock);
783 if (obd->obd_stopping) {
784 cfs_hash_del(hash, cluuid, &export->exp_uuid_hash);
Julia Lawalld212afd2014-09-07 18:18:35 +0200785 rc = -ENODEV;
786 goto exit_unlock;
Peng Taod7e09d02013-05-02 16:46:55 +0800787 }
788
789 class_incref(obd, "export", export);
790 list_add(&export->exp_obd_chain, &export->exp_obd->obd_exports);
Peng Taod7e09d02013-05-02 16:46:55 +0800791 export->exp_obd->obd_num_exports++;
792 spin_unlock(&obd->obd_dev_lock);
793 cfs_hash_putref(hash);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +0800794 return export;
Peng Taod7e09d02013-05-02 16:46:55 +0800795
796exit_unlock:
797 spin_unlock(&obd->obd_dev_lock);
798exit_err:
799 if (hash)
800 cfs_hash_putref(hash);
801 class_handle_unhash(&export->exp_handle);
802 LASSERT(hlist_unhashed(&export->exp_uuid_hash));
803 obd_destroy_export(export);
Julia Lawalld7279042015-05-01 17:51:15 +0200804 kfree(export);
Peng Taod7e09d02013-05-02 16:46:55 +0800805 return ERR_PTR(rc);
806}
807EXPORT_SYMBOL(class_new_export);
808
809void class_unlink_export(struct obd_export *exp)
810{
811 class_handle_unhash(&exp->exp_handle);
812
813 spin_lock(&exp->exp_obd->obd_dev_lock);
814 /* delete an uuid-export hashitem from hashtables */
815 if (!hlist_unhashed(&exp->exp_uuid_hash))
816 cfs_hash_del(exp->exp_obd->obd_uuid_hash,
817 &exp->exp_client_uuid,
818 &exp->exp_uuid_hash);
819
820 list_move(&exp->exp_obd_chain, &exp->exp_obd->obd_unlinked_exports);
Peng Taod7e09d02013-05-02 16:46:55 +0800821 exp->exp_obd->obd_num_exports--;
822 spin_unlock(&exp->exp_obd->obd_dev_lock);
823 class_export_put(exp);
824}
825EXPORT_SYMBOL(class_unlink_export);
826
827/* Import management functions */
Haneen Mohammed052c5292015-03-21 10:51:42 +0300828static void class_import_destroy(struct obd_import *imp)
Peng Taod7e09d02013-05-02 16:46:55 +0800829{
Peng Taod7e09d02013-05-02 16:46:55 +0800830 CDEBUG(D_IOCTL, "destroying import %p for %s\n", imp,
Oleg Drokin926d6fb2016-02-26 01:50:04 -0500831 imp->imp_obd->obd_name);
Peng Taod7e09d02013-05-02 16:46:55 +0800832
833 LASSERT_ATOMIC_ZERO(&imp->imp_refcount);
834
835 ptlrpc_put_connection_superhack(imp->imp_connection);
836
837 while (!list_empty(&imp->imp_conn_list)) {
838 struct obd_import_conn *imp_conn;
839
840 imp_conn = list_entry(imp->imp_conn_list.next,
Oleg Drokin926d6fb2016-02-26 01:50:04 -0500841 struct obd_import_conn, oic_item);
Peng Taod7e09d02013-05-02 16:46:55 +0800842 list_del_init(&imp_conn->oic_item);
843 ptlrpc_put_connection_superhack(imp_conn->oic_conn);
Julia Lawalld7279042015-05-01 17:51:15 +0200844 kfree(imp_conn);
Peng Taod7e09d02013-05-02 16:46:55 +0800845 }
846
Shraddha Barke11d5c782015-09-11 11:09:26 +0530847 LASSERT(!imp->imp_sec);
Peng Taod7e09d02013-05-02 16:46:55 +0800848 class_decref(imp->imp_obd, "import", imp);
849 OBD_FREE_RCU(imp, sizeof(*imp), &imp->imp_handle);
Peng Taod7e09d02013-05-02 16:46:55 +0800850}
851
852static void import_handle_addref(void *import)
853{
854 class_import_get(import);
855}
856
857static struct portals_handle_ops import_handle_ops = {
858 .hop_addref = import_handle_addref,
859 .hop_free = NULL,
860};
861
862struct obd_import *class_import_get(struct obd_import *import)
863{
864 atomic_inc(&import->imp_refcount);
865 CDEBUG(D_INFO, "import %p refcount=%d obd=%s\n", import,
866 atomic_read(&import->imp_refcount),
867 import->imp_obd->obd_name);
868 return import;
869}
870EXPORT_SYMBOL(class_import_get);
871
872void class_import_put(struct obd_import *imp)
873{
Peng Taod7e09d02013-05-02 16:46:55 +0800874 LASSERT(list_empty(&imp->imp_zombie_chain));
875 LASSERT_ATOMIC_GT_LT(&imp->imp_refcount, 0, LI_POISON);
876
877 CDEBUG(D_INFO, "import %p refcount=%d obd=%s\n", imp,
878 atomic_read(&imp->imp_refcount) - 1,
879 imp->imp_obd->obd_name);
880
881 if (atomic_dec_and_test(&imp->imp_refcount)) {
882 CDEBUG(D_INFO, "final put import %p\n", imp);
883 obd_zombie_import_add(imp);
884 }
885
886 /* catch possible import put race */
887 LASSERT_ATOMIC_GE_LT(&imp->imp_refcount, 0, LI_POISON);
Peng Taod7e09d02013-05-02 16:46:55 +0800888}
889EXPORT_SYMBOL(class_import_put);
890
Kris Baumann5d3d4472015-07-09 22:12:48 +0200891static void init_imp_at(struct imp_at *at)
892{
Peng Taod7e09d02013-05-02 16:46:55 +0800893 int i;
Shraddha Barkefd6f9a42015-09-04 12:08:48 +0530894
Peng Taod7e09d02013-05-02 16:46:55 +0800895 at_init(&at->iat_net_latency, 0, 0);
896 for (i = 0; i < IMP_AT_MAX_PORTALS; i++) {
897 /* max service estimates are tracked on the server side, so
Oleg Drokin6ba59172016-02-24 22:00:35 -0500898 * don't use the AT history here, just use the last reported
899 * val. (But keep hist for proc histogram, worst_ever)
900 */
Peng Taod7e09d02013-05-02 16:46:55 +0800901 at_init(&at->iat_service_estimate[i], INITIAL_CONNECT_TIMEOUT,
902 AT_FLG_NOHIST);
903 }
904}
905
906struct obd_import *class_new_import(struct obd_device *obd)
907{
908 struct obd_import *imp;
909
Julia Lawalld7279042015-05-01 17:51:15 +0200910 imp = kzalloc(sizeof(*imp), GFP_NOFS);
Julia Lawall485640b2015-06-20 18:59:07 +0200911 if (!imp)
Peng Taod7e09d02013-05-02 16:46:55 +0800912 return NULL;
913
914 INIT_LIST_HEAD(&imp->imp_pinger_chain);
915 INIT_LIST_HEAD(&imp->imp_zombie_chain);
916 INIT_LIST_HEAD(&imp->imp_replay_list);
917 INIT_LIST_HEAD(&imp->imp_sending_list);
918 INIT_LIST_HEAD(&imp->imp_delayed_list);
Hongchao Zhang63d42572014-02-28 21:16:37 -0500919 INIT_LIST_HEAD(&imp->imp_committed_list);
920 imp->imp_replay_cursor = &imp->imp_committed_list;
Peng Taod7e09d02013-05-02 16:46:55 +0800921 spin_lock_init(&imp->imp_lock);
922 imp->imp_last_success_conn = 0;
923 imp->imp_state = LUSTRE_IMP_NEW;
924 imp->imp_obd = class_incref(obd, "import", imp);
925 mutex_init(&imp->imp_sec_mutex);
926 init_waitqueue_head(&imp->imp_recovery_waitq);
927
928 atomic_set(&imp->imp_refcount, 2);
929 atomic_set(&imp->imp_unregistering, 0);
930 atomic_set(&imp->imp_inflight, 0);
931 atomic_set(&imp->imp_replay_inflight, 0);
932 atomic_set(&imp->imp_inval_count, 0);
933 INIT_LIST_HEAD(&imp->imp_conn_list);
934 INIT_LIST_HEAD(&imp->imp_handle.h_link);
935 class_handle_hash(&imp->imp_handle, &import_handle_ops);
936 init_imp_at(&imp->imp_at);
937
938 /* the default magic is V2, will be used in connect RPC, and
Oleg Drokin6ba59172016-02-24 22:00:35 -0500939 * then adjusted according to the flags in request/reply.
940 */
Peng Taod7e09d02013-05-02 16:46:55 +0800941 imp->imp_msg_magic = LUSTRE_MSG_MAGIC_V2;
942
943 return imp;
944}
945EXPORT_SYMBOL(class_new_import);
946
947void class_destroy_import(struct obd_import *import)
948{
Oleg Drokincce3c2d2016-02-16 00:46:55 -0500949 LASSERT(import);
Peng Taod7e09d02013-05-02 16:46:55 +0800950 LASSERT(import != LP_POISON);
951
952 class_handle_unhash(&import->imp_handle);
953
954 spin_lock(&import->imp_lock);
955 import->imp_generation++;
956 spin_unlock(&import->imp_lock);
957 class_import_put(import);
958}
959EXPORT_SYMBOL(class_destroy_import);
960
961#if LUSTRE_TRACKS_LOCK_EXP_REFS
962
963void __class_export_add_lock_ref(struct obd_export *exp, struct ldlm_lock *lock)
964{
965 spin_lock(&exp->exp_locks_list_guard);
966
967 LASSERT(lock->l_exp_refs_nr >= 0);
968
Oleg Drokincce3c2d2016-02-16 00:46:55 -0500969 if (lock->l_exp_refs_target && lock->l_exp_refs_target != exp) {
Peng Taod7e09d02013-05-02 16:46:55 +0800970 LCONSOLE_WARN("setting export %p for lock %p which already has export %p\n",
971 exp, lock, lock->l_exp_refs_target);
972 }
Mike Rapoportb2952d62015-09-03 11:49:13 +0300973 if ((lock->l_exp_refs_nr++) == 0) {
Peng Taod7e09d02013-05-02 16:46:55 +0800974 list_add(&lock->l_exp_refs_link, &exp->exp_locks_list);
975 lock->l_exp_refs_target = exp;
976 }
977 CDEBUG(D_INFO, "lock = %p, export = %p, refs = %u\n",
978 lock, exp, lock->l_exp_refs_nr);
979 spin_unlock(&exp->exp_locks_list_guard);
980}
981EXPORT_SYMBOL(__class_export_add_lock_ref);
982
983void __class_export_del_lock_ref(struct obd_export *exp, struct ldlm_lock *lock)
984{
985 spin_lock(&exp->exp_locks_list_guard);
986 LASSERT(lock->l_exp_refs_nr > 0);
987 if (lock->l_exp_refs_target != exp) {
Joe Perches2d00bd12014-11-23 11:28:50 -0800988 LCONSOLE_WARN("lock %p, mismatching export pointers: %p, %p\n",
Peng Taod7e09d02013-05-02 16:46:55 +0800989 lock, lock->l_exp_refs_target, exp);
990 }
991 if (-- lock->l_exp_refs_nr == 0) {
992 list_del_init(&lock->l_exp_refs_link);
993 lock->l_exp_refs_target = NULL;
994 }
995 CDEBUG(D_INFO, "lock = %p, export = %p, refs = %u\n",
996 lock, exp, lock->l_exp_refs_nr);
997 spin_unlock(&exp->exp_locks_list_guard);
998}
999EXPORT_SYMBOL(__class_export_del_lock_ref);
1000#endif
1001
1002/* A connection defines an export context in which preallocation can
Oleg Drokin6ba59172016-02-24 22:00:35 -05001003 * be managed. This releases the export pointer reference, and returns
1004 * the export handle, so the export refcount is 1 when this function
1005 * returns.
1006 */
Peng Taod7e09d02013-05-02 16:46:55 +08001007int class_connect(struct lustre_handle *conn, struct obd_device *obd,
1008 struct obd_uuid *cluuid)
1009{
1010 struct obd_export *export;
Shraddha Barkefd6f9a42015-09-04 12:08:48 +05301011
Oleg Drokincce3c2d2016-02-16 00:46:55 -05001012 LASSERT(conn);
1013 LASSERT(obd);
1014 LASSERT(cluuid);
Peng Taod7e09d02013-05-02 16:46:55 +08001015
1016 export = class_new_export(obd, cluuid);
1017 if (IS_ERR(export))
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001018 return PTR_ERR(export);
Peng Taod7e09d02013-05-02 16:46:55 +08001019
1020 conn->cookie = export->exp_handle.h_cookie;
1021 class_export_put(export);
1022
Greg Kroah-Hartman55f5a822014-07-12 20:26:07 -07001023 CDEBUG(D_IOCTL, "connect: client %s, cookie %#llx\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001024 cluuid->uuid, conn->cookie);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001025 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001026}
1027EXPORT_SYMBOL(class_connect);
1028
Peng Taod7e09d02013-05-02 16:46:55 +08001029/* This function removes 1-3 references from the export:
1030 * 1 - for export pointer passed
1031 * and if disconnect really need
1032 * 2 - removing from hash
1033 * 3 - in client_unlink_export
Oleg Drokin6ba59172016-02-24 22:00:35 -05001034 * The export pointer passed to this function can destroyed
1035 */
Peng Taod7e09d02013-05-02 16:46:55 +08001036int class_disconnect(struct obd_export *export)
1037{
1038 int already_disconnected;
Peng Taod7e09d02013-05-02 16:46:55 +08001039
Shraddha Barke11d5c782015-09-11 11:09:26 +05301040 if (!export) {
Peng Taod7e09d02013-05-02 16:46:55 +08001041 CWARN("attempting to free NULL export %p\n", export);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001042 return -EINVAL;
Peng Taod7e09d02013-05-02 16:46:55 +08001043 }
1044
1045 spin_lock(&export->exp_lock);
1046 already_disconnected = export->exp_disconnected;
1047 export->exp_disconnected = 1;
1048 spin_unlock(&export->exp_lock);
1049
1050 /* class_cleanup(), abort_recovery(), and class_fail_export()
1051 * all end up in here, and if any of them race we shouldn't
Oleg Drokin6ba59172016-02-24 22:00:35 -05001052 * call extra class_export_puts().
1053 */
Oleg Drokin706d2632015-09-28 23:44:08 -04001054 if (already_disconnected)
Julia Lawalld212afd2014-09-07 18:18:35 +02001055 goto no_disconn;
Peng Taod7e09d02013-05-02 16:46:55 +08001056
Greg Kroah-Hartman55f5a822014-07-12 20:26:07 -07001057 CDEBUG(D_IOCTL, "disconnect: cookie %#llx\n",
Peng Taod7e09d02013-05-02 16:46:55 +08001058 export->exp_handle.h_cookie);
1059
Peng Taod7e09d02013-05-02 16:46:55 +08001060 class_unlink_export(export);
1061no_disconn:
1062 class_export_put(export);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001063 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001064}
1065EXPORT_SYMBOL(class_disconnect);
1066
Peng Taod7e09d02013-05-02 16:46:55 +08001067void class_fail_export(struct obd_export *exp)
1068{
1069 int rc, already_failed;
1070
1071 spin_lock(&exp->exp_lock);
1072 already_failed = exp->exp_failed;
1073 exp->exp_failed = 1;
1074 spin_unlock(&exp->exp_lock);
1075
1076 if (already_failed) {
1077 CDEBUG(D_HA, "disconnecting dead export %p/%s; skipping\n",
1078 exp, exp->exp_client_uuid.uuid);
1079 return;
1080 }
1081
1082 CDEBUG(D_HA, "disconnecting export %p/%s\n",
1083 exp, exp->exp_client_uuid.uuid);
1084
1085 if (obd_dump_on_timeout)
1086 libcfs_debug_dumplog();
1087
1088 /* need for safe call CDEBUG after obd_disconnect */
1089 class_export_get(exp);
1090
1091 /* Most callers into obd_disconnect are removing their own reference
1092 * (request, for example) in addition to the one from the hash table.
Oleg Drokin6ba59172016-02-24 22:00:35 -05001093 * We don't have such a reference here, so make one.
1094 */
Peng Taod7e09d02013-05-02 16:46:55 +08001095 class_export_get(exp);
1096 rc = obd_disconnect(exp);
1097 if (rc)
1098 CERROR("disconnecting export %p failed: %d\n", exp, rc);
1099 else
1100 CDEBUG(D_HA, "disconnected export %p/%s\n",
1101 exp, exp->exp_client_uuid.uuid);
1102 class_export_put(exp);
1103}
1104EXPORT_SYMBOL(class_fail_export);
1105
Peng Taod7e09d02013-05-02 16:46:55 +08001106#if LUSTRE_TRACKS_LOCK_EXP_REFS
Mike Rapoportb2952d62015-09-03 11:49:13 +03001107void (*class_export_dump_hook)(struct obd_export *) = NULL;
Peng Taod7e09d02013-05-02 16:46:55 +08001108EXPORT_SYMBOL(class_export_dump_hook);
1109#endif
1110
Peng Taod7e09d02013-05-02 16:46:55 +08001111/* Total amount of zombies to be destroyed */
Supriya Karanth225f5972015-03-03 23:48:21 +09001112static int zombies_count;
Peng Taod7e09d02013-05-02 16:46:55 +08001113
1114/**
1115 * kill zombie imports and exports
1116 */
Shraddha Barke63e9a742015-10-04 13:00:14 +05301117static void obd_zombie_impexp_cull(void)
Peng Taod7e09d02013-05-02 16:46:55 +08001118{
1119 struct obd_import *import;
1120 struct obd_export *export;
Peng Taod7e09d02013-05-02 16:46:55 +08001121
1122 do {
1123 spin_lock(&obd_zombie_impexp_lock);
1124
1125 import = NULL;
1126 if (!list_empty(&obd_zombie_imports)) {
1127 import = list_entry(obd_zombie_imports.next,
Oleg Drokin926d6fb2016-02-26 01:50:04 -05001128 struct obd_import,
1129 imp_zombie_chain);
Peng Taod7e09d02013-05-02 16:46:55 +08001130 list_del_init(&import->imp_zombie_chain);
1131 }
1132
1133 export = NULL;
1134 if (!list_empty(&obd_zombie_exports)) {
1135 export = list_entry(obd_zombie_exports.next,
Oleg Drokin926d6fb2016-02-26 01:50:04 -05001136 struct obd_export,
1137 exp_obd_chain);
Peng Taod7e09d02013-05-02 16:46:55 +08001138 list_del_init(&export->exp_obd_chain);
1139 }
1140
1141 spin_unlock(&obd_zombie_impexp_lock);
1142
Oleg Drokincce3c2d2016-02-16 00:46:55 -05001143 if (import) {
Peng Taod7e09d02013-05-02 16:46:55 +08001144 class_import_destroy(import);
1145 spin_lock(&obd_zombie_impexp_lock);
1146 zombies_count--;
1147 spin_unlock(&obd_zombie_impexp_lock);
1148 }
1149
Oleg Drokincce3c2d2016-02-16 00:46:55 -05001150 if (export) {
Peng Taod7e09d02013-05-02 16:46:55 +08001151 class_export_destroy(export);
1152 spin_lock(&obd_zombie_impexp_lock);
1153 zombies_count--;
1154 spin_unlock(&obd_zombie_impexp_lock);
1155 }
1156
1157 cond_resched();
Oleg Drokincce3c2d2016-02-16 00:46:55 -05001158 } while (import || export);
Peng Taod7e09d02013-05-02 16:46:55 +08001159}
1160
1161static struct completion obd_zombie_start;
1162static struct completion obd_zombie_stop;
1163static unsigned long obd_zombie_flags;
1164static wait_queue_head_t obd_zombie_waitq;
1165static pid_t obd_zombie_pid;
1166
1167enum {
1168 OBD_ZOMBIE_STOP = 0x0001,
1169};
1170
1171/**
1172 * check for work for kill zombie import/export thread.
1173 */
1174static int obd_zombie_impexp_check(void *arg)
1175{
1176 int rc;
1177
1178 spin_lock(&obd_zombie_impexp_lock);
1179 rc = (zombies_count == 0) &&
1180 !test_bit(OBD_ZOMBIE_STOP, &obd_zombie_flags);
1181 spin_unlock(&obd_zombie_impexp_lock);
1182
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001183 return rc;
Peng Taod7e09d02013-05-02 16:46:55 +08001184}
1185
1186/**
Masanari Iida52cf6ac2014-02-15 01:11:17 +09001187 * Add export to the obd_zombie thread and notify it.
Peng Taod7e09d02013-05-02 16:46:55 +08001188 */
Kris Baumann5d3d4472015-07-09 22:12:48 +02001189static void obd_zombie_export_add(struct obd_export *exp)
1190{
Peng Taod7e09d02013-05-02 16:46:55 +08001191 spin_lock(&exp->exp_obd->obd_dev_lock);
1192 LASSERT(!list_empty(&exp->exp_obd_chain));
1193 list_del_init(&exp->exp_obd_chain);
1194 spin_unlock(&exp->exp_obd->obd_dev_lock);
1195 spin_lock(&obd_zombie_impexp_lock);
1196 zombies_count++;
1197 list_add(&exp->exp_obd_chain, &obd_zombie_exports);
1198 spin_unlock(&obd_zombie_impexp_lock);
1199
1200 obd_zombie_impexp_notify();
1201}
1202
1203/**
Masanari Iida52cf6ac2014-02-15 01:11:17 +09001204 * Add import to the obd_zombie thread and notify it.
Peng Taod7e09d02013-05-02 16:46:55 +08001205 */
Kris Baumann5d3d4472015-07-09 22:12:48 +02001206static void obd_zombie_import_add(struct obd_import *imp)
1207{
Shraddha Barke11d5c782015-09-11 11:09:26 +05301208 LASSERT(!imp->imp_sec);
Peng Taod7e09d02013-05-02 16:46:55 +08001209 spin_lock(&obd_zombie_impexp_lock);
1210 LASSERT(list_empty(&imp->imp_zombie_chain));
1211 zombies_count++;
1212 list_add(&imp->imp_zombie_chain, &obd_zombie_imports);
1213 spin_unlock(&obd_zombie_impexp_lock);
1214
1215 obd_zombie_impexp_notify();
1216}
1217
1218/**
1219 * notify import/export destroy thread about new zombie.
1220 */
1221static void obd_zombie_impexp_notify(void)
1222{
1223 /*
Masanari Iida52cf6ac2014-02-15 01:11:17 +09001224 * Make sure obd_zombie_impexp_thread get this notification.
Peng Taod7e09d02013-05-02 16:46:55 +08001225 * It is possible this signal only get by obd_zombie_barrier, and
1226 * barrier gulps this notification and sleeps away and hangs ensues
1227 */
1228 wake_up_all(&obd_zombie_waitq);
1229}
1230
1231/**
1232 * check whether obd_zombie is idle
1233 */
1234static int obd_zombie_is_idle(void)
1235{
1236 int rc;
1237
1238 LASSERT(!test_bit(OBD_ZOMBIE_STOP, &obd_zombie_flags));
1239 spin_lock(&obd_zombie_impexp_lock);
1240 rc = (zombies_count == 0);
1241 spin_unlock(&obd_zombie_impexp_lock);
1242 return rc;
1243}
1244
1245/**
1246 * wait when obd_zombie import/export queues become empty
1247 */
1248void obd_zombie_barrier(void)
1249{
1250 struct l_wait_info lwi = { 0 };
1251
1252 if (obd_zombie_pid == current_pid())
1253 /* don't wait for myself */
1254 return;
1255 l_wait_event(obd_zombie_waitq, obd_zombie_is_idle(), &lwi);
1256}
1257EXPORT_SYMBOL(obd_zombie_barrier);
1258
Peng Taod7e09d02013-05-02 16:46:55 +08001259/**
1260 * destroy zombie export/import thread.
1261 */
1262static int obd_zombie_impexp_thread(void *unused)
1263{
1264 unshare_fs_struct();
1265 complete(&obd_zombie_start);
1266
1267 obd_zombie_pid = current_pid();
1268
1269 while (!test_bit(OBD_ZOMBIE_STOP, &obd_zombie_flags)) {
1270 struct l_wait_info lwi = { 0 };
1271
1272 l_wait_event(obd_zombie_waitq,
1273 !obd_zombie_impexp_check(NULL), &lwi);
1274 obd_zombie_impexp_cull();
1275
1276 /*
1277 * Notify obd_zombie_barrier callers that queues
1278 * may be empty.
1279 */
1280 wake_up(&obd_zombie_waitq);
1281 }
1282
1283 complete(&obd_zombie_stop);
1284
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001285 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001286}
1287
Peng Taod7e09d02013-05-02 16:46:55 +08001288/**
1289 * start destroy zombie import/export thread
1290 */
1291int obd_zombie_impexp_init(void)
1292{
Greg Kroah-Hartman68b636b2013-08-04 08:56:42 +08001293 struct task_struct *task;
Peng Taod7e09d02013-05-02 16:46:55 +08001294
1295 INIT_LIST_HEAD(&obd_zombie_imports);
1296 INIT_LIST_HEAD(&obd_zombie_exports);
1297 spin_lock_init(&obd_zombie_impexp_lock);
1298 init_completion(&obd_zombie_start);
1299 init_completion(&obd_zombie_stop);
1300 init_waitqueue_head(&obd_zombie_waitq);
1301 obd_zombie_pid = 0;
1302
1303 task = kthread_run(obd_zombie_impexp_thread, NULL, "obd_zombid");
1304 if (IS_ERR(task))
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001305 return PTR_ERR(task);
Peng Taod7e09d02013-05-02 16:46:55 +08001306
1307 wait_for_completion(&obd_zombie_start);
Greg Kroah-Hartman0a3bdb02013-08-03 10:35:28 +08001308 return 0;
Peng Taod7e09d02013-05-02 16:46:55 +08001309}
Mike Rapoportc9f6bb92015-10-13 16:03:42 +03001310
Peng Taod7e09d02013-05-02 16:46:55 +08001311/**
1312 * stop destroy zombie import/export thread
1313 */
1314void obd_zombie_impexp_stop(void)
1315{
1316 set_bit(OBD_ZOMBIE_STOP, &obd_zombie_flags);
1317 obd_zombie_impexp_notify();
1318 wait_for_completion(&obd_zombie_stop);
1319}