From cfae5c493c746d22bd3506825f9908506a43b283 Mon Sep 17 00:00:00 2001 From: adilger Date: Mon, 2 Sep 2002 21:24:12 +0000 Subject: [PATCH] Protect the obd export list with a spinlock (we do not sleep anywhere while holding this spinlock, so I don't believe we need a semaphore). --- lustre/include/linux/obd.h | 9 ++++++++- lustre/mds/handler.c | 16 +++++++++------- lustre/obdclass/genops.c | 45 +++++++++++++++++++++++++++++++++------------ 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index eaea044..05294a4 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -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 diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index a6ed213..f266985 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -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; diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index 00af192..be04a28 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -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; + } } } -- 1.8.3.1