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;
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
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);
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;
/* 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;
}
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.
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;
+ }
}
}