Whamcloud - gitweb
Defensive check to avoid re-freeing export during force cleanup.
[fs/lustre-release.git] / lustre / obdclass / genops.c
index 8df70b3..3bac4a3 100644 (file)
@@ -91,8 +91,8 @@ void class_put_type(struct obd_type *type)
         module_put(type->typ_ops->o_owner);
 }
 
-int class_register_type(struct obd_ops *ops, struct lprocfs_vars *vars,
-                        char *name)
+int class_register_type(struct obd_ops *ops, struct md_ops *md_ops,
+                        struct lprocfs_vars *vars, char *name)
 {
         struct obd_type *type;
         int rc = 0;
@@ -112,10 +112,17 @@ int class_register_type(struct obd_ops *ops, struct lprocfs_vars *vars,
 
         OBD_ALLOC(type->typ_ops, sizeof(*type->typ_ops));
         OBD_ALLOC(type->typ_name, strlen(name) + 1);
-        if (type->typ_ops == NULL || type->typ_name == NULL)
+        if (md_ops)
+                OBD_ALLOC(type->typ_md_ops, sizeof(*type->typ_md_ops));
+        if (type->typ_ops == NULL || type->typ_name == NULL ||
+                        (md_ops && type->typ_md_ops == NULL))
                 GOTO (failed, rc);
 
         *(type->typ_ops) = *ops;
+        if (md_ops)
+                *(type->typ_md_ops) = *md_ops;
+        else
+                type->typ_md_ops = NULL;
         strcpy(type->typ_name, name);
 
 #ifdef LPROCFS
@@ -139,6 +146,8 @@ int class_register_type(struct obd_ops *ops, struct lprocfs_vars *vars,
                 OBD_FREE(type->typ_name, strlen(name) + 1);
         if (type->typ_ops != NULL)
                 OBD_FREE (type->typ_ops, sizeof (*type->typ_ops));
+        if (type->typ_md_ops != NULL)
+                OBD_FREE (type->typ_md_ops, sizeof (*type->typ_md_ops));
         OBD_FREE(type, sizeof(*type));
         RETURN(rc);
 }
@@ -172,6 +181,8 @@ int class_unregister_type(char *name)
         OBD_FREE(type->typ_name, strlen(name) + 1);
         if (type->typ_ops != NULL)
                 OBD_FREE(type->typ_ops, sizeof(*type->typ_ops));
+        if (type->typ_md_ops != NULL)
+                OBD_FREE (type->typ_md_ops, sizeof (*type->typ_md_ops));
         OBD_FREE(type, sizeof(*type));
         RETURN(0);
 } /* class_unregister_type */
@@ -240,7 +251,8 @@ struct obd_device *class_uuid2obd(struct obd_uuid *uuid)
 
 /* Search for a client OBD connected to tgt_uuid.  If grp_uuid is
    specified, then only the client with that uuid is returned,
-   otherwise any client connected to the tgt is returned. */
+   otherwise any client connected to the tgt is returned.
+   If tgt_uuid is NULL, the lov with grp_uuid is returned. */
 struct obd_device * class_find_client_obd(struct obd_uuid *tgt_uuid,
                                           char * typ_name,
                                           struct obd_uuid *grp_uuid)
@@ -255,6 +267,12 @@ struct obd_device * class_find_client_obd(struct obd_uuid *tgt_uuid,
                              strlen(typ_name)) == 0)) {
                         struct client_obd *cli = &obd->u.cli;
                         struct obd_import *imp = cli->cl_import;
+                        if (tgt_uuid == NULL) {
+                                LASSERT(grp_uuid);
+                                if (obd_uuid_equals(grp_uuid, &obd->obd_uuid))
+                                        return obd;
+                                continue;
+                        }
                         if (obd_uuid_equals(tgt_uuid, &imp->imp_target_uuid) &&
                             ((grp_uuid)? obd_uuid_equals(grp_uuid,
                                                          &obd->obd_uuid) : 1)) {
@@ -420,6 +438,11 @@ void __class_export_put(struct obd_export *exp)
                 if (obd->obd_set_up) {
                         atomic_dec(&obd->obd_refcount);
                         wake_up(&obd->obd_refcount_waitq);
+                } else {
+                        CERROR("removing export %p from obd %s (%p) -- OBD "
+                               "not set up (refcount = %d)\n", exp,
+                               obd->obd_name, obd,
+                               atomic_read(&obd->obd_refcount));
                 }
         }
 }
@@ -439,6 +462,7 @@ struct obd_export *class_new_export(struct obd_device *obd)
 
         export->exp_conn_cnt = 0;
         atomic_set(&export->exp_refcount, 2);
+        atomic_set(&export->exp_rpc_count, 0);
         export->exp_obd = obd;
         INIT_LIST_HEAD(&export->exp_outstanding_replies);
         /* XXX this should be in LDLM init */
@@ -601,8 +625,12 @@ int class_disconnect(struct obd_export *export, int flags)
         CDEBUG(D_IOCTL, "disconnect: cookie "LPX64"\n",
                export->exp_handle.h_cookie);
 
-        class_unlink_export(export);
-        class_export_put(export);
+        if (export->exp_handle.h_cookie == 0x5a5a5a5a5a5a5a5a) {
+                CERROR("disconnecting freed export %p, ignoring\n", export);
+        } else {
+                class_unlink_export(export);
+                class_export_put(export);
+        }
         RETURN(0);
 }