static int dlm_purge_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) { int master; int ret = 0; spin_lock(&res->spinlock); if (!__dlm_lockres_unused(res)) { spin_unlock(&res->spinlock); mlog(0, "%s:%.*s: tried to purge but not unused\n", dlm->name, res->lockname.len, res->lockname.name); return -ENOTEMPTY; } master = (res->owner == dlm->node_num); if (!master) res->state |= DLM_LOCK_RES_DROPPING_REF; spin_unlock(&res->spinlock); mlog(0, "purging lockres %.*s, master = %d\n", res->lockname.len, res->lockname.name, master); if (!master) { spin_lock(&res->spinlock); /* This ensures that clear refmap is sent after the set */ __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG); spin_unlock(&res->spinlock); /* drop spinlock to do messaging, retake below */ spin_unlock(&dlm->spinlock); /* clear our bit from the master's refmap, ignore errors */ ret = dlm_drop_lockres_ref(dlm, res); if (ret < 0) { mlog_errno(ret); if (!dlm_is_host_down(ret)) BUG(); } mlog(0, "%s:%.*s: dlm_deref_lockres returned %d\n", dlm->name, res->lockname.len, res->lockname.name, ret); spin_lock(&dlm->spinlock); } if (!list_empty(&res->purge)) { mlog(0, "removing lockres %.*s:%p from purgelist, " "master = %d\n", res->lockname.len, res->lockname.name, res, master); list_del_init(&res->purge); dlm_lockres_put(res); dlm->purge_count--; } __dlm_unhash_lockres(res); /* lockres is not in the hash now. drop the flag and wake up * any processes waiting in dlm_get_lock_resource. */ if (!master) { spin_lock(&res->spinlock); res->state &= ~DLM_LOCK_RES_DROPPING_REF; spin_unlock(&res->spinlock); wake_up(&res->wq); } return 0; }
static void dlm_purge_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) { int master; int ret = 0; assert_spin_locked(&dlm->spinlock); assert_spin_locked(&res->spinlock); master = (res->owner == dlm->node_num); mlog(0, "%s: Purging res %.*s, master %d\n", dlm->name, res->lockname.len, res->lockname.name, master); if (!master) { res->state |= DLM_LOCK_RES_DROPPING_REF; spin_unlock(&res->spinlock); spin_unlock(&dlm->spinlock); spin_lock(&res->spinlock); __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG); spin_unlock(&res->spinlock); ret = dlm_drop_lockres_ref(dlm, res); if (ret < 0) { if (!dlm_is_host_down(ret)) BUG(); } spin_lock(&dlm->spinlock); spin_lock(&res->spinlock); } if (!list_empty(&res->purge)) { mlog(0, "%s: Removing res %.*s from purgelist, master %d\n", dlm->name, res->lockname.len, res->lockname.name, master); list_del_init(&res->purge); dlm_lockres_put(res); dlm->purge_count--; } if (!__dlm_lockres_unused(res)) { mlog(ML_ERROR, "%s: res %.*s in use after deref\n", dlm->name, res->lockname.len, res->lockname.name); __dlm_print_one_lock_resource(res); BUG(); } __dlm_unhash_lockres(dlm, res); if (!master) { res->state &= ~DLM_LOCK_RES_DROPPING_REF; spin_unlock(&res->spinlock); wake_up(&res->wq); } else spin_unlock(&res->spinlock); }
/* TODO: Eventual API: Called with the dlm spinlock held, may drop it * to do migration, but will re-acquire before exit. */ void dlm_purge_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *lockres) { int master; int ret; spin_lock(&lockres->spinlock); master = lockres->owner == dlm->node_num; spin_unlock(&lockres->spinlock); mlog(0, "purging lockres %.*s, master = %d\n", lockres->lockname.len, lockres->lockname.name, master); /* Non master is the easy case -- no migration required, just * quit. */ if (!master) goto finish; /* Wheee! Migrate lockres here! */ spin_unlock(&dlm->spinlock); again: ret = dlm_migrate_lockres(dlm, lockres, O2NM_MAX_NODES); if (ret == -ENOTEMPTY) { mlog(ML_ERROR, "lockres %.*s still has local locks!\n", lockres->lockname.len, lockres->lockname.name); BUG(); } else if (ret < 0) { mlog(ML_NOTICE, "lockres %.*s: migrate failed, retrying\n", lockres->lockname.len, lockres->lockname.name); goto again; } spin_lock(&dlm->spinlock); finish: if (!list_empty(&lockres->purge)) { list_del_init(&lockres->purge); dlm->purge_count--; } __dlm_unhash_lockres(lockres); }
static void dlm_purge_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) { int master; int ret = 0; assert_spin_locked(&dlm->spinlock); assert_spin_locked(&res->spinlock); master = (res->owner == dlm->node_num); mlog(0, "%s: Purging res %.*s, master %d\n", dlm->name, res->lockname.len, res->lockname.name, master); if (!master) { res->state |= DLM_LOCK_RES_DROPPING_REF; /* drop spinlock... retake below */ spin_unlock(&res->spinlock); spin_unlock(&dlm->spinlock); spin_lock(&res->spinlock); /* This ensures that clear refmap is sent after the set */ __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG); spin_unlock(&res->spinlock); /* clear our bit from the master's refmap, ignore errors */ ret = dlm_drop_lockres_ref(dlm, res); if (ret < 0) { if (!dlm_is_host_down(ret)) BUG(); } spin_lock(&dlm->spinlock); spin_lock(&res->spinlock); } if (!list_empty(&res->purge)) { mlog(0, "%s: Removing res %.*s from purgelist, master %d\n", dlm->name, res->lockname.len, res->lockname.name, master); list_del_init(&res->purge); dlm_lockres_put(res); dlm->purge_count--; } if (!__dlm_lockres_unused(res)) { mlog(ML_ERROR, "%s: res %.*s in use after deref\n", dlm->name, res->lockname.len, res->lockname.name); __dlm_print_one_lock_resource(res); BUG(); } __dlm_unhash_lockres(dlm, res); /* lockres is not in the hash now. drop the flag and wake up * any processes waiting in dlm_get_lock_resource. */ if (!master) { res->state &= ~DLM_LOCK_RES_DROPPING_REF; spin_unlock(&res->spinlock); wake_up(&res->wq); } else spin_unlock(&res->spinlock); }