+void class_disconnect_all(struct obd_device *obddev)
+{
+ int again = 1;
+
+ while (again) {
+ spin_lock(&obddev->obd_dev_lock);
+ if (!list_empty(&obddev->obd_exports)) {
+ struct obd_export *export;
+ struct lustre_handle conn;
+ int rc;
+
+ export = list_entry(obddev->obd_exports.next,
+ struct obd_export,
+ exp_obd_chain);
+ conn.addr = (__u64)(unsigned long)export;
+ conn.cookie = export->exp_cookie;
+ spin_unlock(&obddev->obd_dev_lock);
+ CERROR("force disconnecting export %p\n", export);
+ rc = obd_disconnect(&conn);
+ if (rc < 0) {
+ /* AED: not so sure about this... We can't
+ * loop here forever, yet we shouldn't leak
+ * exports on a struct we will soon destroy.
+ */
+ CERROR("destroy export %p with err: rc = %d\n",
+ export, rc);
+ class_destroy_export(export);
+ }
+ } else {
+ spin_unlock(&obddev->obd_dev_lock);
+ again = 0;
+ }
+ }
+}
+
+#if 0
+
+/* FIXME: Data is a space- or comma-separated list of device IDs. This will
+ * have to change. */
+int class_multi_setup(struct obd_device *obddev, uint32_t len, void *data)
+{
+ int count, rc;
+ char *p;
+ ENTRY;
+
+ for (p = data, count = 0; p < (char *)data + len; count++) {
+ char *end;
+ int tmp = simple_strtoul(p, &end, 0);
+
+ if (p == end) {
+ CERROR("invalid device ID starting at: %s\n", p);
+ GOTO(err_disconnect, rc = -EINVAL);
+ }
+
+ if (tmp < 0 || tmp >= MAX_OBD_DEVICES) {
+ CERROR("Trying to sub dev %d - dev no too large\n",
+ tmp);
+ GOTO(err_disconnect, rc = -EINVAL);
+ }
+
+ rc = obd_connect(&obddev->obd_multi_conn[count], &obd_dev[tmp]);
+ if (rc) {
+ CERROR("cannot connect to device %d: rc = %d\n", tmp,
+ rc);
+ GOTO(err_disconnect, rc);
+ }
+
+ CDEBUG(D_INFO, "target OBD %d is of type %s\n", count,
+ obd_dev[tmp].obd_type->typ_name);
+
+ p = end + 1;
+ }
+
+ obddev->obd_multi_count = count;
+
+ RETURN(0);
+
+ err_disconnect:
+ for (count--; count >= 0; count--)
+ obd_disconnect(&obddev->obd_multi_conn[count]);
+ return rc;
+}