Commit 6a9b2c92 authored by Jinshan Xiong's avatar Jinshan Xiong Committed by Greg Kroah-Hartman
Browse files

staging: lustre: clio: get rid of cl_req



Implement cl_req_attr_set with a cl_object operation.
Get rid of cl_req and related function and data structures.

Signed-off-by: default avatarJinshan Xiong <jinshan.xiong@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6943
Reviewed-on: http://review.whamcloud.com/15833


Reviewed-by: default avatarJohn L. Hammond <john.hammond@intel.com>
Reviewed-by: default avatarBobi Jam <bobijam@hotmail.com>
Reviewed-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarJames Simmons <jsimmons@infradead.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bb371b95
Loading
Loading
Loading
Loading
+17 −225
Original line number Diff line number Diff line
@@ -59,10 +59,6 @@
 *		 read/write system call it is associated with the single user
 *		 thread, that issued the system call).
 *
 *   - cl_req      represents a collection of pages for a transfer. cl_req is
 *		 constructed by req-forming engine that tries to saturate
 *		 transport with large and continuous transfers.
 *
 * Terminology
 *
 *     - to avoid confusion high-level I/O operation like read or write system
@@ -103,11 +99,8 @@
struct inode;

struct cl_device;
struct cl_device_operations;

struct cl_object;
struct cl_object_page_operations;
struct cl_object_lock_operations;

struct cl_page;
struct cl_page_slice;
@@ -120,27 +113,7 @@ struct cl_page_operations;
struct cl_io;
struct cl_io_slice;

struct cl_req;
struct cl_req_slice;

/**
 * Operations for each data device in the client stack.
 *
 * \see vvp_cl_ops, lov_cl_ops, lovsub_cl_ops, osc_cl_ops
 */
struct cl_device_operations {
	/**
	 * Initialize cl_req. This method is called top-to-bottom on all
	 * devices in the stack to get them a chance to allocate layer-private
	 * data, and to attach them to the cl_req by calling
	 * cl_req_slice_add().
	 *
	 * \see osc_req_init(), lov_req_init(), lovsub_req_init()
	 * \see vvp_req_init()
	 */
	int (*cdo_req_init)(const struct lu_env *env, struct cl_device *dev,
			    struct cl_req *req);
};
struct cl_req_attr;

/**
 * Device in the client stack.
@@ -150,8 +123,6 @@ struct cl_device_operations {
struct cl_device {
	/** Super-class. */
	struct lu_device		   cd_lu_dev;
	/** Per-layer operation vector. */
	const struct cl_device_operations *cd_ops;
};

/** \addtogroup cl_object cl_object
@@ -435,6 +406,12 @@ struct cl_object_operations {
	 * Get maximum size of the object.
	 */
	loff_t (*coo_maxbytes)(struct cl_object *obj);
	/**
	 * Set request attributes.
	 */
	void (*coo_req_attr_set)(const struct lu_env *env,
				 struct cl_object *obj,
				 struct cl_req_attr *attr);
};

/**
@@ -626,7 +603,7 @@ enum cl_page_state {
	 *
	 *     - [cl_page_state::CPS_PAGEOUT] page is dirty, the
	 *     req-formation engine decides that it wants to include this page
	 *     into an cl_req being constructed, and yanks it from the cache;
	 *     into an RPC being constructed, and yanks it from the cache;
	 *
	 *     - [cl_page_state::CPS_FREEING] VM callback is executed to
	 *     evict the page form the memory;
@@ -695,7 +672,7 @@ enum cl_page_state {
	 * Page is being read in, as a part of a transfer. This is quite
	 * similar to the cl_page_state::CPS_PAGEOUT state, except that
	 * read-in is always "immediate"---there is no such thing a sudden
	 * construction of read cl_req from cached, presumably not up to date,
	 * construction of read request from cached, presumably not up to date,
	 * pages.
	 *
	 * Underlying VM page is locked for the duration of transfer.
@@ -749,8 +726,6 @@ struct cl_page {
	struct list_head	 cp_batch;
	/** List of slices. Immutable after creation. */
	struct list_head	 cp_layers;
	/** Linkage of pages within cl_req. */
	struct list_head         cp_flight;
	/**
	 * Page state. This field is const to avoid accidental update, it is
	 * modified only internally within cl_page.c. Protected by a VM lock.
@@ -767,12 +742,6 @@ struct cl_page {
	 * by sub-io. Protected by a VM lock.
	 */
	struct cl_io	    *cp_owner;
	/**
	 * Owning IO request in cl_page_state::CPS_PAGEOUT and
	 * cl_page_state::CPS_PAGEIN states. This field is maintained only in
	 * the top-level pages. Protected by a VM lock.
	 */
	struct cl_req	   *cp_req;
	/** List of references to this page, for debugging. */
	struct lu_ref	    cp_reference;
	/** Link to an object, for debugging. */
@@ -814,7 +783,6 @@ enum cl_lock_mode {

/**
 * Requested transfer type.
 * \ingroup cl_req
 */
enum cl_req_type {
	CRT_READ,
@@ -930,8 +898,7 @@ struct cl_page_operations {
	/**
	 * \name transfer
	 *
	 * Transfer methods. See comment on cl_req for a description of
	 * transfer formation and life-cycle.
	 * Transfer methods.
	 *
	 * @{
	 */
@@ -977,7 +944,7 @@ struct cl_page_operations {
				       int ioret);
		/**
		 * Called when cached page is about to be added to the
		 * cl_req as a part of req formation.
		 * ptlrpc request as a part of req formation.
		 *
		 * \return    0       : proceed with this page;
		 * \return    -EAGAIN : skip this page;
@@ -1879,179 +1846,20 @@ struct cl_io {

/** @} cl_io */

/** \addtogroup cl_req cl_req
 * @{
 */
/** \struct cl_req
 * Transfer.
 *
 * There are two possible modes of transfer initiation on the client:
 *
 *     - immediate transfer: this is started when a high level io wants a page
 *       or a collection of pages to be transferred right away. Examples:
 *       read-ahead, synchronous read in the case of non-page aligned write,
 *       page write-out as a part of extent lock cancellation, page write-out
 *       as a part of memory cleansing. Immediate transfer can be both
 *       cl_req_type::CRT_READ and cl_req_type::CRT_WRITE;
 *
 *     - opportunistic transfer (cl_req_type::CRT_WRITE only), that happens
 *       when io wants to transfer a page to the server some time later, when
 *       it can be done efficiently. Example: pages dirtied by the write(2)
 *       path.
 *
 * In any case, transfer takes place in the form of a cl_req, which is a
 * representation for a network RPC.
 *
 * Pages queued for an opportunistic transfer are cached until it is decided
 * that efficient RPC can be composed of them. This decision is made by "a
 * req-formation engine", currently implemented as a part of osc
 * layer. Req-formation depends on many factors: the size of the resulting
 * RPC, whether or not multi-object RPCs are supported by the server,
 * max-rpc-in-flight limitations, size of the dirty cache, etc.
 *
 * For the immediate transfer io submits a cl_page_list, that req-formation
 * engine slices into cl_req's, possibly adding cached pages to some of
 * the resulting req's.
 *
 * Whenever a page from cl_page_list is added to a newly constructed req, its
 * cl_page_operations::cpo_prep() layer methods are called. At that moment,
 * page state is atomically changed from cl_page_state::CPS_OWNED to
 * cl_page_state::CPS_PAGEOUT or cl_page_state::CPS_PAGEIN, cl_page::cp_owner
 * is zeroed, and cl_page::cp_req is set to the
 * req. cl_page_operations::cpo_prep() method at the particular layer might
 * return -EALREADY to indicate that it does not need to submit this page
 * at all. This is possible, for example, if page, submitted for read,
 * became up-to-date in the meantime; and for write, the page don't have
 * dirty bit marked. \see cl_io_submit_rw()
 *
 * Whenever a cached page is added to a newly constructed req, its
 * cl_page_operations::cpo_make_ready() layer methods are called. At that
 * moment, page state is atomically changed from cl_page_state::CPS_CACHED to
 * cl_page_state::CPS_PAGEOUT, and cl_page::cp_req is set to
 * req. cl_page_operations::cpo_make_ready() method at the particular layer
 * might return -EAGAIN to indicate that this page is not eligible for the
 * transfer right now.
 *
 * FUTURE
 *
 * Plan is to divide transfers into "priority bands" (indicated when
 * submitting cl_page_list, and queuing a page for the opportunistic transfer)
 * and allow glueing of cached pages to immediate transfers only within single
 * band. This would make high priority transfers (like lock cancellation or
 * memory pressure induced write-out) really high priority.
 *
 */

/**
 * Per-transfer attributes.
 */
struct cl_req_attr {
	enum cl_req_type cra_type;
	u64		 cra_flags;
	struct cl_page	*cra_page;

	/** Generic attributes for the server consumption. */
	struct obdo	*cra_oa;
	/** Jobid */
	char		 cra_jobid[LUSTRE_JOBID_SIZE];
};

/**
 * Transfer request operations definable at every layer.
 *
 * Concurrency: transfer formation engine synchronizes calls to all transfer
 * methods.
 */
struct cl_req_operations {
	/**
	 * Invoked top-to-bottom by cl_req_prep() when transfer formation is
	 * complete (all pages are added).
	 *
	 * \see osc_req_prep()
	 */
	int  (*cro_prep)(const struct lu_env *env,
			 const struct cl_req_slice *slice);
	/**
	 * Called top-to-bottom to fill in \a oa fields. This is called twice
	 * with different flags, see bug 10150 and osc_build_req().
	 *
	 * \param obj an object from cl_req which attributes are to be set in
	 *	    \a oa.
	 *
	 * \param oa struct obdo where attributes are placed
	 *
	 * \param flags \a oa fields to be filled.
	 */
	void (*cro_attr_set)(const struct lu_env *env,
			     const struct cl_req_slice *slice,
			     const struct cl_object *obj,
			     struct cl_req_attr *attr, u64 flags);
	/**
	 * Called top-to-bottom from cl_req_completion() to notify layers that
	 * transfer completed. Has to free all state allocated by
	 * cl_device_operations::cdo_req_init().
	 */
	void (*cro_completion)(const struct lu_env *env,
			       const struct cl_req_slice *slice, int ioret);
};

/**
 * A per-object state that (potentially multi-object) transfer request keeps.
 */
struct cl_req_obj {
	/** object itself */
	struct cl_object   *ro_obj;
	/** reference to cl_req_obj::ro_obj. For debugging. */
	struct lu_ref_link  ro_obj_ref;
	/* something else? Number of pages for a given object? */
};

/**
 * Transfer request.
 *
 * Transfer requests are not reference counted, because IO sub-system owns
 * them exclusively and knows when to free them.
 *
 * Life cycle.
 *
 * cl_req is created by cl_req_alloc() that calls
 * cl_device_operations::cdo_req_init() device methods to allocate per-req
 * state in every layer.
 *
 * Then pages are added (cl_req_page_add()), req keeps track of all objects it
 * contains pages for.
 *
 * Once all pages were collected, cl_page_operations::cpo_prep() method is
 * called top-to-bottom. At that point layers can modify req, let it pass, or
 * deny it completely. This is to support things like SNS that have transfer
 * ordering requirements invisible to the individual req-formation engine.
 *
 * On transfer completion (or transfer timeout, or failure to initiate the
 * transfer of an allocated req), cl_req_operations::cro_completion() method
 * is called, after execution of cl_page_operations::cpo_completion() of all
 * req's pages.
 */
struct cl_req {
	enum cl_req_type      crq_type;
	/** A list of pages being transferred */
	struct list_head	    crq_pages;
	/** Number of pages in cl_req::crq_pages */
	unsigned	      crq_nrpages;
	/** An array of objects which pages are in ->crq_pages */
	struct cl_req_obj    *crq_o;
	/** Number of elements in cl_req::crq_objs[] */
	unsigned	      crq_nrobjs;
	struct list_head	    crq_layers;
};

/**
 * Per-layer state for request.
 */
struct cl_req_slice {
	struct cl_req    *crs_req;
	struct cl_device *crs_dev;
	struct list_head	crs_linkage;
	const struct cl_req_operations *crs_ops;
};

/* @} cl_req */

enum cache_stats_item {
	/** how many cache lookups were performed */
	CS_lookup = 0,
@@ -2196,9 +2004,6 @@ void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice,
		       const struct cl_lock_operations *ops);
void cl_io_slice_add(struct cl_io *io, struct cl_io_slice *slice,
		     struct cl_object *obj, const struct cl_io_operations *ops);
void cl_req_slice_add(struct cl_req *req, struct cl_req_slice *slice,
		      struct cl_device *dev,
		      const struct cl_req_operations *ops);
/** @} helpers */

/** \defgroup cl_object cl_object
@@ -2567,19 +2372,8 @@ void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page);

/** @} cl_page_list */

/** \defgroup cl_req cl_req
 * @{
 */
struct cl_req *cl_req_alloc(const struct lu_env *env, struct cl_page *page,
			    enum cl_req_type crt, int nr_objects);

void cl_req_page_add(const struct lu_env *env, struct cl_req *req,
		     struct cl_page *page);
void cl_req_page_done(const struct lu_env *env, struct cl_page *page);
int  cl_req_prep(const struct lu_env *env, struct cl_req *req);
void cl_req_attr_set(const struct lu_env *env, struct cl_req *req,
		     struct cl_req_attr *attr, u64 flags);
void cl_req_completion(const struct lu_env *env, struct cl_req *req, int ioret);
void cl_req_attr_set(const struct lu_env *env, struct cl_object *obj,
		     struct cl_req_attr *attr);

/** \defgroup cl_sync_io cl_sync_io
 * @{
@@ -2615,8 +2409,6 @@ void cl_sync_io_end(const struct lu_env *env, struct cl_sync_io *anchor);

/** @} cl_sync_io */

/** @} cl_req */

/** \defgroup cl_env cl_env
 *
 * lu_env handling for a client.
+1 −1
Original line number Diff line number Diff line
@@ -3,5 +3,5 @@ lustre-y := dcache.o dir.o file.o llite_lib.o llite_nfs.o \
	    rw.o rw26.o namei.o symlink.o llite_mmap.o range_lock.o \
	    xattr.o xattr_cache.o xattr_security.o \
	    super25.o statahead.o glimpse.o lcommon_cl.o lcommon_misc.o \
	    vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o vvp_req.o \
	    vvp_dev.o vvp_page.o vvp_lock.o vvp_io.o vvp_object.o \
	    lproc_llite.o
+0 −11
Original line number Diff line number Diff line
@@ -662,8 +662,6 @@ enum {
	LPROC_LL_WRITE_BYTES,
	LPROC_LL_BRW_READ,
	LPROC_LL_BRW_WRITE,
	LPROC_LL_OSC_READ,
	LPROC_LL_OSC_WRITE,
	LPROC_LL_IOCTL,
	LPROC_LL_OPEN,
	LPROC_LL_RELEASE,
@@ -1215,15 +1213,6 @@ struct ll_dio_pages {
	int	   ldp_nr;
};

static inline void cl_stats_tally(struct cl_device *dev, enum cl_req_type crt,
				  int rc)
{
	int opc = (crt == CRT_READ) ? LPROC_LL_OSC_READ :
				      LPROC_LL_OSC_WRITE;

	ll_stats_ops_tally(ll_s2sbi(cl2vvp_dev(dev)->vdv_sb), opc, rc);
}

ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
			   int rw, struct inode *inode,
			   struct ll_dio_pages *pv);
+0 −4
Original line number Diff line number Diff line
@@ -1060,10 +1060,6 @@ static const struct llite_file_opcode {
				   "brw_read" },
	{ LPROC_LL_BRW_WRITE,      LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_PAGES,
				   "brw_write" },
	{ LPROC_LL_OSC_READ,       LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
				   "osc_read" },
	{ LPROC_LL_OSC_WRITE,      LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
				   "osc_write" },
	{ LPROC_LL_IOCTL,	  LPROCFS_TYPE_REGS, "ioctl" },
	{ LPROC_LL_OPEN,	   LPROCFS_TYPE_REGS, "open" },
	{ LPROC_LL_RELEASE,	LPROCFS_TYPE_REGS, "close" },
+0 −12
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@
static struct kmem_cache *ll_thread_kmem;
struct kmem_cache *vvp_lock_kmem;
struct kmem_cache *vvp_object_kmem;
struct kmem_cache *vvp_req_kmem;
static struct kmem_cache *vvp_session_kmem;
static struct kmem_cache *vvp_thread_kmem;

@@ -75,11 +74,6 @@ static struct lu_kmem_descr vvp_caches[] = {
		.ckd_name  = "vvp_object_kmem",
		.ckd_size  = sizeof(struct vvp_object),
	},
	{
		.ckd_cache = &vvp_req_kmem,
		.ckd_name  = "vvp_req_kmem",
		.ckd_size  = sizeof(struct vvp_req),
	},
	{
		.ckd_cache = &vvp_session_kmem,
		.ckd_name  = "vvp_session_kmem",
@@ -177,10 +171,6 @@ static const struct lu_device_operations vvp_lu_ops = {
	.ldo_object_alloc      = vvp_object_alloc
};

static const struct cl_device_operations vvp_cl_ops = {
	.cdo_req_init = vvp_req_init
};

static struct lu_device *vvp_device_free(const struct lu_env *env,
					 struct lu_device *d)
{
@@ -213,7 +203,6 @@ static struct lu_device *vvp_device_alloc(const struct lu_env *env,
	lud = &vdv->vdv_cl.cd_lu_dev;
	cl_device_init(&vdv->vdv_cl, t);
	vvp2lu_dev(vdv)->ld_ops = &vvp_lu_ops;
	vdv->vdv_cl.cd_ops = &vvp_cl_ops;

	site = kzalloc(sizeof(*site), GFP_NOFS);
	if (site) {
@@ -332,7 +321,6 @@ int cl_sb_init(struct super_block *sb)
		cl = cl_type_setup(env, NULL, &vvp_device_type,
				   sbi->ll_dt_exp->exp_obd->obd_lu_dev);
		if (!IS_ERR(cl)) {
			cl2vvp_dev(cl)->vdv_sb = sb;
			sbi->ll_cl = cl;
			sbi->ll_site = cl2lu_dev(cl)->ld_site;
		}
Loading