void __dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
			      struct dlm_lock_resource *res)
{
	assert_spin_locked(&dlm->spinlock);
	assert_spin_locked(&res->spinlock);

	if (__dlm_lockres_unused(res)){
		if (list_empty(&res->purge)) {
			mlog(0, "%s: Adding res %.*s to purge list\n",
			     dlm->name, res->lockname.len, res->lockname.name);

			res->last_used = jiffies;
			dlm_lockres_get(res);
			list_add_tail(&res->purge, &dlm->purge_list);
			dlm->purge_count++;
		}
	} else if (!list_empty(&res->purge)) {
		mlog(0, "%s: Removing res %.*s from purge list\n",
		     dlm->name, res->lockname.len, res->lockname.name);

		list_del_init(&res->purge);
		dlm_lockres_put(res);
		dlm->purge_count--;
	}
}
예제 #2
0
void __dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
			      struct dlm_lock_resource *res)
{
	mlog_entry("%.*s\n", res->lockname.len, res->lockname.name);

	assert_spin_locked(&dlm->spinlock);
	assert_spin_locked(&res->spinlock);

	if (__dlm_lockres_unused(res)){
		if (list_empty(&res->purge)) {
			mlog(0, "putting lockres %.*s:%p onto purge list\n",
			     res->lockname.len, res->lockname.name, res);

			res->last_used = jiffies;
			dlm_lockres_get(res);
			list_add_tail(&res->purge, &dlm->purge_list);
			dlm->purge_count++;
		}
	} else if (!list_empty(&res->purge)) {
		mlog(0, "removing lockres %.*s:%p from purge list, owner=%u\n",
		     res->lockname.len, res->lockname.name, res, res->owner);

		list_del_init(&res->purge);
		dlm_lockres_put(res);
		dlm->purge_count--;
	}
}
예제 #3
0
static void dlm_run_purge_list(struct dlm_ctxt *dlm,
			       int purge_now)
{
	unsigned int run_max, unused;
	unsigned long purge_jiffies;
	struct dlm_lock_resource *lockres;

	spin_lock(&dlm->spinlock);
	run_max = dlm->purge_count;

	while(run_max && !list_empty(&dlm->purge_list)) {
		run_max--;

		lockres = list_entry(dlm->purge_list.next,
				     struct dlm_lock_resource, purge);

		spin_lock(&lockres->spinlock);

		purge_jiffies = lockres->last_used +
			msecs_to_jiffies(DLM_PURGE_INTERVAL_MS);

		/* Make sure that we want to be processing this guy at
		 * this time. */
		if (!purge_now && time_after(purge_jiffies, jiffies)) {
			/* Since resources are added to the purge list
			 * in tail order, we can stop at the first
			 * unpurgable resource -- anyone added after
			 * him will have a greater last_used value */
			spin_unlock(&lockres->spinlock);
			break;
		}

		/* Status of the lockres *might* change so double
		 * check. If the lockres is unused, holding the dlm
		 * spinlock will prevent people from getting and more
		 * refs on it. */
		unused = __dlm_lockres_unused(lockres);
		if (!unused ||
		    (lockres->state & DLM_LOCK_RES_MIGRATING)) {
			mlog(0, "lockres %s:%.*s: is in use or "
			     "being remastered, used %d, state %d\n",
			     dlm->name, lockres->lockname.len,
			     lockres->lockname.name, !unused, lockres->state);
			list_move_tail(&dlm->purge_list, &lockres->purge);
			spin_unlock(&lockres->spinlock);
			continue;
		}

		dlm_lockres_get(lockres);

		dlm_purge_lockres(dlm, lockres);

		dlm_lockres_put(lockres);

		/* Avoid adding any scheduling latencies */
		cond_resched_lock(&dlm->spinlock);
	}

	spin_unlock(&dlm->spinlock);
}
예제 #4
0
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);
}
예제 #6
0
파일: dlmthread.c 프로젝트: rcplay/snake-os
static void dlm_run_purge_list(struct dlm_ctxt *dlm,
                               int purge_now)
{
    unsigned int run_max, unused;
    unsigned long purge_jiffies;
    struct dlm_lock_resource *lockres;

    spin_lock(&dlm->spinlock);
    run_max = dlm->purge_count;

    while(run_max && !list_empty(&dlm->purge_list)) {
        run_max--;

        lockres = list_entry(dlm->purge_list.next,
                             struct dlm_lock_resource, purge);

        /* Status of the lockres *might* change so double
         * check. If the lockres is unused, holding the dlm
         * spinlock will prevent people from getting and more
         * refs on it -- there's no need to keep the lockres
         * spinlock. */
        spin_lock(&lockres->spinlock);
        unused = __dlm_lockres_unused(lockres);
        spin_unlock(&lockres->spinlock);

        if (!unused)
            continue;

        purge_jiffies = lockres->last_used +
                        msecs_to_jiffies(DLM_PURGE_INTERVAL_MS);

        /* Make sure that we want to be processing this guy at
         * this time. */
        if (!purge_now && time_after(purge_jiffies, jiffies)) {
            /* Since resources are added to the purge list
             * in tail order, we can stop at the first
             * unpurgable resource -- anyone added after
             * him will have a greater last_used value */
            break;
        }

        list_del_init(&lockres->purge);
        dlm->purge_count--;

        /* This may drop and reacquire the dlm spinlock if it
         * has to do migration. */
        mlog(0, "calling dlm_purge_lockres!\n");
        dlm_purge_lockres(dlm, lockres);
        mlog(0, "DONE calling dlm_purge_lockres!\n");

        /* Avoid adding any scheduling latencies */
        cond_resched_lock(&dlm->spinlock);
    }

    spin_unlock(&dlm->spinlock);
}
static void dlm_run_purge_list(struct dlm_ctxt *dlm,
			       int purge_now)
{
	unsigned int run_max, unused;
	unsigned long purge_jiffies;
	struct dlm_lock_resource *lockres;

	spin_lock(&dlm->spinlock);
	run_max = dlm->purge_count;

	while(run_max && !list_empty(&dlm->purge_list)) {
		run_max--;

		lockres = list_entry(dlm->purge_list.next,
				     struct dlm_lock_resource, purge);

		spin_lock(&lockres->spinlock);

		purge_jiffies = lockres->last_used +
			msecs_to_jiffies(DLM_PURGE_INTERVAL_MS);

		if (!purge_now && time_after(purge_jiffies, jiffies)) {
			spin_unlock(&lockres->spinlock);
			break;
		}

		unused = __dlm_lockres_unused(lockres);
		if (!unused ||
		    (lockres->state & DLM_LOCK_RES_MIGRATING)) {
			mlog(0, "%s: res %.*s is in use or being remastered, "
			     "used %d, state %d\n", dlm->name,
			     lockres->lockname.len, lockres->lockname.name,
			     !unused, lockres->state);
			list_move_tail(&dlm->purge_list, &lockres->purge);
			spin_unlock(&lockres->spinlock);
			continue;
		}

		dlm_lockres_get(lockres);

		dlm_purge_lockres(dlm, lockres);

		dlm_lockres_put(lockres);

		
		cond_resched_lock(&dlm->spinlock);
	}

	spin_unlock(&dlm->spinlock);
}
예제 #8
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;
		/* 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);
}