Whamcloud - gitweb
Branch b1_5
authornathan <nathan>
Tue, 11 Jul 2006 16:31:17 +0000 (16:31 +0000)
committernathan <nathan>
Tue, 11 Jul 2006 16:31:17 +0000 (16:31 +0000)
b=10709
- prevent race in llog_setup
- drop export reference on llog setup failure

lustre/include/obd.h
lustre/obdclass/llog_obd.c
lustre/obdclass/obd_config.c

index 809edbd..d12f96a 100644 (file)
@@ -744,7 +744,8 @@ struct obd_device {
                      obd_async_recov:1;   /* allow asyncronous orphan cleanup */
         atomic_t obd_refcount;
         cfs_waitq_t             obd_refcount_waitq;
-        cfs_proc_dir_entry_t  *obd_proc_entry;
+        struct semaphore        obd_setup_sem; /* for gating config stuff */
+        cfs_proc_dir_entry_t   *obd_proc_entry;
         struct list_head        obd_exports;
         int                     obd_num_exports;
         struct ldlm_namespace  *obd_namespace;
index f31450d..6b21b5c 100644 (file)
@@ -71,6 +71,7 @@ int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
         if (index < 0 || index >= LLOG_MAX_CTXTS)
                 RETURN(-EFAULT);
 
+        mutex_down(&obd->obd_setup_sem);
 
         if (obd->obd_llog_ctxt[index]) {
                 /* mds_lov_update_mds might call here multiple times. So if the
@@ -81,12 +82,12 @@ int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
                 LASSERT(ctxt->loc_obd == obd);
                 LASSERT(ctxt->loc_exp == disk_obd->obd_self_export);
                 LASSERT(ctxt->loc_logops == op);
-                RETURN(0);
+                GOTO(out, rc = 0);
         }
         
         OBD_ALLOC(ctxt, sizeof(*ctxt));
         if (!ctxt)
-                RETURN(-ENOMEM);
+                GOTO(out, rc = -ENOMEM);
 
         obd->obd_llog_ctxt[index] = ctxt;
         ctxt->loc_obd = obd;
@@ -97,7 +98,15 @@ int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
 
         if (op->lop_setup)
                 rc = op->lop_setup(obd, index, disk_obd, count, logid);
-
+        
+        if (rc) {
+                obd->obd_llog_ctxt[index] = NULL;
+                class_export_put(ctxt->loc_exp);
+                OBD_FREE(ctxt, sizeof(*ctxt));
+        }
+        
+out:
+        mutex_up(&obd->obd_setup_sem);
         RETURN(rc);
 }
 EXPORT_SYMBOL(llog_setup);
@@ -243,10 +252,6 @@ int llog_obd_origin_setup(struct obd_device *obd, int index,
         if (rc)
                 CERROR("llog_process with cat_cancel_cb failed: %d\n", rc);
  out:
-        if (ctxt && rc) {
-                obd->obd_llog_ctxt[index] = NULL;
-                OBD_FREE(ctxt, sizeof(*ctxt));
-        }
         RETURN(rc);
 }
 EXPORT_SYMBOL(llog_obd_origin_setup);
index 6ea6808..7e76d70 100644 (file)
@@ -181,6 +181,7 @@ int class_attach(struct lustre_cfg *lcfg)
         LASSERTF(strncmp(obd->obd_name, name, strlen(name)) == 0, "%p obd_name %s != %s\n",
                  obd, obd->obd_name, name);
 
+        sema_init(&obd->obd_setup_sem, 1);
         CFS_INIT_LIST_HEAD(&obd->obd_exports);
         CFS_INIT_LIST_HEAD(&obd->obd_exports_timed);
         spin_lock_init(&obd->obd_dev_lock);
@@ -406,8 +407,11 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
                         dump_exports(obd);
                         GOTO(out, err = -EBUSY);
                 }
+                /* refcounf - 3 might be the number of real exports 
+                   (excluding self export). But class_incref is called
+                   by other things as well, so don't count on it. */
                 CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
-                       obd->obd_name, atomic_read(&obd->obd_refcount) - 1);
+                       obd->obd_name, atomic_read(&obd->obd_refcount) - 3);
                 dump_exports(obd);
                 class_disconnect_exports(obd);
         }