예제 #1
0
파일: mdeg.c 프로젝트: apprisi/illumos-gate
static void
mdeg_notify_client(void *arg)
{
	mdeg_clnt_t		*clnt = (mdeg_clnt_t *)arg;
	md_diff_cookie_t	mdd = MD_INVAL_DIFF_COOKIE;
	mdeg_result_t		mdeg_res;
	mde_cookie_t		md_prev_start;
	mde_cookie_t		md_curr_start;

	/*
	 * mdeg.rwlock must be held as a reader while this function
	 * executes. However, we do not need to acquire the lock as a
	 * reader here because it is held as a reader by the thread
	 * executing mdeg_notify_clients which triggers the execution
	 * of this function from a taskq. Since mdeg_notify_clients
	 * holds the lock as a reader until the taskq callbacks have
	 * completed, it will be held for the life of this function call.
	 * Furthermore, we must not attempt to acquire the lock as a
	 * reader with rw_enter because if there is a pending writer,
	 * we will block, creating a circular deadlock with this function,
	 * the writer, and mdeg_notify_clients. Since we do not need
	 * to acquire the lock, just assert that it is held.
	 */
	ASSERT(RW_READ_HELD(&mdeg.rwlock));

	if (!mdeg.enabled) {
		/* trying to shutdown */
		MDEG_DBG("mdeg_notify_client: mdeg disabled, aborting\n");
		goto cleanup;
	}

	/*
	 * Handle the special case where the node specification
	 * is NULL. In this case, call the client callback without
	 * any results. All processing is left to the client.
	 */
	if (clnt->pspec == NULL) {
		/* call the client callback */
		(*clnt->cb)(clnt->cb_arg, NULL);

		MDEG_DBG("MDEG client callback done\n");
		goto cleanup;
	}

	/* find our start nodes */
	md_prev_start = mdeg_find_start_node(mdeg.md_prev, clnt->pspec);
	if (md_prev_start == MDE_INVAL_ELEM_COOKIE) {
		goto cleanup;
	}

	md_curr_start = mdeg_find_start_node(mdeg.md_curr, clnt->pspec);
	if (md_curr_start == MDE_INVAL_ELEM_COOKIE) {
		goto cleanup;
	}

	/* diff the MDs */
	mdd = md_diff_init(mdeg.md_prev, md_prev_start, mdeg.md_curr,
	    md_curr_start, clnt->nmatch->namep, clnt->nmatch->matchp);

	if (mdd == MD_INVAL_DIFF_COOKIE) {
		MDEG_DBG("unable to diff MDs\n");
		goto cleanup;
	}

	/*
	 * Cache the results of the diff
	 */
	mdeg_get_diff_results(mdd, &mdeg_res);

	/* call the client callback */
	(*clnt->cb)(clnt->cb_arg, &mdeg_res);

	MDEG_DBG("MDEG client callback done\n");

cleanup:
	if (mdd != MD_INVAL_DIFF_COOKIE)
		(void) md_diff_fini(mdd);
}
예제 #2
0
파일: mdeg.c 프로젝트: andreiw/polaris
static void
mdeg_notify_client(void *arg)
{
	mdeg_clnt_t		*clnt = (mdeg_clnt_t *)arg;
	md_diff_cookie_t	mdd = MD_INVAL_DIFF_COOKIE;
	mdeg_result_t		mdeg_res;
	mde_cookie_t		md_prev_start;
	mde_cookie_t		md_curr_start;

	rw_enter(&mdeg.rwlock, RW_READER);

	if (!mdeg.enabled) {
		/* trying to shutdown */
		MDEG_DBG("mdeg_notify_client: mdeg disabled, aborting\n");
		goto cleanup;
	}

	/*
	 * Handle the special case where the node specification
	 * is NULL. In this case, call the client callback without
	 * any results. All processing is left to the client.
	 */
	if (clnt->pspec == NULL) {
		/* call the client callback */
		(*clnt->cb)(clnt->cb_arg, NULL);

		MDEG_DBG("MDEG client callback done\n");
		goto cleanup;
	}

	/* find our start nodes */
	md_prev_start = mdeg_find_start_node(mdeg.md_prev, clnt->pspec);
	if (md_prev_start == MDE_INVAL_ELEM_COOKIE) {
		goto cleanup;
	}

	md_curr_start = mdeg_find_start_node(mdeg.md_curr, clnt->pspec);
	if (md_curr_start == MDE_INVAL_ELEM_COOKIE) {
		goto cleanup;
	}

	/* diff the MDs */
	mdd = md_diff_init(mdeg.md_prev, md_prev_start, mdeg.md_curr,
	    md_curr_start, clnt->nmatch->namep, clnt->nmatch->matchp);

	if (mdd == MD_INVAL_DIFF_COOKIE) {
		MDEG_DBG("unable to diff MDs\n");
		goto cleanup;
	}

	/*
	 * Cache the results of the diff
	 */
	mdeg_get_diff_results(mdd, &mdeg_res);

	/* call the client callback */
	(*clnt->cb)(clnt->cb_arg, &mdeg_res);

	MDEG_DBG("MDEG client callback done\n");

cleanup:
	rw_exit(&mdeg.rwlock);

	if (mdd != MD_INVAL_DIFF_COOKIE)
		(void) md_diff_fini(mdd);
}