struct lvfs_run_ctxt obd_lvfs_ctxt;
struct obd_llog_group obd_olg; /* default llog group */
struct obd_device *obd_observer;
+ struct rw_semaphore obd_observer_link_sem;
struct obd_notify_upcall obd_upcall;
struct obd_export *obd_self_export;
/* list of exports in LRU order, for ping evictor, with obd_dev_lock */
{
ENTRY;
OBD_CHECK_DEV(obd);
- if (obd->obd_observer && observer)
+ down_write(&obd->obd_observer_link_sem);
+ if (obd->obd_observer && observer) {
+ up_write(&obd->obd_observer_link_sem);
RETURN(-EALREADY);
+ }
obd->obd_observer = observer;
+ up_write(&obd->obd_observer_link_sem);
+ RETURN(0);
+}
+
+static inline int obd_pin_observer(struct obd_device *obd,
+ struct obd_device **observer)
+{
+ ENTRY;
+ down_read(&obd->obd_observer_link_sem);
+ if (!obd->obd_observer) {
+ *observer = NULL;
+ up_read(&obd->obd_observer_link_sem);
+ RETURN(-ENOENT);
+ }
+ *observer = obd->obd_observer;
+ RETURN(0);
+}
+
+static inline int obd_unpin_observer(struct obd_device *obd)
+{
+ ENTRY;
+ up_read(&obd->obd_observer_link_sem);
RETURN(0);
}
{
#ifdef __KERNEL__
struct obd_device *obd = req->rq_export->exp_obd;
- struct obd_device *master_obd;
+ struct obd_device *master_obd = NULL, *lov_obd = NULL;
struct obd_device_target *obt;
struct lustre_quota_ctxt *qctxt;
struct qunit_data *qdata = NULL;
}
/* we use the observer */
- if (!obd->obd_observer || !obd->obd_observer->obd_observer) {
+ if (obd_pin_observer(obd, &lov_obd) ||
+ obd_pin_observer(lov_obd, &master_obd)) {
CERROR("Can't find the observer, it is recovering\n");
req->rq_status = -EAGAIN;
GOTO(out, rc);
}
- master_obd = obd->obd_observer->obd_observer;
obt = &master_obd->u.obt;
qctxt = &obt->obt_qctxt;
EXIT;
out:
+ if (master_obd)
+ obd_unpin_observer(lov_obd);
+ if (lov_obd)
+ obd_unpin_observer(obd);
+
rc = ptlrpc_reply(req);
return rc;
#else
obd->obd_osfs_age = cfs_time_shift_64(-1000);
/* XXX belongs in setup not attach */
+ init_rwsem(&obd->obd_observer_link_sem);
/* recovery data */
cfs_init_timer(&obd->obd_recovery_timer);
spin_lock_init(&obd->obd_processing_task_lock);