Whamcloud - gitweb
Protect the obd export list with a spinlock (we do not sleep anywhere while
authoradilger <adilger>
Mon, 2 Sep 2002 21:24:12 +0000 (21:24 +0000)
committeradilger <adilger>
Mon, 2 Sep 2002 21:24:12 +0000 (21:24 +0000)
holding this spinlock, so I don't believe we need a semaphore).

lustre/include/linux/obd.h
lustre/mds/handler.c
lustre/obdclass/genops.c

index eaea044..05294a4 100644 (file)
@@ -220,6 +220,8 @@ struct obd_device {
         struct list_head obd_exports;
         struct list_head obd_imports;
         struct ldlm_namespace *obd_namespace;
+        /* a spinlock is OK for what we do now, may need a semaphore later */
+        spinlock_t obd_dev_lock;
         union {
                 struct ext2_obd ext2;
                 struct filter_obd filter;
@@ -304,9 +306,14 @@ struct obd_ops {
         int (*o_cancel)(struct lustre_handle *, struct lov_stripe_md *md, __u32 mode, struct lustre_handle *);
 };
 
-/* FIXME: for 64-bit arch */
+#if BITS_PER_LONG > 32
+#define LPU64 "%lu"
+#define LPD64 "%ld"
+#define LPX64 "%lx"
+#else
 #define LPU64 "%Lu"
 #define LPD64 "%Ld"
 #define LPX64 "%Lx"
+#endif
 
 #endif
index a6ed213..f266985 100644 (file)
@@ -274,23 +274,30 @@ static int mds_connect(struct lustre_handle *conn, struct obd_device *obd,
 
         MOD_INC_USE_COUNT;
 
+        spin_lock(&obd->obd_dev_lock);
         list_for_each(p, &obd->obd_exports) {
                 exp = list_entry(p, struct obd_export, exp_chain);
                 mcd = exp->exp_mds_data.med_mcd;
                 if (!memcmp(cluuid, mcd->mcd_uuid, sizeof(mcd->mcd_uuid))) {
-                        CDEBUG(D_INFO, "existing export for UUID '%s' at %p\n",
-                               cluuid, exp);
                         LASSERT(exp->exp_obd == obd);
 
                         exp->exp_rconnh.addr = conn->addr;
                         exp->exp_rconnh.cookie = conn->cookie;
                         conn->addr = (__u64) (unsigned long)exp;
                         conn->cookie = exp->exp_cookie;
+                        spin_unlock(&obd->obd_dev_lock);
+                        CDEBUG(D_INFO, "existing export for UUID '%s' at %p\n",
+                               cluuid, exp);
                         CDEBUG(D_IOCTL,"connect: addr %Lx cookie %Lx\n",
                                (long long)conn->addr, (long long)conn->cookie);
                         RETURN(0);
                 }
         }
+        spin_unlock(&obd->obd_dev_lock);
+        /* XXX There is a small race between checking the list and adding a
+         * new connection for the same UUID, but the real threat (list
+         * corruption when multiple different clients connect) is solved.
+         */
         rc = class_connect(conn, obd, cluuid);
         if (rc)
                 GOTO(out_dec, rc);
@@ -322,13 +329,8 @@ out_dec:
 
 static int mds_disconnect(struct lustre_handle *conn)
 {
-        struct obd_export *exp;
         int rc;
 
-        exp = class_conn2export(conn);
-        if (!exp)
-                RETURN(-EINVAL);
-
         rc = class_disconnect(conn);
         if (!rc)
                 MOD_DEC_USE_COUNT;
index 00af192..be04a28 100644 (file)
@@ -285,7 +285,9 @@ struct obd_export *class_new_export(struct obd_device *obddev)
         /* XXX should these be in MDS and LDLM init functions? */
         INIT_LIST_HEAD(&export->exp_mds_data.med_open_head);
         INIT_LIST_HEAD(&export->exp_ldlm_data.led_held_locks);
+        spin_lock(&obddev->obd_dev_lock);
         list_add(&export->exp_chain, &export->exp_obd->obd_exports);
+        spin_unlock(&obddev->obd_dev_lock);
         return export;
 }
 
@@ -294,9 +296,9 @@ void class_destroy_export(struct obd_export *exp)
         int rc;
         ENTRY;
 
-        //spin_lock(&exp->exp_connection->c_lock);
+        spin_lock(&exp->exp_obd->obd_dev_lock);
         list_del(&exp->exp_chain);
-        //spin_unlock(&exp->exp_connection->c_lock);
+        spin_unlock(&exp->exp_obd->obd_dev_lock);
 
         /* XXXshaver these bits want to be hung off the export, instead of
          * XXXshaver hard-coded here.
@@ -380,16 +382,35 @@ int class_disconnect(struct lustre_handle *conn)
 
 void class_disconnect_all(struct obd_device *obddev)
 {
-        struct list_head *tmp, *next;
-
-        list_for_each_safe(tmp, next, &obddev->obd_exports) {
-                struct obd_export *export;
-                struct lustre_handle conn;
-
-                export = list_entry(tmp, struct obd_export, exp_chain);
-                conn.addr = (__u64) (unsigned long)export;
-                conn.cookie = export->exp_cookie;
-                obd_disconnect(&conn);
+        struct list_head *tmp;
+        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(tmp, struct obd_export, exp_chain);
+                        CERROR("force disconnecting export %p\n", export);
+                        conn.addr = (__u64)(unsigned long)export;
+                        conn.cookie = export->exp_cookie;
+                        spin_unlock(&obddev->obd_dev_lock);
+                        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;
+                }
         }
 }