- case OBD_IOC_CLEANUP: {
- int flags = 0;
- char *flag;
-
- if (!obd->obd_set_up) {
- CERROR("Device %d not setup\n", obd->obd_minor);
- GOTO(out, err = -ENODEV);
- }
-
- if (data->ioc_inlbuf1) {
- for (flag = data->ioc_inlbuf1; *flag != 0; flag++)
- switch (*flag) {
- case 'F':
- flags |= OBD_OPT_FORCE;
- break;
- case 'A':
- flags |= OBD_OPT_FAILOVER;
- break;
- default:
- CERROR("unrecognised flag '%c'\n",
- *flag);
- }
- }
-
- if (atomic_read(&obd->obd_refcount) == 1 ||
- flags & OBD_OPT_FORCE) {
- /* this will stop new connections, and need to
- do it before class_disconnect_exports() */
- obd->obd_stopping = 1;
- }
-
- if (atomic_read(&obd->obd_refcount) > 1) {
- struct l_wait_info lwi = LWI_TIMEOUT_INTR(60 * HZ, NULL,
- NULL, NULL);
- int rc;
-
- if (!(flags & OBD_OPT_FORCE)) {
- CERROR("OBD device %d (%p) has refcount %d\n",
- obd->obd_minor, obd,
- atomic_read(&obd->obd_refcount));
- dump_exports(obd);
- GOTO(out, err = -EBUSY);
- }
- class_disconnect_exports(obd, flags);
- CDEBUG(D_IOCTL,
- "%s: waiting for obd refs to go away: %d\n",
- obd->obd_name, atomic_read(&obd->obd_refcount));
-
- rc = l_wait_event(obd->obd_refcount_waitq,
- atomic_read(&obd->obd_refcount) < 2, &lwi);
- if (rc == 0) {
- LASSERT(atomic_read(&obd->obd_refcount) == 1);
- } else {
- CERROR("wait cancelled cleaning anyway. "
- "refcount: %d\n",
- atomic_read(&obd->obd_refcount));
- dump_exports(obd);
- }
- CDEBUG(D_IOCTL, "%s: awake, now finishing cleanup\n",
- obd->obd_name);
- }
-
- if (OBT(obd) && OBP(obd, cleanup))
- err = obd_cleanup(obd, flags);
-
- if (!err) {
- obd->obd_set_up = obd->obd_stopping = 0;
- obd->obd_type->typ_refcnt--;
- atomic_dec(&obd->obd_refcount);
- /* XXX this should be an LASSERT */
- if (atomic_read(&obd->obd_refcount) > 0)
- CERROR("%s still has refcount %d after "
- "cleanup.\n", obd->obd_name,
- atomic_read(&obd->obd_refcount));
- }