Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2: ocfs2_dlm: Check for migrateable lockres in dlm_empty_lockres() ocfs2_dlm: Fix lockres ref counting bug
This commit is contained in:
commit
e5c465f5d9
|
@ -138,8 +138,10 @@ static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm);
|
||||||
|
|
||||||
void __dlm_unhash_lockres(struct dlm_lock_resource *lockres)
|
void __dlm_unhash_lockres(struct dlm_lock_resource *lockres)
|
||||||
{
|
{
|
||||||
hlist_del_init(&lockres->hash_node);
|
if (!hlist_unhashed(&lockres->hash_node)) {
|
||||||
dlm_lockres_put(lockres);
|
hlist_del_init(&lockres->hash_node);
|
||||||
|
dlm_lockres_put(lockres);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __dlm_insert_lockres(struct dlm_ctxt *dlm,
|
void __dlm_insert_lockres(struct dlm_ctxt *dlm,
|
||||||
|
@ -655,6 +657,8 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm)
|
||||||
dlm_kick_thread(dlm, NULL);
|
dlm_kick_thread(dlm, NULL);
|
||||||
|
|
||||||
while (dlm_migrate_all_locks(dlm)) {
|
while (dlm_migrate_all_locks(dlm)) {
|
||||||
|
/* Give dlm_thread time to purge the lockres' */
|
||||||
|
msleep(500);
|
||||||
mlog(0, "%s: more migration to do\n", dlm->name);
|
mlog(0, "%s: more migration to do\n", dlm->name);
|
||||||
}
|
}
|
||||||
dlm_mark_domain_leaving(dlm);
|
dlm_mark_domain_leaving(dlm);
|
||||||
|
|
|
@ -2424,6 +2424,57 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
|
||||||
dlm_lockres_put(res);
|
dlm_lockres_put(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Checks whether the lockres can be migrated. Returns 0 if yes, < 0
|
||||||
|
* if not. If 0, numlocks is set to the number of locks in the lockres.
|
||||||
|
*/
|
||||||
|
static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
|
||||||
|
struct dlm_lock_resource *res,
|
||||||
|
int *numlocks)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
int count = 0;
|
||||||
|
struct list_head *queue, *iter;
|
||||||
|
struct dlm_lock *lock;
|
||||||
|
|
||||||
|
assert_spin_locked(&res->spinlock);
|
||||||
|
|
||||||
|
ret = -EINVAL;
|
||||||
|
if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
|
||||||
|
mlog(0, "cannot migrate lockres with unknown owner!\n");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res->owner != dlm->node_num) {
|
||||||
|
mlog(0, "cannot migrate lockres this node doesn't own!\n");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
queue = &res->granted;
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
list_for_each(iter, queue) {
|
||||||
|
lock = list_entry(iter, struct dlm_lock, list);
|
||||||
|
++count;
|
||||||
|
if (lock->ml.node == dlm->node_num) {
|
||||||
|
mlog(0, "found a lock owned by this node still "
|
||||||
|
"on the %s queue! will not migrate this "
|
||||||
|
"lockres\n", (i == 0 ? "granted" :
|
||||||
|
(i == 1 ? "converting" :
|
||||||
|
"blocked")));
|
||||||
|
ret = -ENOTEMPTY;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queue++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*numlocks = count;
|
||||||
|
mlog(0, "migrateable lockres having %d locks\n", *numlocks);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DLM_MIGRATE_LOCKRES
|
* DLM_MIGRATE_LOCKRES
|
||||||
|
@ -2437,14 +2488,12 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
|
||||||
struct dlm_master_list_entry *mle = NULL;
|
struct dlm_master_list_entry *mle = NULL;
|
||||||
struct dlm_master_list_entry *oldmle = NULL;
|
struct dlm_master_list_entry *oldmle = NULL;
|
||||||
struct dlm_migratable_lockres *mres = NULL;
|
struct dlm_migratable_lockres *mres = NULL;
|
||||||
int ret = -EINVAL;
|
int ret = 0;
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned int namelen;
|
unsigned int namelen;
|
||||||
int mle_added = 0;
|
int mle_added = 0;
|
||||||
struct list_head *queue, *iter;
|
int numlocks;
|
||||||
int i;
|
int wake = 0;
|
||||||
struct dlm_lock *lock;
|
|
||||||
int empty = 1, wake = 0;
|
|
||||||
|
|
||||||
if (!dlm_grab(dlm))
|
if (!dlm_grab(dlm))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -2458,42 +2507,16 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
|
||||||
* ensure this lockres is a proper candidate for migration
|
* ensure this lockres is a proper candidate for migration
|
||||||
*/
|
*/
|
||||||
spin_lock(&res->spinlock);
|
spin_lock(&res->spinlock);
|
||||||
if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
|
ret = dlm_is_lockres_migrateable(dlm, res, &numlocks);
|
||||||
mlog(0, "cannot migrate lockres with unknown owner!\n");
|
if (ret < 0) {
|
||||||
spin_unlock(&res->spinlock);
|
spin_unlock(&res->spinlock);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if (res->owner != dlm->node_num) {
|
|
||||||
mlog(0, "cannot migrate lockres this node doesn't own!\n");
|
|
||||||
spin_unlock(&res->spinlock);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
mlog(0, "checking queues...\n");
|
|
||||||
queue = &res->granted;
|
|
||||||
for (i=0; i<3; i++) {
|
|
||||||
list_for_each(iter, queue) {
|
|
||||||
lock = list_entry (iter, struct dlm_lock, list);
|
|
||||||
empty = 0;
|
|
||||||
if (lock->ml.node == dlm->node_num) {
|
|
||||||
mlog(0, "found a lock owned by this node "
|
|
||||||
"still on the %s queue! will not "
|
|
||||||
"migrate this lockres\n",
|
|
||||||
i==0 ? "granted" :
|
|
||||||
(i==1 ? "converting" : "blocked"));
|
|
||||||
spin_unlock(&res->spinlock);
|
|
||||||
ret = -ENOTEMPTY;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
queue++;
|
|
||||||
}
|
|
||||||
mlog(0, "all locks on this lockres are nonlocal. continuing\n");
|
|
||||||
spin_unlock(&res->spinlock);
|
spin_unlock(&res->spinlock);
|
||||||
|
|
||||||
/* no work to do */
|
/* no work to do */
|
||||||
if (empty) {
|
if (numlocks == 0) {
|
||||||
mlog(0, "no locks were found on this lockres! done!\n");
|
mlog(0, "no locks were found on this lockres! done!\n");
|
||||||
ret = 0;
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2729,6 +2752,7 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int lock_dropped = 0;
|
int lock_dropped = 0;
|
||||||
|
int numlocks;
|
||||||
|
|
||||||
spin_lock(&res->spinlock);
|
spin_lock(&res->spinlock);
|
||||||
if (res->owner != dlm->node_num) {
|
if (res->owner != dlm->node_num) {
|
||||||
|
@ -2740,6 +2764,13 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
|
||||||
spin_unlock(&res->spinlock);
|
spin_unlock(&res->spinlock);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No need to migrate a lockres having no locks */
|
||||||
|
ret = dlm_is_lockres_migrateable(dlm, res, &numlocks);
|
||||||
|
if (ret >= 0 && numlocks == 0) {
|
||||||
|
spin_unlock(&res->spinlock);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
spin_unlock(&res->spinlock);
|
spin_unlock(&res->spinlock);
|
||||||
|
|
||||||
/* Wheee! Migrate lockres here! Will sleep so drop spinlock. */
|
/* Wheee! Migrate lockres here! Will sleep so drop spinlock. */
|
||||||
|
|
|
@ -256,20 +256,14 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mlog(0, "removing lockres %.*s:%p from purgelist\n",
|
dlm_lockres_get(lockres);
|
||||||
lockres->lockname.len, lockres->lockname.name, lockres);
|
|
||||||
list_del_init(&lockres->purge);
|
|
||||||
dlm_lockres_put(lockres);
|
|
||||||
dlm->purge_count--;
|
|
||||||
|
|
||||||
/* This may drop and reacquire the dlm spinlock if it
|
/* This may drop and reacquire the dlm spinlock if it
|
||||||
* has to do migration. */
|
* has to do migration. */
|
||||||
mlog(0, "calling dlm_purge_lockres!\n");
|
|
||||||
dlm_lockres_get(lockres);
|
|
||||||
if (dlm_purge_lockres(dlm, lockres))
|
if (dlm_purge_lockres(dlm, lockres))
|
||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
dlm_lockres_put(lockres);
|
dlm_lockres_put(lockres);
|
||||||
mlog(0, "DONE calling dlm_purge_lockres!\n");
|
|
||||||
|
|
||||||
/* Avoid adding any scheduling latencies */
|
/* Avoid adding any scheduling latencies */
|
||||||
cond_resched_lock(&dlm->spinlock);
|
cond_resched_lock(&dlm->spinlock);
|
||||||
|
|
Loading…
Reference in New Issue