Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 * GPL HEADER START
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 only,
 * as published by the Free Software Foundation.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License version 2 for more details.  A copy is
 * included in the COPYING file that accompanied this code.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * GPL HEADER END
 */
/*
 * Copyright (c) 2011 Intel Corporation
 *
 * Copyright 2012 Xyratex Technology Limited
 */
/*
 * lustre/ptlrpc/nrs_fifo.c
 *
 * Network Request Scheduler (NRS) FIFO policy
 *
 * Handles RPCs in a FIFO manner, as received from the network. This policy is
 * a logical wrapper around previous, non-NRS functionality. It is used as the
 * default and fallback policy for all types of RPCs on all PTLRPC service
 * partitions, for both regular and high-priority NRS heads. Default here means
 * the policy is the one enabled at PTLRPC service partition startup time, and
 * fallback means the policy is used to handle RPCs that are not handled
 * successfully or are not handled at all by any primary policy that may be
 * enabled on a given NRS head.
 *
 * Author: Liang Zhen <liang@whamcloud.com>
 * Author: Nikitas Angelinas <nikitas_angelinas@xyratex.com>
 */
/**
 * \addtogoup nrs
 * @{
 */

#define DEBUG_SUBSYSTEM S_RPC
#include "../include/obd_support.h"
#include "../include/obd_class.h"
#include "../../include/linux/libcfs/libcfs.h"
#include "ptlrpc_internal.h"

/**
 * \name fifo
 *
 * The FIFO policy is a logical wrapper around previous, non-NRS functionality.
 * It schedules RPCs in the same order as they are queued from LNet.
 *
 * @{
 */

#define NRS_POL_NAME_FIFO	"fifo"

/**
 * Is called before the policy transitions into
 * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED; allocates and initializes a
 * policy-specific private data structure.
 *
 * \param[in] policy The policy to start
 *
 * \retval -ENOMEM OOM error
 * \retval  0	   success
 *
 * \see nrs_policy_register()
 * \see nrs_policy_ctl()
 */
static int nrs_fifo_start(struct ptlrpc_nrs_policy *policy)
{
	struct nrs_fifo_head *head;

	head = kzalloc_node(sizeof(*head), GFP_NOFS,
			    cfs_cpt_spread_node(nrs_pol2cptab(policy),
						nrs_pol2cptid(policy)));
	if (head == NULL)
		return -ENOMEM;

	INIT_LIST_HEAD(&head->fh_list);
	policy->pol_private = head;
	return 0;
}

/**
 * Is called before the policy transitions into
 * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPED; deallocates the policy-specific
 * private data structure.
 *
 * \param[in] policy The policy to stop
 *
 * \see nrs_policy_stop0()
 */
static void nrs_fifo_stop(struct ptlrpc_nrs_policy *policy)
{
	struct nrs_fifo_head *head = policy->pol_private;

	LASSERT(head != NULL);
	LASSERT(list_empty(&head->fh_list));

	kfree(head);
}

/**
 * Is called for obtaining a FIFO policy resource.
 *
 * \param[in]  policy	  The policy on which the request is being asked for
 * \param[in]  nrq	  The request for which resources are being taken
 * \param[in]  parent	  Parent resource, unused in this policy
 * \param[out] resp	  Resources references are placed in this array
 * \param[in]  moving_req Signifies limited caller context; unused in this
 *			  policy
 *
 * \retval 1 The FIFO policy only has a one-level resource hierarchy, as since
 *	     it implements a simple scheduling algorithm in which request
 *	     priority is determined on the request arrival order, it does not
 *	     need to maintain a set of resources that would otherwise be used
 *	     to calculate a request's priority.
 *
 * \see nrs_resource_get_safe()
 */
static int nrs_fifo_res_get(struct ptlrpc_nrs_policy *policy,
			    struct ptlrpc_nrs_request *nrq,
			    const struct ptlrpc_nrs_resource *parent,
			    struct ptlrpc_nrs_resource **resp, bool moving_req)
{
	/**
	 * Just return the resource embedded inside nrs_fifo_head, and end this
	 * resource hierarchy reference request.
	 */
	*resp = &((struct nrs_fifo_head *)policy->pol_private)->fh_res;
	return 1;
}

/**
 * Called when getting a request from the FIFO policy for handling, or just
 * peeking; removes the request from the policy when it is to be handled.
 *
 * \param[in] policy The policy
 * \param[in] peek   When set, signifies that we just want to examine the
 *		     request, and not handle it, so the request is not removed
 *		     from the policy.
 * \param[in] force  Force the policy to return a request; unused in this
 *		     policy
 *
 * \retval The request to be handled; this is the next request in the FIFO
 *	   queue
 *
 * \see ptlrpc_nrs_req_get_nolock()
 * \see nrs_request_get()
 */
static
struct ptlrpc_nrs_request *nrs_fifo_req_get(struct ptlrpc_nrs_policy *policy,
					    bool peek, bool force)
{
	struct nrs_fifo_head *head = policy->pol_private;
	struct ptlrpc_nrs_request *nrq;

	nrq = unlikely(list_empty(&head->fh_list)) ? NULL :
	      list_entry(head->fh_list.next, struct ptlrpc_nrs_request,
			     nr_u.fifo.fr_list);

	if (likely(!peek && nrq != NULL)) {
		struct ptlrpc_request *req = container_of(nrq,
							  struct ptlrpc_request,
							  rq_nrq);

		list_del_init(&nrq->nr_u.fifo.fr_list);

		CDEBUG(D_RPCTRACE, "NRS start %s request from %s, seq: %llu\n",
		       policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer),
		       nrq->nr_u.fifo.fr_sequence);
	}

	return nrq;
}

/**
 * Adds request \a nrq to \a policy's list of queued requests
 *
 * \param[in] policy The policy
 * \param[in] nrq    The request to add
 *
 * \retval 0 success; nrs_request_enqueue() assumes this function will always
 *		      succeed
 */
static int nrs_fifo_req_add(struct ptlrpc_nrs_policy *policy,
			    struct ptlrpc_nrs_request *nrq)
{
	struct nrs_fifo_head *head;

	head = container_of(nrs_request_resource(nrq), struct nrs_fifo_head,
			    fh_res);
	/**
	 * Only used for debugging
	 */
	nrq->nr_u.fifo.fr_sequence = head->fh_sequence++;
	list_add_tail(&nrq->nr_u.fifo.fr_list, &head->fh_list);

	return 0;
}

/**
 * Removes request \a nrq from \a policy's list of queued requests.
 *
 * \param[in] policy The policy
 * \param[in] nrq    The request to remove
 */
static void nrs_fifo_req_del(struct ptlrpc_nrs_policy *policy,
			     struct ptlrpc_nrs_request *nrq)
{
	LASSERT(!list_empty(&nrq->nr_u.fifo.fr_list));
	list_del_init(&nrq->nr_u.fifo.fr_list);
}

/**
 * Prints a debug statement right before the request \a nrq stops being
 * handled.
 *
 * \param[in] policy The policy handling the request
 * \param[in] nrq    The request being handled
 *
 * \see ptlrpc_server_finish_request()
 * \see ptlrpc_nrs_req_stop_nolock()
 */
static void nrs_fifo_req_stop(struct ptlrpc_nrs_policy *policy,
			      struct ptlrpc_nrs_request *nrq)
{
	struct ptlrpc_request *req = container_of(nrq, struct ptlrpc_request,
						  rq_nrq);

	CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: %llu\n",
	       policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer),
	       nrq->nr_u.fifo.fr_sequence);
}

/**
 * FIFO policy operations
 */
static const struct ptlrpc_nrs_pol_ops nrs_fifo_ops = {
	.op_policy_start	= nrs_fifo_start,
	.op_policy_stop		= nrs_fifo_stop,
	.op_res_get		= nrs_fifo_res_get,
	.op_req_get		= nrs_fifo_req_get,
	.op_req_enqueue		= nrs_fifo_req_add,
	.op_req_dequeue		= nrs_fifo_req_del,
	.op_req_stop		= nrs_fifo_req_stop,
};

/**
 * FIFO policy configuration
 */
struct ptlrpc_nrs_pol_conf nrs_conf_fifo = {
	.nc_name		= NRS_POL_NAME_FIFO,
	.nc_ops			= &nrs_fifo_ops,
	.nc_compat		= nrs_policy_compat_all,
	.nc_flags		= PTLRPC_NRS_FL_FALLBACK |
				  PTLRPC_NRS_FL_REG_START
};

/** @} fifo */

/** @} nrs */