text:
/*
 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 * Use is subject to license terms.
 *
 * Copyright (c) 2011, 2012, Intel Corporation.
 */
/*
 * This file is part of Lustre, http://www.lustre.org/
 * Lustre is a trademark of Sun Microsystems, Inc.
 *
 * Client IO.
 *
 *   Author: Nikita Danilov <nikita.danilov@sun.com>
 */

#define DEBUG_SUBSYSTEM S_CLASS

#include <obd_class.h>
#include <obd_support.h>
#include <lustre_fid.h>
#include <linux/list.h>
#include <cl_object.h>
#include "cl_internal.h"

/*****************************************************************************
 *
 * cl_io interface.
 *
 */

#define cl_io_for_each(slice, io) \
	list_for_each_entry((slice), &io->ci_layers, cis_linkage)
#define cl_io_for_each_reverse(slice, io)		 \
	list_for_each_entry_reverse((slice), &io->ci_layers, cis_linkage)

static inline int cl_io_type_is_valid(enum cl_io_type type)
{
	return CIT_READ <= type && type < CIT_OP_NR;
}

static inline int cl_io_is_loopable(const struct cl_io *io)
{
	return cl_io_type_is_valid(io->ci_type) && io->ci_type != CIT_MISC;
}

/**
 * Returns true iff there is an IO ongoing in the given environment.
 */
int cl_io_is_going(const struct lu_env *env)
{
	return cl_env_info(env)->clt_current_io != NULL;
}
EXPORT_SYMBOL(cl_io_is_going);

/**
 * cl_io invariant that holds at all times when exported cl_io_*() functions
 * are entered and left.
 */
static int cl_io_invariant(const struct cl_io *io)
{
	struct cl_io *up;

	up = io->ci_parent;
	return
		/*
		 * io can own pages only when it is ongoing. Sub-io might
		 * still be in CIS_LOCKED state when top-io is in
		 * CIS_IO_GOING.
		 */
		ergo(io->ci_owned_nr > 0, io->ci_state == CIS_IO_GOING ||
		     (io->ci_state == CIS_LOCKED && up != NULL));
}

/**
 * Finalize \a io, by calling cl_io_operations::cio_fini() bottom-to-top.
 */
void cl_io_fini(const struct lu_env *env, struct cl_io *io)
{
	struct cl_io_slice    *slice;
	struct cl_thread_info *info;

	LINVRNT(cl_io_type_is_valid(io->ci_type));
	LINVRNT(cl_io_invariant(io));

	while (!list_empty(&io->ci_layers)) {
		slice = container_of(io->ci_layers.prev, struct cl_io_slice,
				     cis_linkage);
		list_del_init(&slice->cis_linkage);
		if (slice->cis_iop->op[io->ci_type].cio_fini != NULL)
			slice->cis_iop->op[io->ci_type].cio_fini(env, slice);
		/*
		 * Invalidate slice to catch use after free. This assumes that
		 * slices are allocated within session and can be touched
		 * after ->cio_fini() returns.
		 */
		slice->cis_io = NULL;
	}
	io->ci_state = CIS_FINI;
	info = cl_env_info(env);
	if (info->clt_current_io == io)
		info->clt_current_io = NULL;

	/* sanity check for layout change */
	switch(io->ci_type) {
	case CIT_READ:
	case CIT_WRITE:
		break;
	case CIT_FAULT:
	case CIT_FSYNC:
		LASSERT(!io->ci_need_restart);
		break;
	case CIT_SETATTR:
	case CIT_MISC:
		/* Check ignore layout change conf */
		LASSERT(ergo(io->ci_ignore_layout || !io->ci_verify_layout,
				!io->ci_need_restart));
		break;
	default:
		LBUG();
	}
}
EXPORT_SYMBOL(cl_io_fini);

static int cl_io_init0(const struct lu_env *env, struct cl_io *io,
		       enum cl_io_type iot, struct cl_object *obj)
{
	struct cl_object *scan;
	int result;

	LINVRNT(io->ci_state == CIS_ZERO || io->ci_state == CIS_FINI);
	LINVRNT(cl_io_type_is_valid(iot));
	LINVRNT(cl_io_invariant(io));

	io->ci_type = iot;
	INIT_LIST_HEAD(&io->ci_lockset.cls_todo);
	INIT_LIST_HEAD(&io->ci_lockset.cls_curr);
	INIT_LIST_HEAD(&io->ci_lockset.cls_done);
	INIT_LIST_HEAD(&io->ci_layers);

	result = 0;
	cl_object_for_each(scan, obj) {
		if (scan->co_ops->coo_io_init != NULL) {
			result = scan->co_ops->coo_io_init(env, scan, io);
			if (result != 0)
				break;
		}
	}
	if (result == 0)
		io->ci_state = CIS_INIT;
	return result;
}

/**
 * Initialize sub-io, by calling cl_io_operations::cio_init() top-to-bottom.
 *
 * \pre obj != cl_object_top(obj)
 */
int cl_io_sub_init(const struct lu_env *env, struct cl_io *io,
		   enum cl_io_type iot, struct cl_object *obj)
{
	struct cl_thread_info *info = cl_env_info(env);

	LASSERT(obj != cl_object_top(obj));
	if (info->clt_current_io == NULL)
		info->clt_current_io = io;
	return cl_io_init0(env, io, iot, obj);
}
EXPORT_SYMBOL(cl_io_sub_init);

/**
 * Initialize \a io, by calling cl_io_operations::cio_init() top-to-bottom.
 *
 * Caller has to call cl_io_fini() after a call to cl_io_init(), no matter
 * what the latter returned.
 *
 * \pre obj == cl_object_top(obj)
 * \pre cl_io_type_is_valid(iot)
 * \post cl_io_type_is_valid(io->ci_type) && io->ci_type == iot
 */
int cl_io_init(const struct lu_env *env, struct cl_io *io,
	       enum cl_io_type iot, struct cl_object *obj)
{
	struct cl_thread_info *info = cl_env_info(env);

	LASSERT(obj == cl_object_top(obj));
	LASSERT(info->clt_current_io == NULL);

	info->clt_current_io = io;
	return cl_io_init0(env, io, iot, obj);
}
EXPORT_SYMBOL(cl_io_init);

/**
 * Initialize read or write io.
 *
 * \pre iot == CIT_READ || iot == CIT_WRITE
 */
int cl_io_rw_init(const struct lu_env *env, struct cl_io *io,
		  enum cl_io_type iot, loff_t pos, size_t count)
{
	LINVRNT(iot == CIT_READ || iot == CIT_WRITE);
	LINVRNT(io->ci_obj != NULL);

	LU_OBJECT_HEADER(D_VFSTRACE, env, &io->ci_obj->co_lu,
			 "io range: %u ["LPU64", "LPU64") %u %u\n",
			 iot, (__u64)pos, (__u64)pos + count,
			 io->u.ci_rw.crw_nonblock, io->u.ci_wr.wr_append);
	io->u.ci_rw.crw_pos    = pos;
	io->u.ci_rw.crw_count  = count;
	return cl_io_init(env, io, iot, io->ci_obj);
}
EXPORT_SYMBOL(cl_io_rw_init);

static inline const struct lu_fid *
cl_lock_descr_fid(const struct cl_lock_descr *descr)
{
	return lu_object_fid(&descr->cld_obj->co_lu);
}

static int cl_lock_descr_sort(const struct cl_lock_descr *d0,
			      const struct cl_lock_descr *d1)
{
	return lu_fid_cmp(cl_lock_descr_fid(d0), cl_lock_descr_fid(d1)) ?:
		__diff_normalize(d0->cld_start, d1->cld_start);
}

static int cl_lock_descr_cmp(const struct cl_lock_descr *d0,
			     const struct cl_lock_descr *d1)
{
	int ret;

	ret = lu_fid_cmp(cl_lock_descr_fid(d0), cl_lock_descr_fid(d1));
	if (ret)
		return ret;
	if (d0->cld_end < d1->cld_start)
		return -1;
	if (d0->cld_start > d0->cld_end)
		return 1;
	return 0;
}

static void cl_lock_descr_merge(struct cl_lock_descr *d0,
				const struct cl_lock_descr *d1)
{
	d0->cld_start = min(d0->cld_start, d1->cld_start);
	d0->cld_end = max(d0->cld_end, d1->cld_end);

	if (d1->cld_mode == CLM_WRITE && d0->cld_mode != CLM_WRITE)
		d0->cld_mode = CLM_WRITE;

	if (d1->cld_mode == CLM_GROUP && d0->cld_mode != CLM_GROUP)
		d0->cld_mode = CLM_GROUP;
}

/*
 * Sort locks in lexicographical order of their (fid, start-offset) pairs.
 */
static void cl_io_locks_sort(struct cl_io *io)
{
	int done = 0;

	/* hidden treasure: bubble sort for now. */
	do {
		struct cl_io_lock_link *curr;
		struct cl_io_lock_link *prev;
		struct cl_io_lock_link *temp;

		done = 1;
		prev = NULL;

		list_for_each_entry_safe(curr, temp,
					     &io->ci_lockset.cls_todo,
					     cill_linkage) {
			if (prev != NULL) {
				switch (cl_lock_descr_sort(&prev->cill_descr,
							  &curr->cill_descr)) {
				case 0:
					/*
					 * IMPOSSIBLE: Identical locks are
					 *	     already removed at
					 *	     this point.
					 */
				default:
					LBUG();
				case +1:
					list_move_tail(&curr->cill_linkage,
							   &prev->cill_linkage);
					done = 0;
					continue; /* don't change prev: it's
						   * still "previous" */
				case -1: /* already in order */
					break;
				}
			}
			prev = curr;
		}
	} while (!done);
}

/**
 * Check whether \a queue contains locks matching \a need.
 *
 * \retval +ve there is a matching lock in the \a queue
 * \retval   0 there are no matching locks in the \a queue
 */
int cl_queue_match(const struct list_head *queue,
		   const struct cl_lock_descr *need)
{
       struct cl_io_lock_link *scan;

       list_for_each_entry(scan, queue, cill_linkage) {
	       if (cl_lock_descr_match(&scan->cill_descr, need))
		       return +1;
       }
       return 0;
}
EXPORT_SYMBOL(cl_queue_match);

static int cl_queue_merge(const struct list_head *queue,
			  const struct cl_lock_descr *need)
{
       struct cl_io_lock_link *scan;

       list_for_each_entry(scan, queue, cill_linkage) {
	       if (cl_lock_descr_cmp(&scan->cill_descr, need))
		       continue;
	       cl_lock_descr_merge(&scan->cill_descr, need);
	       CDEBUG(D_VFSTRACE, "lock: %d: [%lu, %lu]\n",
		      scan->cill_descr.cld_mode, scan->cill_descr.cld_start,
		      scan->cill_descr.cld_end);
	       return +1;
       }
       return 0;

}

static int cl_lockset_match(const struct cl_lockset *set,
			    const struct cl_lock_descr *need)
{
	return cl_queue_match(&set->cls_curr, need) ||
	       cl_queue_match(&set->cls_done, need);
}

static int cl_lockset_merge(const struct cl_lockset *set,
			    const struct cl_lock_descr *need)
{
	return cl_queue_merge(&set->cls_todo, need) ||
	       cl_lockset_match(set, need);
}

static int cl_lockset_lock_one(const struct lu_env *env,
			       struct cl_io *io, struct cl_lockset *set,
			       struct cl_io_lock_link *link)
{
	struct cl_lock *lock;
	int	     result;

	lock = cl_lock_request(env, io, &link->cill_descr, "io", io);

	if (!IS_ERR(lock)) {
		link->cill_lock = lock;
		list_move(&link->cill_linkage, &set->cls_curr);
		if (!(link->cill_descr.cld_enq_flags & CEF_ASYNC)) {
			result = cl_wait(env, lock);
			if (result == 0)
				list_move(&link->cill_linkage,
					      &set->cls_done);
		} else
			result = 0;
	} else
		result = PTR_ERR(lock);
	return result;
}

static void cl_lock_link_fini(const struct lu_env *env, struct cl_io *io,
			      struct cl_io_lock_link *link)
{
	struct cl_lock *lock = link->cill_lock;

	list_del_init(&link->cill_linkage);
	if (lock != NULL) {
		cl_lock_release(env, lock, "io", io);
		link->cill_lock = NULL;
	}
	if (link->cill_fini != NULL)
		link->cill_fini(env, link);
}

static int cl_lockset_lock(const struct lu_env *env, struct cl_io *io,
			   struct cl_lockset *set)
{
	struct cl_io_lock_link *link;
	struct cl_io_lock_link *temp;
	struct cl_lock	 *lock;
	int result;

	result = 0;
	list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage) {
		if (!cl_lockset_match(set, &link->cill_descr)) {
			/* XXX some locking to guarantee that locks aren't
			 * expanded in between. */
			result = cl_lockset_lock_one(env, io, set, link);
			if (result != 0)
				break;
		} else
			cl_lock_link_fini(env, io, link);
	}
	if (result == 0) {
		list_for_each_entry_safe(link, temp,
					     &set->cls_curr, cill_linkage) {
			lock = link->cill_lock;
			result = cl_wait(env, lock);
			if (result == 0)
				list_move(&link->cill_linkage,
					      &set->cls_done);
			else
				break;
		}
	}
	return result;
}

/**
 * Takes locks necessary for the current iteration of io.
 *
 * Calls cl_io_operations::cio_lock() top-to-bottom to collect locks required
 * by layers for the current iteration. Then sort locks (to avoid dead-locks),
 * and acquire them.
 */
int cl_io_lock(const struct lu_env *env, struct cl_io *io)
{
	const struct cl_io_slice *scan;
	int result = 0;

	LINVRNT(cl_io_is_loopable(io));
	LINVRNT(io->ci_state == CIS_IT_STARTED);
	LINVRNT(cl_io_invariant(io));

	cl_io_for_each(scan, io) {
		if (scan->cis_iop->op[io->ci_type].cio_lock == NULL)
			continue;
		result = scan->cis_iop->op[io->ci_type].cio_lock(env, scan);
		if (result != 0)
			break;
	}
	if (result == 0) {
		cl_io_locks_sort(io);
		result = cl_lockset_lock(env, io, &io->ci_lockset);
	}
	if (result != 0)
		cl_io_unlock(env, io);
	else
		io->ci_state = CIS_LOCKED;
	return result;
}
EXPORT_SYMBOL(cl_io_lock);

/**
 * Release locks takes by io.
 */
void cl_io_unlock(const struct lu_env *env, struct cl_io *io)
{
	struct cl_lockset	*set;
	struct cl_io_lock_link   *link;
	struct cl_io_lock_link   *temp;
	const struct cl_io_slice *scan;

	LASSERT(cl_io_is_loopable(io));
	LASSERT(CIS_IT_STARTED <= io->ci_state && io->ci_state < CIS_UNLOCKED);
	LINVRNT(cl_io_invariant(io));

	set = &io->ci_lockset;

	list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage)
		cl_lock_link_fini(env, io, link);

	list_for_each_entry_safe(link, temp, &set->cls_curr, cill_linkage)
		cl_lock_link_fini(env, io, link);

	list_for_each_entry_safe(link, temp, &set->cls_done, cill_linkage) {
		cl_unuse(env, link->cill_lock);
		cl_lock_link_fini(env, io, link);
	}
	cl_io_for_each_reverse(scan, io) {
		if (scan->cis_iop->op[io->ci_type].cio_unlock != NULL)
			scan->cis_iop->op[io->ci_type].cio_unlock(env, scan);
	}
	io->ci_state = CIS_UNLOCKED;
	LASSERT(!cl_env_info(env)->clt_counters[CNL_TOP].ctc_nr_locks_acquired);
}
EXPORT_SYMBOL(cl_io_unlock);

/**
 * Prepares next iteration of io.
 *
 * Calls cl_io_operations::cio_iter_init() top-to-bottom. This exists to give
 * layers a chance to modify io parameters, e.g., so that lov can restrict io
 * to a single stripe.
 */
int cl_io_iter_init(const struct lu_env *env, struct cl_io *io)
{
	const struct cl_io_slice *scan;
	int result;

	LINVRNT(cl_io_is_loopable(io));
	LINVRNT(io->ci_state == CIS_INIT || io->ci_state == CIS_IT_ENDED);
	LINVRNT(cl_io_invariant(io));

	result = 0;
	cl_io_for_each(scan, io) {
		if (scan->cis_iop->op[io->ci_type].cio_iter_init == NULL)
			continue;
		result = scan->cis_iop->op[io->ci_type].cio_iter_init(env,
								      scan);
		if (result != 0)
			break;
	}
	if (result == 0)
		io->ci_state = CIS_IT_STARTED;
	return result;
}
EXPORT_SYMBOL(cl_io_iter_init);

/**
 * Finalizes io iteration.
 *
 * Calls cl_io_operations::cio_iter_fini() bottom-to-top.
 */
void cl_io_iter_fini(const struct lu_env *env, struct cl_io *io)
{
	const struct cl_io_slice *scan;

	LINVRNT(cl_io_is_loopable(io));
	LINVRNT(io->ci_state == CIS_UNLOCKED);
	LINVRNT(cl_io_invariant(io));

	cl_io_for_each_reverse(scan, io) {
		if (scan->cis_iop->op[io->ci_type].cio_iter_fini != NULL)
			scan->cis_iop->op[io->ci_type].cio_iter_fini(env, scan);
	}
	io->ci_state = CIS_IT_ENDED;
}
EXPORT_SYMBOL(cl_io_iter_fini);

/**
 * Records that read or write io progressed \a nob bytes forward.
 */
void cl_io_rw_advance(const struct lu_env *env, struct cl_io *io, size_t nob)
{
	const struct cl_io_slice *scan;

	LINVRNT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE ||
		nob == 0);
	LINVRNT(cl_io_is_loopable(io));
	LINVRNT(cl_io_invariant(io));

	io->u.ci_rw.crw_pos   += nob;
	io->u.ci_rw.crw_count -= nob;

	/* layers have to be notified. */
	cl_io_for_each_reverse(scan, io) {
		if (scan->cis_iop->op[io->ci_type].cio_advance != NULL)
			scan->cis_iop->op[io->ci_type].cio_advance(env, scan,
								   nob);
	}
}
EXPORT_SYMBOL(cl_io_rw_advance);

/**
 * Adds a lock to a lockset.
 */
int cl_io_lock_add(const struct lu_env *env, struct cl_io *io,
		   struct cl_io_lock_link *link)
{
	int result;

	if (cl_lockset_merge(&io->ci_lockset, &link->cill_descr))
		result = +1;
	else {
		list_add(&link->cill_linkage, &io->ci_lockset.cls_todo);
		result = 0;
	}
	return result;
}
EXPORT_SYMBOL(cl_io_lock_add);

static void cl_free_io_lock_link(const struct lu_env *env,
				 struct cl_io_lock_link *link)
{
	OBD_FREE_PTR(link);
}

/**
 * Allocates new lock link, and uses it to add a lock to a lockset.
 */
int cl_io_lock_alloc_add(const struct lu_env *env, struct cl_io *io,
			 struct cl_lock_descr *descr)
{
	struct cl_io_lock_link *link;
	int result;

	OBD_ALLOC_PTR(link);
	if (link != NULL) {
		link->cill_descr     = *descr;
		link->cill_fini      = cl_free_io_lock_link;
		result = cl_io_lock_add(env, io, link);
		if (result) /* lock match */
			link->cill_fini(env, link);
	} else
		result = -ENOMEM;

	return result;
}
EXPORT_SYMBOL(cl_io_lock_alloc_add);

/**
 * Starts io by calling cl_io_operations::cio_start() top-to-bottom.
 */
int cl_io_start(const struct lu_env *env, struct cl_io *io)
{
	const struct cl_io_slice *scan;
	int result = 0;

	LINVRNT(cl_io_is_loopable(io));
	LINVRNT(io->ci_state == CIS_LOCKED);
	LINVRNT(cl_io_invariant(io));

	io->ci_state = CIS_IO_GOING;
	cl_io_for_each(scan, io) {
		if (scan->cis_iop->op[io->ci_type].cio_start == NULL)
			continue;
		result = scan->cis_iop->op[io->ci_type].cio_start(env, scan);
		if (result != 0)
			break;
	}
	if (result >= 0)
		result = 0;
	return result;
}
EXPORT_SYMBOL(cl_io_start);

/**
 * Wait until current io iteration is finished by calling
 * cl_io_operations::cio_end() bottom-to-top.
 */
void cl_io_end(const struct lu_env *env, struct cl_io *io)
{
	const struct cl_io_slice *scan;

	LINVRNT(cl_io_is_loopable(io));
	LINVRNT(io->ci_state == CIS_IO_GOING);
	LINVRNT(cl_io_invariant(io));

	cl_io_for_each_reverse(scan, io) {
		if (scan->cis_iop->op[io->ci_type].cio_end != NULL)
			scan->cis_iop->op[io->ci_type].cio_end(env, scan);
		/* TODO: error handling. */
	}
	io->ci_state = CIS_IO_FINISHED;
}
EXPORT_SYMBOL(cl_io_end);

static const struct cl_page_slice *
cl_io_slice_page(const struct cl_io_slice *ios, struct cl_page *page)
{
	const struct cl_page_slice *slice;

	slice = cl_page_at(page, ios->cis_obj->co_lu.lo_dev->ld_type);
	LINVRNT(slice != NULL);
	return slice;
}

/**
 * True iff \a page is within \a io range.
 */
static int cl_page_in_io(const struct cl_page *page, const struct cl_io *io)
{
	int     result = 1;
	loff_t  start;
	loff_t  end;
	pgoff_t idx;

	idx = page->cp_index;
	switch (io->ci_type) {
	case CIT_READ:
	case CIT_WRITE:
		/*
		 * check that [start, end) and [pos, pos + count) extents
		 * overlap.
		 */
		if (!cl_io_is_append(io)) {
			const struct cl_io_rw_common *crw = &(io->u.ci_rw);
			start = cl_offset(page->cp_obj, idx);
			end   = cl_offset(page->cp_obj, idx + 1);
			result = crw->crw_pos < end &&
				 start < crw->crw_pos + crw->crw_count;
		}
		break;
	case CIT_FAULT:
		result = io->u.ci_fault.ft_index == idx;
		break;
	default:
		LBUG();
	}
	return result;
}

/**
 * Called by read io, when page has to be read from the server.
 *
 * \see cl_io_operations::cio_read_page()
 */
int cl_io_read_page(const struct lu_env *env, struct cl_io *io,
		    struct cl_page *page)
{
	const struct cl_io_slice *scan;
	struct cl_2queue	 *queue;
	int		       result = 0;

	LINVRNT(io->ci_type == CIT_READ || io->ci_type == CIT_FAULT);
	LINVRNT(cl_page_is_owned(page, io));
	LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED);
	LINVRNT(cl_page_in_io(page, io));
	LINVRNT(cl_io_invariant(io));

	queue = &io->ci_queue;

	cl_2queue_init(queue);
	/*
	 * ->cio_read_page() methods called in the loop below are supposed to
	 * never block waiting for network (the only subtle point is the
	 * creation of new pages for read-ahead that might result in cache
	 * shrinking, but currently only clean pages are shrunk and this
	 * requires no network io).
	 *
	 * Should this ever starts blocking, retry loop would be needed for
	 * "parallel io" (see CLO_REPEAT loops in cl_lock.c).
	 */
	cl_io_for_each(scan, io) {
		if (scan->cis_iop->cio_read_page != NULL) {
			const struct cl_page_slice *slice;

			slice = cl_io_slice_page(scan, page);
			LINVRNT(slice != NULL);
			result = scan->cis_iop->cio_read_page(env, scan, slice);
			if (result != 0)
				break;
		}
	}
	if (result == 0)
		result = cl_io_submit_rw(env, io, CRT_READ, queue);
	/*
	 * Unlock unsent pages in case of error.
	 */
	cl_page_list_disown(env, io, &queue->c2_qin);
	cl_2queue_fini(env, queue);
	return result;
}
EXPORT_SYMBOL(cl_io_read_page);

/**
 * Called by write io to prepare page to receive data from user buffer.
 *
 * \see cl_io_operations::cio_prepare_write()
 */
int cl_io_prepare_write(const struct lu_env *env, struct cl_io *io,
			struct cl_page *page, unsigned from, unsigned to)
{
	const struct cl_io_slice *scan;
	int result = 0;

	LINVRNT(io->ci_type == CIT_WRITE);
	LINVRNT(cl_page_is_owned(page, io));
	LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED);
	LINVRNT(cl_io_invariant(io));
	LASSERT(cl_page_in_io(page, io));

	cl_io_for_each_reverse(scan, io) {
		if (scan->cis_iop->cio_prepare_write != NULL) {
			const struct cl_page_slice *slice;

			slice = cl_io_slice_page(scan, page);
			result = scan->cis_iop->cio_prepare_write(env, scan,
								  slice,
								  from, to);
			if (result != 0)
				break;
		}
	}
	return result;
}
EXPORT_SYMBOL(cl_io_prepare_write);

/**
 * Called by write io after user data were copied into a page.
 *
 * \see cl_io_operations::cio_commit_write()
 */
int cl_io_commit_write(const struct lu_env *env, struct cl_io *io,
		       struct cl_page *page, unsigned from, unsigned to)
{
	const struct cl_io_slice *scan;
	int result = 0;

	LINVRNT(io->ci_type == CIT_WRITE);
	LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED);
	LINVRNT(cl_io_invariant(io));
	/*
	 * XXX Uh... not nice. Top level cl_io_commit_write() call (vvp->lov)
	 * already called cl_page_cache_add(), moving page into CPS_CACHED
	 * state. Better (and more general) way of dealing with such situation
	 * is needed.
	 */
	LASSERT(cl_page_is_owned(page, io) || page->cp_parent != NULL);
	LASSERT(cl_page_in_io(page, io));

	cl_io_for_each(scan, io) {
		if (scan->cis_iop->cio_commit_write != NULL) {
			const struct cl_page_slice *slice;

			slice = cl_io_slice_page(scan, page);
			result = scan->cis_iop->cio_commit_write(env, scan,
								 slice,
								 from, to);
			if (result != 0)
				break;
		}
	}
	LINVRNT(result <= 0);
	return result;
}
EXPORT_SYMBOL(cl_io_commit_write);

/**
 * Submits a list of pages for immediate io.
 *
 * After the function gets returned, The submitted pages are moved to
 * queue->c2_qout queue, and queue->c2_qin contain both the pages don't need
 * to be submitted, and the pages are errant to submit.
 *
 * \returns 0 if at least one page was submitted, error code otherwise.
 * \see cl_io_operations::cio_submit()
 */
int cl_io_submit_rw(const struct lu_env *env, struct cl_io *io,
		    enum cl_req_type crt, struct cl_2queue *queue)
{
	const struct cl_io_slice *scan;
	int result = 0;

	LINVRNT(crt < ARRAY_SIZE(scan->cis_iop->req_op));

	cl_io_for_each(scan, io) {
		if (scan->cis_iop->req_op[crt].cio_submit == NULL)
			continue;
		result = scan->cis_iop->req_op[crt].cio_submit(env, scan, crt,
							       queue);
		if (result != 0)
			break;
	}
	/*
	 * If ->cio_submit() failed, no pages were sent.
	 */
	LASSERT(ergo(result != 0, list_empty(&queue->c2_qout.pl_pages)));
	return result;
}
EXPORT_SYMBOL(cl_io_submit_rw);

/**
 * Submit a sync_io and wait for the IO to be finished, or error happens.
 * If \a timeout is zero, it means to wait for the IO unconditionally.
 */
int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io,
		      enum cl_req_type iot, struct cl_2queue *queue,
		      long timeout)
{
	struct cl_sync_io *anchor = &cl_env_info(env)->clt_anchor;
	struct cl_page *pg;
	int rc;

	cl_page_list_for_each(pg, &queue->c2_qin) {
		LASSERT(pg->cp_sync_io == NULL);
		pg->cp_sync_io = anchor;
	}

	cl_sync_io_init(anchor, queue->c2_qin.pl_nr);
	rc = cl_io_submit_rw(env, io, iot, queue);
	if (rc == 0) {
		/*
		 * If some pages weren't sent for any reason (e.g.,
		 * read found up-to-date pages in the cache, or write found
		 * clean pages), count them as completed to avoid infinite
		 * wait.
		 */
		 cl_page_list_for_each(pg, &queue->c2_qin) {
			pg->cp_sync_io = NULL;
			cl_sync_io_note(anchor, +1);
		 }

		 /* wait for the IO to be finished. */
		 rc = cl_sync_io_wait(env, io, &queue->c2_qout,
				      anchor, timeout);
	} else {
		LASSERT(list_empty(&queue->c2_qout.pl_pages));
		cl_page_list_for_each(pg, &queue->c2_qin)
			pg->cp_sync_io = NULL;
	}
	return rc;
}
EXPORT_SYMBOL(cl_io_submit_sync);

/**
 * Cancel an IO which has been submitted by cl_io_submit_rw.
 */
int cl_io_cancel(const struct lu_env *env, struct cl_io *io,
		 struct cl_page_list *queue)
{
	struct cl_page *page;
	int result = 0;

	CERROR("Canceling ongoing page trasmission\n");
	cl_page_list_for_each(page, queue) {
		int rc;

		LINVRNT(cl_page_in_io(page, io));
		rc = cl_page_cancel(env, page);
		result = result ?: rc;
	}
	return result;
}
EXPORT_SYMBOL(cl_io_cancel);

/**
 * Main io loop.
 *
 * Pumps io through iterations calling
 *
 *    - cl_io_iter_init()
 *
 *    - cl_io_lock()
 *
 *    - cl_io_start()
 *
 *    - cl_io_end()
 *
 *    - cl_io_unlock()
 *
 *    - cl_io_iter_fini()
 *
 * repeatedly until there is no more io to do.
 */
int cl_io_loop(const struct lu_env *env, struct cl_io *io)
{
	int result   = 0;

	LINVRNT(cl_io_is_loopable(io));

	do {
		size_t nob;

		io->ci_continue = 0;
		result = cl_io_iter_init(env, io);
		if (result == 0) {
			nob    = io->ci_nob;
			result = cl_io_lock(env, io);
			if (result == 0) {
				/*
				 * Notify layers that locks has been taken,
				 * and do actual i/o.
				 *
				 *   - llite: kms, short read;
				 *   - llite: generic_file_read();
				 */
				result = cl_io_start(env, io);
				/*
				 * Send any remaining pending
				 * io, etc.
				 *
				 *   - llite: ll_rw_stats_tally.
				 */
				cl_io_end(env, io);
				cl_io_unlock(env, io);
				cl_io_rw_advance(env, io, io->ci_nob - nob);
			}
		}
		cl_io_iter_fini(env, io);
	} while (result == 0 && io->ci_continue);
	if (result == 0)
		result = io->ci_result;
	return result < 0 ? result : 0;
}
EXPORT_SYMBOL(cl_io_loop);

/**
 * Adds io slice to the cl_io.
 *
 * This is called by cl_object_operations::coo_io_init() methods to add a
 * per-layer state to the io. New state is added at the end of
 * cl_io::ci_layers list, that is, it is at the bottom of the stack.
 *
 * \see cl_lock_slice_add(), cl_req_slice_add(), cl_page_slice_add()
 */
void cl_io_slice_add(struct cl_io *io, struct cl_io_slice *slice,
		     struct cl_object *obj,
		     const struct cl_io_operations *ops)
{
	struct list_head *linkage = &slice->cis_linkage;

	LASSERT((linkage->prev == NULL && linkage->next == NULL) ||
		list_empty(linkage));

	list_add_tail(linkage, &io->ci_layers);
	slice->cis_io  = io;
	slice->cis_obj = obj;
	slice->cis_iop = ops;
}
EXPORT_SYMBOL(cl_io_slice_add);

/**
 * Initializes page list.
 */
void cl_page_list_init(struct cl_page_list *plist)
{
	plist->pl_nr = 0;
	INIT_LIST_HEAD(&plist->pl_pages);
	plist->pl_owner = current;
}
EXPORT_SYMBOL(cl_page_list_init);

/**
 * Adds a page to a page list.
 */
void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page)
{
	/* it would be better to check that page is owned by "current" io, but
	 * it is not passed here. */
	LASSERT(page->cp_owner != NULL);
	LINVRNT(plist->pl_owner == current);

	lockdep_off();
	mutex_lock(&page->cp_mutex);
	lockdep_on();
	LASSERT(list_empty(&page->cp_batch));
	list_add_tail(&page->cp_batch, &plist->pl_pages);
	++plist->pl_nr;
	lu_ref_add_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist);
	cl_page_get(page);
}
EXPORT_SYMBOL(cl_page_list_add);

/**
 * Removes a page from a page list.
 */
void cl_page_list_del(const struct lu_env *env,
		      struct cl_page_list *plist, struct cl_page *page)
{
	LASSERT(plist->pl_nr > 0);
	LINVRNT(plist->pl_owner == current);

	list_del_init(&page->cp_batch);
	lockdep_off();
	mutex_unlock(&page->cp_mutex);
	lockdep_on();
	--plist->pl_nr;
	lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist);
	cl_page_put(env, page);
}
EXPORT_SYMBOL(cl_page_list_del);

/**
 * Moves a page from one page list to another.
 */
void cl_page_list_move(struct cl_page_list *dst, struct cl_page_list *src,
		       struct cl_page *page)
{
	LASSERT(src->pl_nr > 0);
	LINVRNT(dst->pl_owner == current);
	LINVRNT(src->pl_owner == current);

	list_move_tail(&page->cp_batch, &dst->pl_pages);
	--src->pl_nr;
	++dst->pl_nr;
	lu_ref_set_at(&page->cp_reference, &page->cp_queue_ref, "queue",
		      src, dst);
}
EXPORT_SYMBOL(cl_page_list_move);

/**
 * splice the cl_page_list, just as list head does
 */
void cl_page_list_splice(struct cl_page_list *list, struct cl_page_list *head)
{
	struct cl_page *page;
	struct cl_page *tmp;

	LINVRNT(list->pl_owner == current);
	LINVRNT(head->pl_owner == current);

	cl_page_list_for_each_safe(page, tmp, list)
		cl_page_list_move(head, list, page);
}
EXPORT_SYMBOL(cl_page_list_splice);

void cl_page_disown0(const struct lu_env *env,
		     struct cl_io *io, struct cl_page *pg);

/**
 * Disowns pages in a queue.
 */
void cl_page_list_disown(const struct lu_env *env,
			 struct cl_io *io, struct cl_page_list *plist)
{
	struct cl_page *page;
	struct cl_page *temp;

	LINVRNT(plist->pl_owner == current);

	cl_page_list_for_each_safe(page, temp, plist) {
		LASSERT(plist->pl_nr > 0);

		list_del_init(&page->cp_batch);
		lockdep_off();
		mutex_unlock(&page->cp_mutex);
		lockdep_on();
		--plist->pl_nr;
		/*
		 * cl_page_disown0 rather than usual cl_page_disown() is used,
		 * because pages are possibly in CPS_FREEING state already due
		 * to the call to cl_page_list_discard().
		 */
		/*
		 * XXX cl_page_disown0() will fail if page is not locked.
		 */
		cl_page_disown0(env, io, page);
		lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue",
			      plist);
		cl_page_put(env, page);
	}
}
EXPORT_SYMBOL(cl_page_list_disown);

/**
 * Releases pages from queue.
 */
void cl_page_list_fini(const struct lu_env *env, struct cl_page_list *plist)
{
	struct cl_page *page;
	struct cl_page *temp;

	LINVRNT(plist->pl_owner == current);

	cl_page_list_for_each_safe(page, temp, plist)
		cl_page_list_del(env, plist, page);
	LASSERT(plist->pl_nr == 0);
}
EXPORT_SYMBOL(cl_page_list_fini);

/**
 * Owns all pages in a queue.
 */
int cl_page_list_own(const struct lu_env *env,
		     struct cl_io *io, struct cl_page_list *plist)
{
	struct cl_page *page;
	struct cl_page *temp;
	pgoff_t index = 0;
	int result;

	LINVRNT(plist->pl_owner == current);

	result = 0;
	cl_page_list_for_each_safe(page, temp, plist) {
		LASSERT(index <= page->cp_index);
		index = page->cp_index;
		if (cl_page_own(env, io, page) == 0)
			result = result ?: page->cp_error;
		else
			cl_page_list_del(env, plist, page);
	}
	return result;
}
EXPORT_SYMBOL(cl_page_list_own);

/**
 * Assumes all pages in a queue.
 */
void cl_page_list_assume(const struct lu_env *env,
			 struct cl_io *io, struct cl_page_list *plist)
{
	struct cl_page *page;

	LINVRNT(plist->pl_owner == current);

	cl_page_list_for_each(page, plist)
		cl_page_assume(env, io, page);
}
EXPORT_SYMBOL(cl_page_list_assume);

/**
 * Discards all pages in a queue.
 */
void cl_page_list_discard(const struct lu_env *env, struct cl_io *io,
			  struct cl_page_list *plist)
{
	struct cl_page *page;

	LINVRNT(plist->pl_owner == current);
	cl_page_list_for_each(page, plist)
		cl_page_discard(env, io, page);
}
EXPORT_SYMBOL(cl_page_list_discard);

/**
 * Unmaps all pages in a queue from user virtual memory.
 */
int cl_page_list_unmap(const struct lu_env *env, struct cl_io *io,
			struct cl_page_list *plist)
{
	struct cl_page *page;
	int result;

	LINVRNT(plist->pl_owner == current);
	result = 0;
	cl_page_list_for_each(page, plist) {
		result = cl_page_unmap(env, io, page);
		if (result != 0)
			break;
	}
	return result;
}
EXPORT_SYMBOL(cl_page_list_unmap);

/**
 * Initialize dual page queue.
 */
void cl_2queue_init(struct cl_2queue *queue)
{
	cl_page_list_init(&queue->c2_qin);
	cl_page_list_init(&queue->c2_qout);
}
EXPORT_SYMBOL(cl_2queue_init);

/**
 * Add a page to the incoming page list of 2-queue.
 */
void cl_2queue_add(struct cl_2queue *queue, struct cl_page *page)
{
	cl_page_list_add(&queue->c2_qin, page);
}
EXPORT_SYMBOL(cl_2queue_add);

/**
 * Disown pages in both lists of a 2-queue.
 */
void cl_2queue_disown(const struct lu_env *env,
		      struct cl_io *io, struct cl_2queue *queue)
{
	cl_page_list_disown(env, io, &queue->c2_qin);
	cl_page_list_disown(env, io, &queue->c2_qout);
}
EXPORT_SYMBOL(cl_2queue_disown);

/**
 * Discard (truncate) pages in both lists of a 2-queue.
 */
void cl_2queue_discard(const struct lu_env *env,
		       struct cl_io *io, struct cl_2queue *queue)
{
	cl_page_list_discard(env, io, &queue->c2_qin);
	cl_page_list_discard(env, io, &queue->c2_qout);
}
EXPORT_SYMBOL(cl_2queue_discard);

/**
 * Assume to own the pages in cl_2queue
 */
void cl_2queue_assume(const struct lu_env *env,
		      struct cl_io *io, struct cl_2queue *queue)
{
	cl_page_list_assume(env, io, &queue->c2_qin);
	cl_page_list_assume(env, io, &queue->c2_qout);
}
EXPORT_SYMBOL(cl_2queue_assume);

/**
 * Finalize both page lists of a 2-queue.
 */
void cl_2queue_fini(const struct lu_env *env, struct cl_2queue *queue)
{
	cl_page_list_fini(env, &queue->c2_qout);
	cl_page_list_fini(env, &queue->c2_qin);
}
EXPORT_SYMBOL(cl_2queue_fini);

/**
 * Initialize a 2-queue to contain \a page in its incoming page list.
 */
void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page)
{
	cl_2queue_init(queue);
	cl_2queue_add(queue, page);
}
EXPORT_SYMBOL(cl_2queue_init_page);

/**
 * Returns top-level io.
 *
 * \see cl_object_top(), cl_page_top().
 */
struct cl_io *cl_io_top(struct cl_io *io)
{
	while (io->ci_parent != NULL)
		io = io->ci_parent;
	return io;
}
EXPORT_SYMBOL(cl_io_top);

/**
 * Prints human readable representation of \a io to the \a f.
 */
void cl_io_print(const struct lu_env *env, void *cookie,
		 lu_printer_t printer, const struct cl_io *io)
{
}

/**
 * Adds request slice to the compound request.
 *
 * This is called by cl_device_operations::cdo_req_init() methods to add a
 * per-layer state to the request. New state is added at the end of
 * cl_req::crq_layers list, that is, it is at the bottom of the stack.
 *
 * \see cl_lock_slice_add(), cl_page_slice_add(), cl_io_slice_add()
 */
void cl_req_slice_add(struct cl_req *req, struct cl_req_slice *slice,
		      struct cl_device *dev,
		      const struct cl_req_operations *ops)
{
	list_add_tail(&slice->crs_linkage, &req->crq_layers);
	slice->crs_dev = dev;
	slice->crs_ops = ops;
	slice->crs_req = req;
}
EXPORT_SYMBOL(cl_req_slice_add);

static void cl_req_free(const struct lu_env *env, struct cl_req *req)
{
	unsigned i;

	LASSERT(list_empty(&req->crq_pages));
	LASSERT(req->crq_nrpages == 0);
	LINVRNT(list_empty(&req->crq_layers));
	LINVRNT(equi(req->crq_nrobjs > 0, req->crq_o != NULL));

	if (req->crq_o != NULL) {
		for (i = 0; i < req->crq_nrobjs; ++i) {
			struct cl_object *obj = req->crq_o[i].ro_obj;
			if (obj != NULL) {
				lu_object_ref_del_at(&obj->co_lu,
						     &req->crq_o[i].ro_obj_ref,
						     "cl_req", req);
				cl_object_put(env, obj);
			}
		}
		OBD_FREE(req->crq_o, req->crq_nrobjs * sizeof(req->crq_o[0]));
	}
	OBD_FREE_PTR(req);
}

static int cl_req_init(const struct lu_env *env, struct cl_req *req,
		       struct cl_page *page)
{
	struct cl_device     *dev;
	struct cl_page_slice *slice;
	int result;

	result = 0;
	page = cl_page_top(page);
	do {
		list_for_each_entry(slice, &page->cp_layers, cpl_linkage) {
			dev = lu2cl_dev(slice->cpl_obj->co_lu.lo_dev);
			if (dev->cd_ops->cdo_req_init != NULL) {
				result = dev->cd_ops->cdo_req_init(env,
								   dev, req);
				if (result != 0)
					break;
			}
		}
		page = page->cp_child;
	} while (page != NULL && result == 0);
	return result;
}

/**
 * Invokes per-request transfer completion call-backs
 * (cl_req_operations::cro_completion()) bottom-to-top.
 */
void cl_req_completion(const struct lu_env *env, struct cl_req *req, int rc)
{
	struct cl_req_slice *slice;

	/*
	 * for the lack of list_for_each_entry_reverse_safe()...
	 */
	while (!list_empty(&req->crq_layers)) {
		slice = list_entry(req->crq_layers.prev,
				       struct cl_req_slice, crs_linkage);
		list_del_init(&slice->crs_linkage);
		if (slice->crs_ops->cro_completion != NULL)
			slice->crs_ops->cro_completion(env, slice, rc);
	}
	cl_req_free(env, req);
}
EXPORT_SYMBOL(cl_req_completion);

/**
 * Allocates new transfer request.
 */
struct cl_req *cl_req_alloc(const struct lu_env *env, struct cl_page *page,
			    enum cl_req_type crt, int nr_objects)
{
	struct cl_req *req;

	LINVRNT(nr_objects > 0);

	OBD_ALLOC_PTR(req);
	if (req != NULL) {
		int result;

		OBD_ALLOC(req->crq_o, nr_objects * sizeof(req->crq_o[0]));
		if (req->crq_o != NULL) {
			req->crq_nrobjs = nr_objects;
			req->crq_type = crt;
			INIT_LIST_HEAD(&req->crq_pages);
			INIT_LIST_HEAD(&req->crq_layers);
			result = cl_req_init(env, req, page);
		} else
			result = -ENOMEM;
		if (result != 0) {
			cl_req_completion(env, req, result);
			req = ERR_PTR(result);
		}
	} else
		req = ERR_PTR(-ENOMEM);
	return req;
}
EXPORT_SYMBOL(cl_req_alloc);

/**
 * Adds a page to a request.
 */
void cl_req_page_add(const struct lu_env *env,
		     struct cl_req *req, struct cl_page *page)
{
	struct cl_object  *obj;
	struct cl_req_obj *rqo;
	int i;

	page = cl_page_top(page);

	LASSERT(list_empty(&page->cp_flight));
	LASSERT(page->cp_req == NULL);

	CL_PAGE_DEBUG(D_PAGE, env, page, "req %p, %d, %u\n",
		      req, req->crq_type, req->crq_nrpages);

	list_add_tail(&page->cp_flight, &req->crq_pages);
	++req->crq_nrpages;
	page->cp_req = req;
	obj = cl_object_top(page->cp_obj);
	for (i = 0, rqo = req->crq_o; obj != rqo->ro_obj; ++i, ++rqo) {
		if (rqo->ro_obj == NULL) {
			rqo->ro_obj = obj;
			cl_object_get(obj);
			lu_object_ref_add_at(&obj->co_lu, &rqo->ro_obj_ref,
					     "cl_req", req);
			break;
		}
	}
	LASSERT(i < req->crq_nrobjs);
}
EXPORT_SYMBOL(cl_req_page_add);

/**
 * Removes a page from a request.
 */
void cl_req_page_done(const struct lu_env *env, struct cl_page *page)
{
	struct cl_req *req = page->cp_req;

	page = cl_page_top(page);

	LASSERT(!list_empty(&page->cp_flight));
	LASSERT(req->crq_nrpages > 0);

	list_del_init(&page->cp_flight);
	--req->crq_nrpages;
	page->cp_req = NULL;
}
EXPORT_SYMBOL(cl_req_page_done);

/**
 * Notifies layers that request is about to depart by calling
 * cl_req_operations::cro_prep() top-to-bottom.
 */
int cl_req_prep(const struct lu_env *env, struct cl_req *req)
{
	int i;
	int result;
	const struct cl_req_slice *slice;

	/*
	 * Check that the caller of cl_req_alloc() didn't lie about the number
	 * of objects.
	 */
	for (i = 0; i < req->crq_nrobjs; ++i)
		LASSERT(req->crq_o[i].ro_obj != NULL);

	result = 0;
	list_for_each_entry(slice, &req->crq_layers, crs_linkage) {
		if (slice->crs_ops->cro_prep != NULL) {
			result = slice->crs_ops->cro_prep(env, slice);
			if (result != 0)
				break;
		}
	}
	return result;
}
EXPORT_SYMBOL(cl_req_prep);

/**
 * Fills in attributes that are passed to server together with transfer. Only
 * attributes from \a flags may be touched. This can be called multiple times
 * for the same request.
 */
void cl_req_attr_set(const struct lu_env *env, struct cl_req *req,
		     struct cl_req_attr *attr, obd_valid flags)
{
	const struct cl_req_slice *slice;
	struct cl_page	    *page;
	int i;

	LASSERT(!list_empty(&req->crq_pages));

	/* Take any page to use as a model. */
	page = list_entry(req->crq_pages.next, struct cl_page, cp_flight);

	for (i = 0; i < req->crq_nrobjs; ++i) {
		list_for_each_entry(slice, &req->crq_layers, crs_linkage) {
			const struct cl_page_slice *scan;
			const struct cl_object     *obj;

			scan = cl_page_at(page,
					  slice->crs_dev->cd_lu_dev.ld_type);
			LASSERT(scan != NULL);
			obj = scan->cpl_obj;
			if (slice->crs_ops->cro_attr_set != NULL)
				slice->crs_ops->cro_attr_set(env, slice, obj,
							     attr + i, flags);
		}
	}
}
EXPORT_SYMBOL(cl_req_attr_set);

/* XXX complete(), init_completion(), and wait_for_completion(), until they are
 * implemented in libcfs. */
# include <linux/sched.h>

/**
 * Initialize synchronous io wait anchor, for transfer of \a nrpages pages.
 */
void cl_sync_io_init(struct cl_sync_io *anchor, int nrpages)
{
	init_waitqueue_head(&anchor->csi_waitq);
	atomic_set(&anchor->csi_sync_nr, nrpages);
	atomic_set(&anchor->csi_barrier, nrpages > 0);
	anchor->csi_sync_rc = 0;
}
EXPORT_SYMBOL(cl_sync_io_init);

/**
 * Wait until all transfer completes. Transfer completion routine has to call
 * cl_sync_io_note() for every page.
 */
int cl_sync_io_wait(const struct lu_env *env, struct cl_io *io,
		    struct cl_page_list *queue, struct cl_sync_io *anchor,
		    long timeout)
{
	struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(timeout),
						  NULL, NULL, NULL);
	int rc;

	LASSERT(timeout >= 0);

	rc = l_wait_event(anchor->csi_waitq,
			  atomic_read(&anchor->csi_sync_nr) == 0,
			  &lwi);
	if (rc < 0) {
		CERROR("SYNC IO failed with error: %d, try to cancel "
		       "%d remaining pages\n",
		       rc, atomic_read(&anchor->csi_sync_nr));

		(void)cl_io_cancel(env, io, queue);

		lwi = (struct l_wait_info) { 0 };
		(void)l_wait_event(anchor->csi_waitq,
				   atomic_read(&anchor->csi_sync_nr) == 0,
				   &lwi);
	} else {
		rc = anchor->csi_sync_rc;
	}
	LASSERT(atomic_read(&anchor->csi_sync_nr) == 0);
	cl_page_list_assume(env, io, queue);

	/* wait until cl_sync_io_note() has done wakeup */
	while (unlikely(atomic_read(&anchor->csi_barrier) != 0)) {
		cpu_relax();
	}

	POISON(anchor, 0x5a, sizeof(*anchor));
	return rc;
}
EXPORT_SYMBOL(cl_sync_io_wait);

/**
 * Indicate that transfer of a single page completed.
 */
void cl_sync_io_note(struct cl_sync_io *anchor, int ioret)
{
	if (anchor->csi_sync_rc == 0 && ioret < 0)
		anchor->csi_sync_rc = ioret;
	/*
	 * Synchronous IO done without releasing page lock (e.g., as a part of
	 * ->{prepare,commit}_write(). Completion is used to signal the end of
	 * IO.
	 */
	LASSERT(atomic_read(&anchor->csi_sync_nr) > 0);
	if (atomic_dec_and_test(&anchor->csi_sync_nr)) {
		wake_up_all(&anchor->csi_waitq);
		/* it's safe to nuke or reuse anchor now */
		atomic_set(&anchor->csi_barrier, 0);
	}
}
EXPORT_SYMBOL(cl_sync_io_note);

redpajama_set_name: RedPajamaGithub


text:
Anne Yarbrough
Refinery derives its power from juxtapositions: nature and artifice, past and present, intention and outcome. Like Wallace Steven's jar, the refinery is a touchstone and a human presence:
It owns the landscape
rises into the sky declares
dominion over the river
The book is a meditation on what lasts and what disappears, the light changing above the river, the landscape changing over the years, the refinery – which we learn through these poems to see as a chalice of human desire, memory, misstep, and beauty. Yarbrough's poems teach us that everything human desecrates, and everything human is sacred.
— Anne Colwell, Poetry Editor, Delmarva Review
Anne Yarbrough's poems recall Blake's "Dark Satanic Mills," when the industrial age impacted the British way of life. She is poet, historian, critic, activist, and has studied a Delaware refinery's tenuous dance with the natural world. In this new age of ecological disaster we are the better for her keen attention and clarion call.
— Richard Peabody, Publisher and Editor, Gargoyle Magazine
In Refinery, poet Anne Yarbrough presents an immediate, living landscape both imposing and vulnerable. These poems offer "an example of the end of nature," layered with silt, water, mud, civilizations, development, and destruction. Refinery is as carefully constructed as a cathedral or an opera, and it similarly builds on both ancient and modern mythologies as it traces the lineage of "petroleum and all her daughters." History is interrogated and interrupted, eventually dissolving into the poet's white open space.
— Courtney Bambrick, Poetry Editor Philadelphia Stories
Anne Yarbrough's Refinery feels fully conceived as a whole as it carries the reader through a landscape with a single towering presence in poems that keep shifting perspective and angle. I was drawn in by the poems' singular focus, attention, the rich and resonant language, painterly and atmospheric details, and the layers of science, industry, history, and exploitation explored through this deep dive into a single place and the lives and relationships of those connected to this geography.
— Hayden Saunier, 2021 Dogfish Head Poetry Prize Judge and Author, A Cartography of Home
a passing acquaintance with grief
The haunting lyricism of Jamie Brown's poetry does not turn away from the daily vicissitudes of life and all its wounds and diminishments; but these poems are complemented by a series of trope-rich meditations — "The Delaware Bay Poems" — that are evocatively tuned to the immensity of the momentary present.
— Merrill Leffler, author of Mark the Music, publisher of Dryad Press
The power in these poems gathers like a storm over water. Deaths and lesser losses pile up wave-like until we question–how do we, each of us, survive the small, quotidian hurts, to say nothing of the erosions of time, and the unthinkable finality of murders. The closing section, "The Delaware Bay Poems," is the beautiful culmination of a career-long habit of quiet observation of the day and night time worlds.
— H. A. Maxson, Author of Lemon Light and On the Sonnets of Robert Frost
Birds of New Jersey
Susan Rothbard
(January 11th, 2021— Lewes, Delaware) Susan Rothbard, a resident of Fairfield, N.J. was named as the Dogfish Head Poetry Prize Laureate for 2020 in a competition marked by cancellation of the award presentation gala at the Dogfish Head Inn in Lewes, Delaware and other delays caused by complications from the Covid-19 pandemic. Rothbard earned her MFA in creative writing from Fairleigh Dickinson University and a Doctor of Letters from Drew University. She is a retired teacher of English and creative writing. She is the first New Jersey resident to win the Prize.
The annual Dogfish Head Poetry Prize consists of publication of the manuscript by the
Broadkill River Press, 10 copies of the published book, $500 in prize money, two cases of Dogfish Head Craft Brewed Ale, and two nights' stay at the Dogfish Inn.
Birds of New Jersey is a field guide of sorts, though not of avian fauna so much as of the poet's life and natural surroundings: her family, friends, neighborhood. Not one to shy away from or blink at life's exigencies, and standing in judgment of the behavior of her subjects — she turns an unflinching eye on herself — the book is a sometimes shocking, often bemused, and always insightful collection of such observations as a naturalist might make of any species being studied.
Edgar Kunz, author of Tap Out, and final judge of this year's competition, notes that, "In the cadences of everyday speech, the poems of Birds of New Jersey struggle and yearn and transform the ordinary – a tense exchange over dinner, a pre-dawn drive into the city, an abundance of oranges in the fridge – into lyrics of remarkable complexity. This is a voice that doesn't shy from difficulty, doesn't flinch, a voice that is at once subtle and confident, ruthless and warm. Rothbard is a magician and Birds of New Jersey is a deeply satisfying book."
Of Birds of New Jersey, Renée Ashley, author of Minglements: Prose on Poetry and Life, writes, "Rothbard, feet firmly anchored to terra firma, takes us to headier lands, liminal and philosophical regions, without ever leaving the earthy sources of her subjects, raising them to the airier cusps, to those thresholds of uncertainty that we all have experienced but rarely articulate. Her ability to sharpen the reader's senses, in both those worlds at once, is astonishing. These lapidary, lyric poems say what I need to tell you, but far more concisely, far more precisely, and more artfully than any paraphrase, any summing up, any lit crit or craft critique I might muster. Her work is full of edgy percepts, some funny, some so sharp you'll flinch. Read Birds of New Jersey: you'll be more than charmed and convinced by both her voice and her skill, and, as a perk, she'll make clearer for you what we've all suspected all along: '[N]othing's as real as we want it to be.' And she'll do it beautifully. "
Jeanne Marie Beaumont, author of Letters from Limbo, says of Birds of New Jersey, "'This is the view from the kitchen sink,' the poet writes, yet how expansive that view turns out to be—both complicating and elevating what it means to be at home, to make a home. Rothbard is a savvy poem-maker, whose abundant wit and technical polish never deflect from her honest accounting of the ways we navigate intimate relations, as well as those farther afield. Birds of New Jersey makes the best sort of company in this mortal world we share and try to care responsibly for."
This is the 18th annual presentation of the Dogfish Head Poetry Prize which was created by Sam Calagione (a literature major in college), CEO of Dogfish Head Craft Brewed Ales, of Milton, Delaware and Rehoboth Beach, Delaware. The Prize is open to residents of North Carolina, Virginia, West Virginia, Maryland, Delaware, New Jersey, Pennsylvania, New York, and the District of Columbia. Publication of the winning manuscript is supported in part by The Cape Gazette.
"Purple, Purple" and other poems
Ian Walton
Ian Walton's poems come from the greatest of our literary traditions. He honors our ancestors, "preserving the beloved," memorializing his cultural heroes, bringing their souls back from the ruins. With equal strength Walton honors the living, with truthfulness, sometimes autobiographical, letting language tell his stories of experience and perception. This is a book where history, artistry and vulnerability intersect, creating poems that are inimitable.
— Grace Cavalieri
"The Poet and the Poem from
the Library of Congress."
There is a wild and powerful profusion of images in Ian Walton's Purple, Purple. Whether
describing shocking events, recounting personal history, addressing the ghosts of moral figures, or relating fragmentary thoughts, his poems are stunning in both senses of that word. These poems are a pleasure to read and re-read many times.
– Howard Gofreed
Ian Walton's Purple, Purple and Other Poems captures that elusive sensual moment where our consciousness connects with another, and for a brief moment is transformed by the coupling. Walton's a poet of sex, romance, aging, and desire. His style captures the tension between desire and love, the formal and the informal. His language is sticky with sensation, and throttling with energy. Walton's poems itch and gyrate; never satisfied. Purple, Purple and Other Poems writhes, seethes, and lusts. You can practically feel their pulse beneath the pages.
— Scott Whitaker
"Purple, Purple," the title poem in this collection, is subtitled, "to a successful suicide on
Washington, D.C.'s Metrorail," and it is these system code words brought to us by an insider on the Metrorail system which are the most indicative of the eye-witness point of view of the poetic narrative voice. These are poems of power, whether the power of insight, politics, or the gender clash, and they are brutally, yet beautifully, honest.
— Jamie Brown
Normal They Napalm the Cottonfields
D. L. Pearlman
Winner of the 2019 Dogfish Head Poetry Prize
(December 14, 2019— Lewes, Delaware) D. L. Pearlman, native son of Norfolk and Adjunct Professor of English at Tidewater Community College, has been selected as the winner of the 2019 Dogfish Head Poetry Prize for his manuscript, "Normal They Napalm the Cottonfields." The Prize was presented on December 14th at the Dogfish Inn, in Lewes, DE, by a company official. The annual Prize
consists of publication of the manuscript by the Broadkill River Press, 10 copies of the published book, $500 in prize money, two cases of Dogfish Head Craft Brewed Ale, and two nights' stay at the Dogfish Inn.
Normal They Napalm the Cottonfields is a tour de force examination of many of the events which have shaped both the author and the world in which he grew up, and in which he continues to make his way, sometimes in spite of the obstacles which he perceives with a clarity of vision unmatched by myriad lesser talents. The poems in this collection serve much like the napalm used to burn off the leaves of the cotton plants and open the bolls by presenting the reader with what would, in a more mundane poets' hands, merely be hinted at or concealed.
Of Normal They Napalm the Cottonfields, Joseph Millar, author of Kingdom, who was judge of this year's competition, says of Pearlman's work that "the poems in D. L. Pearlman's collection are filled with the experience of this world. I admire the variety of their subject matter, the reminiscences of a traveling photographer, and especially their gritty images of working life in a countryside worn down by time and weather, its crops and dirt roads, its shoreline and bays and woods." Grace Cavalieri, radio host of "The Poet and the Poem," and current Maryland Poet Laureate, writes of his work that Pearlman "sees every detail of grandeur in our failing earth, and makes the reader feel the rubble under his feet, . . A world ripe with . . . Richness and wreckage." Pearlman's work is, she continues, "large with social conscience and awareness. . .This is real writing. This is real poetry."
Stephen Scott Whitaker, a poet, author and editor, and member of the National Book Critics Circle,says that Pearlman "transforms America's broken and littered landscapes into a song of woe and loss. . . (He) pulls no punches," and that the author "offers glimpses of hope in a world where life and struggle are synonymous, a country littered with garbage, both real and metaphorical…"
This is the 17th presentation of the annual Dogfish Head Poetry Prize and was created by Sam Calagione (a literature major in college), CEO of Dogfish Head Craft Brewed Ales, which is open to residents of North Carolina, Virginia, West Virginia, Maryland, Delaware, New Jersey, Pennsylvania, New York, and the District of Columbia. Publication of the winning manuscript is supported in part by The Cape Gazette. Printed on recycled paper and priced at $15.00, readers who wish to acquire a copy of Normal They Napalm the Cottonfields can purchase the book on-line at www.broadkillriverpress.com
The Delaware Bay: Poems
"There is a haunting lyricism in Jamie Brown's The Delaware Bay Poems, a series of trope-rich meditations on timeless natural forces that subtly evoke the human struggle in its many manifestations." — Merrill Leffler, author of Mark the Music. publisher of Dryad Press
The Delaware Bay Poems, are the beautiful culmination of a career-long habit of quiet observation of the day and night time worlds. A real pleasure to my waking eyes, .. they remind me, in places, of the fine, close observations of the New Yorker's John McFee. — H. A. Maxson, Author of Lemon Light and On the Sonnets of Robert Frost
Becky Could Gibson
Becky Gould Gibson, of Winston-Salem, North Carolina, has been selected as the winner of the 2018 Dogfish Head Poetry
Prize for her manuscript, "Indelible." The Prize was presented on December 8 at the Dogfish Inn, in Lewes, DE, by Andrew Greeley, innkeeper. The annual Prize consists of publication of her manuscript by the Broadkill River Press, 10 copies of the published book, $500 in prize money, two cases of Dogfish Head beer, and two nights' stay at the Dogfish Inn.
Indelible is a testament in verse that concerns 'Lydia' of Philippi, the dealer in purple cloth mentioned in the Book of Acts, said to be the first convert to Christianity in Europe. Gibson brings to life 'Lydia's' charged relationship with the Apostle Paul and her struggle to sustain religious faith over two millennia. No stranger to the Pauline texts (and later works) which inform the poems, Gibson brings her scholarly eye to bear on the humanity of Lydia and those other early converts, situating them firmly in their historical time and place.
Becky Gould Gibson, Ph.D. (UNC-Chapel Hill, 1977), taught English and Women's Studies at Guilford College until her retirement in 2008. Her poems have appeared in journals and anthologies, to include Kalliope, Feminist Studies, The Comstock Review, The Chattahoochee Review, Tampa Review, Poetry South, and The Southern Poetry Anthology: Volume VII (Texas Review Press, 2014). Gibson has published seven poetry collections, notably, Aphrodite's Daughter (2006 X. J. Kennedy Prize, Texas Review Press, 2007); Need-Fire (2005 Poetry Book Contest, Bright Hill Press, 2007); and The Xanthippe Fragments (St.Andrews University Press, 2016). The last two books give voice to women whose words are missing from the historical record: Hild, Abbess of Whitby (615-680), and Socrates' wife Xanthippe. Indelible is a third poetic sequence in that vein. Becky lives with her husband and their canary in Winston-Salem, NC.
The Dogfish Head Poetry Prize is in its 16th year and was created by CEO of Dogfish Head Sam Calagione (a literature major in college), and is open to residents of North Carolina, Virginia, West Virginia, Maryland, Delaware, New Jersey, Pennsylvania, New York, and District of Columbia. Publication of the winning manuscript is supported in part by The Cape Gazette. Readers who wish to acquire a copy of Indelible can purchase the book online at www.broadkillriverpress.com
Necessary Myths
Grant Clauser
Clauser's work is firmly anchored in his home state, with many of the poems set in ( or on) the far s, fields, woods, state parks, and rivers of the region. A self-described "frustrated gardener and hack fly-fisherman," he is a working parent who also leads workshops in writing poetry at conferences and at Philadelphia's Musehouse. Necessary Myths is his second published book; his first, The Trouble with Rivers (FootHills Publishing, 2012), was praised by Robert Bly as being "able to carry some tragedy with it (while) At the same time there is some sort of triumph ."
His poetry has appeared in The Literary Review, Painted Bride Quarterly, Cortland Review, Sow's Ear Poetry Review and others. In 2010 he was Montgomery County Poet Laureate. His interviews with other poets have appeared in the Schuylkill Valley Journal and The American Poetry Review. He also finds time to run the blog www.unIambic.com.
Director of the Dogfish Head Poetry Prize competition Linda Blaskey says of Clauser's work, "His work is rich and evocative. Full of imagery. I think the judges got it right."
Beth Copeland
"The Blue Honey that flows through Copeland's collection by that name, through her parents' flurry of furious wings–that flows through Japan, her siblings, an Alaskan airport, and The South, where a childhood was held by the ankles upside down and slapped–that flows through a marriage, torn and mended, flows through it all with a fearless and loving spirit, with personality, humor, anger, and craft. Reader, I dare you to walk away from this elegy unmoved."
Roger Weingarten, author of Ethan Benjamin Boldt (Knopf), Ghost-wrestling (Godine), and The Four Gentlemen and Their Footmen (Longleaf, 2015).
"Beth Copeland's Blue Honey is a lyrical case study of loss and the ways in which it reverberates through a family's center. . . Copeland is a master storyteller; she weaves each of these narratives seamlessly through the text, and her ear for language—not to mention her eye for the most delicate of details—is a veritable honey trap for the reader."
Destiny O. Birdsong, MFA, PhD, recipient, Academy of American Poets Prize
"The structure of Blue Honey . . . reenacts the circular journey that so many of us must make, from being cared for by our parents to ushering them through the mysterious borderland known as old age. Beth Copeland (writes) with breathtaking honesty . . . metaphorically fresh and formally inventive . . . Bravo to Copeland for not shying away from poetry's most arduous and important task, which is to write about life in a way that makes us feel less alone."
Sue Ellen Thompson, editor The Autumn House Anthology of Contemporary American Poetry, and recipient of the 2010 Maryland Author Award
About Beth Copeland
The child of missionaries, Beth Copeland was born in Japan, where she spent her early childhood, as well as in India and the United States. Her first full-length poetry book Traveling through Glass received the 1999 Bright Hill Press Poetry Book Award. Her second book Transcendental Telemarketer was published by BlazeVOX in 2012. Her poems have appeared in literary journals and anthologies, including Aeolian Harp, Atlanta Review, New Millennium Writings, The North American Review, Pedestal Magazine, Pirene's Fountain, Poet's Market, Rattle, The Southern Poetry Anthology, and Tar River Poetry and have been featured on the CBS NewsHour website. Beth received her MFA degree from Bowling Green State University in Ohio and teaches creative writing at her undergraduate alma mater, St. Andrews University. She lives with her husband Phil Rech and hound dog Kasey in a log cabin in North Carolina.
FLUX Quanta
James Michael Robbins
James Michael Robbins, noted Austin poet and former Publisher of The Sulphur River Literary Review, has authored a new collection of work, FLUX Quanta (Broadkill Press, $10.95).
Richard Peabody, Publisher of Gargoyle Magazine, says "Robbins is a poet at play in the fields of economics and science," and that these poems are "shot through the Large Hadron Collider into Bartleby's wall…(Robbins) is not the first to intertwine language and science via exploratory poems, but he sure has a good time."
Peabody's assessment will not surprise anyone familiar with Robbins' prior work, which melded his academic interest in Physics (BS in Physics, East Texas State) with his poetry. His previous chapbook of poems, Graviture, was published by Rancho Loco Press in 2001.
Lyn Lifshin notes that "Lostness and the unreal collide with creativity in a world where things keep disappearing. The poems move between mystery and enigma. Opposites flourish, action and inaction."
Poet a. mclean appreciates how Robbins' poems seem coaxed from "the intersection of the frontiers of physics and poetry," suggesting that they reflect "what…NASA, the wild west, and Stephen Hawking have in common."
Mary B.Moore
WINNER- 2016 DOGFISH HEAD POETRY PRIZE
"Flicker is the work of a poet's poet, someone who captures the lyric moment with precision and careful prosody, and who loves language. as much for its malleability as for its sensuality. These are poems that celebrate the sound of every word and the feel in the mouth when we say them. In these poems, M. B. Moore remakes the natural world in 'orderly/coats of gloss and reverie,' reminding us that our most ardent prayer is founded in paying attention."
Gerry LaFemina, author of Vanishing Horizon and Little Heretic
"The poetry of Mary Moore, with its lush vocabulary and soaring music, its historical intelligence and emotional risk, repeatedly — relentlessly, in fact — wakens readers to the power of verse to vivify the commonplace, quash the pompous, and locate the 'liquored vagaries' as well as the 'rifts brief cleavings and aversions' of our world. Flicker is a book that shimmers with invention, insight, and the 'jumpy translucence of flame.'"
Gregory Fraser, author of Designed for Flight and Answering the Ruins
"The poet's imagination does not tamper with the Indigo bunting, 'the sun's/mutable spokes,' the 'premise' of rock near Alpine Lake, zinnia, larkspur, cloudscape, a hawk riding updrafts in Flicker. Instead with fresh, nuanced language — words and the sounds of word — the poet affirms reality and creates something else, something familiar and entirely new."
Carol Frost, author of Entwined: Three Lyric Sequences
"In Flicker, M. B. Moore considers 'what holds us together.' In doing so, she looks closely and unflinchingly at this world, its buzzing and its beauty. These are poems full of color and light, startling imagery, and keen observation. Flicker is a finely wrought book from a poet who deserves attention."
Joseph Mills, author of Exit, Pursued by a Bear and The Miraculous Turning
ROCK TAUGHT
David McAleavey
OUR NOMINEE FOR THE 2016 NATIONAL BOOK AWARD!
It's hard to describe the pleasure that comes from reading David McAleavey's poetry, that wonderful, unstable union of the cerebral with the corporeal, the frisson present in every line. He says, "Yogis call it 'Breath of Fire': the spinal,/painful thrill bashing into brain/from tailbone, winging back down/and up again." The poems follow the breath of fire that is consciousness itself. In Rock Taught, we wander through the poet's life, follow him on his "daily route" to work, or into an abandoned house, or on his visits to a museum in Germany or a strip club in Harlem.
Always restless, he discovers in his poems a place within himself, where, as he says, "something shifts and shunts me / into the predicament of not knowing / how to praise, how to exclaim, / and a way appears." His way is to confront the ordinary and let it prompt in him the unexpected exclamations that are these poems with their gift for feeling fully the inexplicable world around him. They breathe dark fire.
Dana Roeser
MATCHSTICK & BRAMBLE
Lucy Simpson
It is a rare occurrence to find a poet of a high professional standard on an internet poetry forum; rarer still to share a literary journey with one such for over a decade. Lucy has a skillful command of her inner world and often employs classical mythological archetypes to paint that world in new and personal hues. Her insights and lyricism attract the reader on every level. She is quite simply, a major, and magical poet.
Eric Ashford-Poet
Lucy Simpson has written a spellbinding collection of poetry, reminiscent of Anne Sexton's Transformations; language brutal and poignant, reframing myths, legends and fairy tales with fearsome attention to detail. Many of the poems read like incantations, a reversal of curses, chock full of blood and gore and prescient beasts. Magic steps out from the crannies in the guise of angels, orphans and donkey daughters in this collection of poetry. I was totally bewitched.
Tori Grant Welhouse, Poet
Lucy Simpson's poems are full of windows, and she takes her readers through these windows into worlds where a woodworker's daughter plays a fiddle made from a branch of Eve's tree and witches drink pennyroyal for whisky. Simpson's poems retell and reinvent the tales we remember or half-remember, blending mythology, biblical heroes and demons, the Brothers Grimm and girls falling like brides in the Triangle Factory fire. Her poems transport us and guide us–both a heady bottle of "Drink me" and a map in a bottle. She leads us into and out of the dark woods, and to follow her Riding Hood still bloody in exodus from the wolf's belly is to know the word wonderful. Kelly Riggle Hower – Seattle Public Schools Teacher – Poet – Winner of the Richard Hugo House Poetry of Place
CONTENTS UNDER PRESSURE
A COLLECTION OF SHORT FICTION
Ellen Prentiss Campbell
THE BROADKILL RIVER PRESS NOMINEE FOR THE 2015 NATIONAL BOOK AWARD IN FICTION!
Contents Under Pressure is a beautiful story collection by a writer whose wisdom and compassion illuminate every page. Ellen Prentiss Campbell understands how her vividly drawn characters can love and hurt each other simultaneously, and she probes into the recesses of their hearts. Altogether a pleasure to read.
Lynne Sharon Schwartz
Ellen Prentiss Campbell's Contents Under Pressure is an aptly named book, indeed. These stories crackle with tension, delivered in language with the concision and precision of poetry. Never predictable, always insightful, and often breathtakingly acute, Campbell is a writer to watch.
Rose Solari, author of The Last Girl and A Secret Woman
The strange and the unexpected play powerful roles in Ellen Prentiss Campbell's haunting stories of transformation. The characters' dilemmas—a foundering marriage, a child's death, a father's madness—are not so much resolved at the story's end as they are given surprising new forms. In one, an amazing tour de force, a young woman drawn to the underwater world is transformed into a mermaid. Campbell's precise, elegant prose renders her gift for the uncanny both believable and a wonderful read.
Kate Blackwell, author of You Won't Remember This: Stories
ORPHEUS, TURNING
Faith Shearin
2015 Dogfish Head Poetry Prize Winner!
Faith Shearin's elegant skitterings manage to be at the same time well-crafted and spontaneous, unself-conscious and acute, so that the reader is drawn to her lively spirit. I can't think of anyone else who would write "The past demands /that you wear a hat, that you
/eat your dead aunt's casserole" and achieve our delight in her surprising truth.
David R. Slavitt
If Orpheus, Turning doesn't make you ache with the love of poetry, please have your vital signs checked as soon as possible. Faith Shearin creates a reality of light and shadow, sweet textures of a sentient past, with respect for its impermanence and a vow to make it last. 'Just beyond the ghost of the dog of childhood' she writes. We believe in the passage of her time, and beneath its skin are set pieces of effortless beauty. She says, 'The past wants you back,' and I say, yes, we want to go there.
Grace Cavalieri
In Faith Shearin's fifth collection, Orpheus,Turning, the sixty-one free-verse lyrics are often drawn from the dynamics of an American family. They convey both hope and sorrow in moving ways, and in language that delights when it offers jolts like this possum, "his face a triangle/ of albino dislike." The power of memory sometimes over-rules the ravages of time, too, when remembered details flesh out events. Ms. Shearin can also stand reality on its head, as when some passengers on the Titanic, still down there in the ship's hull, carry on as though no disaster occurred, or when the family dog educates itself by watching TV. Add to this some historical characters like Marie Curie and Amelia Earhart, some figures like Orpheus and Eurydice and the Pied Piper of Hamelin, and Orpheus, Turning is a heart-made view of how we live.
Brendan Galvin
Faith Shearin gives us a study of turning points, instants where the world of the interior begins to swing back on a hinge of understanding or wonder. As we enter in that stillness, "listening to our low horn ask its one question," we share in Orpheus's eagerness and his rue. A stirring and scissors-sharp collection.
Jeremy Penna
W.M. Rivera
William Rivera is a master poet. He speaks of "imagination made flesh" in his stunning new book. Imagination also makes thought forms beautifully shaped and crafted with surprises coming in the side doors. Rivera writes of poetry, science, history, nature, art, travel, mythology, with knowledge and achievement; but being learned is not what wins the day in any poem — it is Rivera's freedom of heart and generosity of feeling that expand the context. Of all the books you'll leaf through, sitting on your desk waiting, this is the one you'll rather read. I promise.
Grace Cavalieri "The Poet and the Poem from The Library of Congress"
With a romantic's ear for lyricism, Rivera's poems explore our highs and lows, our lust for beauty and the folly of love. Driving to work, or checking out at the supermarket, lines in Noise keep coming back to you.
Scott Whitaker, Author, Book Review Editor for The Broadkill Review, and Member, NBCC
SILENCE, INTERRUPTED
Jim Bourey
Named Best Book of Verse 2015 Delaware Press Association
Silence often marks the absence of life, or it's pause, but in Bourey's poems of family, rural life, and work the world, is anything but silent, or paused. Bourey searches the darkness lurking at the edge of small towns, and searches the natural world around him to discover wise teachers in the birds, a fishing trip, and the veterans drinking at the bar. Bourey is after the truth, which is never silent.
Scott Whitaker, author of The Black Narrows
Jim Bourey's Silence, Interrupted is a superb collection of poems that raise a cry/bringing others in/ to savor the wintry meal. His poems resound with passion, compassion, inventiveness, and intelligence. Jim reminds the reader, when spring's melting/arrived there was less silence. / Noise was welcomed. These poems deliver noise. Jim teases the reader, wants to hear/your poet's voice as if we're in/ the same room, drinking together with urgency. These poems do not reminisce or drift in sentimental tides. These poems listen to neighbors talking loudly at two-thirty in the morning. But do not be misled, these poems are not white noise – these poems break silence.
Michael Blaine, author of Brackish Water
"Silence, Interrupted embraces the beauty and necessity of noise in our lives. In poems that take us from Vietnam to abandoned coal mines and the ocean boardwalk, Jim Bourey's meditative and often ironic eye never flinches from the poet's task of questioning and telling the truth, "no matter how it all plays out." Fiercely attentive to the poetic line, he allows us to linger in the music of each moment as he explores themes of loss, guilt, and family legacy. Bourey's words are like "sparks generating fire"; his poems remind us to pay attention to our internal and external worlds, those noises both "silent and alive."
Amanda Newell, author of Fractured Light
THE TABLE OF THE ELEMENTS
J. T. Whitehead
BROADKILL RIVER PRESS NOMINEE FOR THE 2015 NATIONAL BOOK AWARD IN POETRY!
NAMED WINNER OF THE 2015 Margaret Randall Poetry Prize, sponsored by The Mas Tequila Review
"Whether being lighthearted as a helium balloon or serious as a hydrogen bomb, J. T. Whitehead seeks what is true and elemental about our lives. The spirit of Kurt Vonnegut lives on in this poetic romp through the periodic table by the editor of So It Goes: The Literary Journal of the Kurt Vonnegut Memorial Library."
Julie Kane
"Thank you so much for The Table of the Elements, which I'm enjoying more than any poetry I've seen in a long time. (I'm on my second reading now.) It's original, unselfconscious, deep, often very witty. It's also sensuous and erudite. If it isn't nice, I don't know what is. . . .There are poems in here that touch on things that have always been important to me, and some that jog my long, old memory in some ways I can't pin down yet. . . . I'm impressed and entertained."
James Alexander Thom
"J.T. Whitehead's Table of the Elements is alchemy, boldly discovering and rediscovering the natural world. These poems recast the periodic table of elements, and raw natural resources such as salt and oil through the poetic eye. Whitehead reminds us that nothing is ever as it appears, that mankind may be gifted at naming elements, and wielding natural resources, but their stories, their histories, and their mythologies, personal and universal, transmute us all."
Scott Whitaker Book Review Editor, The Broadkill Review, and Member, National Book Critics Circle
"J. T. Whitehead brings to this monumental collection all the gifts we would expect of any poet worth his sodium: Music, Imagery, Form (traditional and free), Sensitivity, Passion, Humanity, The World, The Self. What he adds to those . . . what is lacking in so much of the mediocre volumes heaped upon us today . . . is INTELLIGENCE! A World Class Intelligence. That which envelops experience, orders and reorders it, penetrates and invades it, not eschewing syllogistic reasoning or immersion in the knowledge and wisdom of the great geniuses of the past, and the application of this great inquiry to the particularities of his life and ours. What poets of permanent interest have possessed intelligence of such dimensions? Eliot springs to mind. John Donne. Yeats. Blake. Dante. Joyce (in his great poem, Finnegans Wake). Shakespeare. Rilke. Whitman. Horace. Pope. Homer. There are others, but you get the idea. We are talking about Poets of DIMENSION.
"Do not be scared off by this. All those I have mentioned have ultimately demonstrated the greatest clarity of vision and expression. J.T. brings to language the quintessential precision and clarity of the Legal Mind, enriched by the Poetic Imagination: a Bicameral Creativity. Accept the challenge. Prove yourself the equal of it. "Buy the Fucking Book!"
Gerald Locklin
"J.T. Whitehead's The Table of the Elements gives us proof that poetry is found in all things, and we are engulfed in it. His poetic vision takes our arrogant assumption of the inanimate world, and turns it on its head. This collection of poems declares to the reader: you and I do not master the elements, the elements master us. In a time when it becomes clear that mankind has done nothing to deserve a planet so full of wonder and grace, these poems remind us that we are nothing but the stuff we, ourselves, take for granted and waste. Here, poetry documents the folly and mayhem of our physical journey. While we squander our lives, Whitehead reminds us that the solids, gases, molecules and atoms of the universe patiently await our unavoidable return."
Richard Vargas, author of Guernica, revisited, publisher/editor of The Más Tequila Review
GOOD WITH ORANGES
Sid Gold
Sid Gold is a quintessential American poet. Unlike many of his contemporaries he is a pioneer, a conqueror, who keeps expanding his artistic universe. Read this book, read again his previous poetry collections and you will agree: Sid Gold is a master!
Lyubomir Nikolov, Author of Unreal Estate
Sid Gold's poems are both streetwise and deeply compassionate. Going against the grain of our wish-fulfillment culture, they look to the unlovely and dilapidate; many of the characters we meet in them have survived setbacks, while some are on a collision course with reality. These are poems about coming to terms, and about finding—as we cast off ego and delusion—what will suffice: "the crisp leaves/of November stirring in the wind/the knife blade slicing through the day-old loaf." Gold's generosity of spirit recalls Whitman, William Carlos Williams and Gerald Stern; at the same time, the artistry and seductive elegance of his poems distinguishes him from most chroniclers of contemporary urban life. He is, as the book's title suggests, "good with oranges."
Robert Herschbach, Author of Loose Weather
Sid Gold's Good with Oranges offers us an unflinching view of the world. The voice in these poems is as clear and direct as the truths they lay bare—truths spanning from our deepest individual desires to the public narrative of our shared human history. Often the two are present in a single moment, juxtaposed in such surprising ways that we are forced to reexamine what we thought we knew…and find ourselves changed in the process.
Holly Karapetkova, Author of Words We Might One Day Say
THE STORIES WE TELL
Irene Fick
Best Book of Poetry 2014! National Federation of Press Women
Best Book of Verse 2014! Delaware Press Association
Irene Fick's first book has stolen my heart with its clear sweet lines, and lack of artifice. Here's poetry that doesn't need to persuade, for its presence in the world emerges from a genuine source with immediate connectivity. The title of the book is straightforward, yet it's rare to create the right story in the right form with themes laid out in a unified vision. Fick is a writer of observation, but more, of felt life. Once you enter her currents of thought, there's no going back or stopping. To be able to show hard glimpses of reality with beauty and truth is a gift many poets have not achieved. As for fear, age, dementia, illness and death, Fick turns them over to the angels of language where they belong—and they could not do better. I am permanently touched by this book.
Grace Cavalieri, Producer/Host, "The Poet and the Poem from the Library of Congress"
Fick focuses her journalist's eyes on her childhood (in an imperfect Italian family in Brooklyn) and her adulthood as though she wanted to be sentimental, but instead nails down her observations with sharply delineated details. Entering the domain of poetry, she combines words in novel combinations, often juxtaposing one truth against another with fresh vision, originality, and regard for the innate music of good free verse. One sees ever the sense of discovery, uncovering truths without need for fancy phrases, pretty devices or four-letter words, because, poem after poem, the perceptions and combinations are right on target.
Elisavietta Ritchie, Author of Tiger Upstairs on Connecticut Avenue
PEREGRINE NATION
Lucian Mattison
Lucian Mattison writes poems that travel across continents and griefs, bi-cultural, speaking between languages, his is a broad geography from pool halls to the dim lights of Argentina, he brings us through the alleyways of lost loves and the bar tables where we count our losses, but always with some sense of hope, some far away music calling us as when he urges "hear my voice inhabit/a familiar melody, as if/ I've lived my entire life somewhere else/ in a second tongue."
Sean Thomas Dougherty
In semi-documentary dramatic scenes, Lucian Mattison tells stories about a specific locale, a Peregrine Nation that I can think my way into, or sink into–an outlier's view of Argentina. His scenes remain in the mind because each line of poetry, as Ezra Pound recommended, is written "at least as well as prose." Mattison's poetry masquerading as prose is generally straightforward but delivers sudden fillips that transpose the reader to another level. He is a scrupulous poet who will engage readers with his bright, spontaneous, clear, never-strained, uncluttered , new voice.
Larry Woiwode
Lucian Mattison stamps our passports and welcomes us to the Peregrine Nation, a region in history both personal and shared. Although the poems take us all over Chile and Argentina, we never feel welcome in either. Rather the Peregrine Nation seems to be a kind of Nowhere Land for those "not completely gringo or Argentinian." By oscillating between poetic strategies, between shorter lyrics and more narrative poem, Mattison formally enacts this juxtaposition, creating a poetry that all outsiders will find welcoming.
Gerry LaFemina
ON GANNON STREET
Mary Ann Larkin
Exquisitely made, lyrical, yet unpretentious, Mary Ann Larkin's On Gannon Street evokes the complexities of a black neighborhood and its relationship with a sole white resident, with all the poignance of a novel, but with a gifted poet's miraculous economy. We know these characters, their dreams, frustrations, acts of ordinary kindness, in all four dimensions, but above it all there's a visionary fifth dimension hovering, showing a wisdom and imagination of the highest order, making Gannon Street a place not to be missed in anyone's tour of America.
Alan Feldman, Author of Immortality
POSTCARD FROM BOLOGNA
Howard Gofreed
Nominated for the 2014 National Book Critics Circle Award!
Howard Gofreed's Postcard from Bologna contains personal poems with both violence and ache at their center. Gofreed looks war, loneliness, and age in the face and dares to keep on going. There's courage in these poems, and humor too, and Gofreed doesn't back down from a fight. "There will always be hostages," he writes about Iran and his own health, and he's right; sometimes the hostages of our horrible acts are our loved ones, and our own damaged hearts.
Howard Gofreed's voice is egalitarian and inviting, each poem an invitation to overhear a man reflect on his experiences – war, children divorce, lustings, the past, the everyday comings and goings – in a tone that is often wryly comic and sceptical but always empathic.
Merrill Leffler, Author of Mark the Music
LEMON LIGHT
H.A. Maxson
H.A. Maxson's Lemon Light is a resounding addition to an already fine body of work. There is many-angled and moving clarity here, a plain-spokenness shot through with illuminating nuance. Any one of these poems can have the reader saying, "Yes, this is it exactly."
Thomas Reiter Author of Catchment: Poems
Clear, lively, and often stunning in their language, the poems in H.A. Maxson's LEMON LIGHT surprise us with images like this: "I have held the ankles of the voracious upside-down man as he chewed through rock and root for the last time." That's a brand new look at a post-hole digger, and whether the subject is muskrats, King Croesus, or Assateague ponies, Maxson's particulars are exact and gratifying. He is that rare poet who lifts the world out of the commonplace for the reader's astonishment.
Brendan Galvin Author of Ocean Effects: Poems
CHARMED LIFE
Buck Downs
I don't know if Buck Downs leads a charmed life—literally—but there's something exceedingly lucky—felicitous—happy—about the way he lays down these poetic telegrams of twenty-first-century experience in Charmed Life. The reader swoops along on Downs's burst of coy and cunning language, "drifting like old- / fashioned / radio signals" through the perennial—but here freshly revivified—territories of love, sex, music, everyday living. These poems will charm your socks—hell, maybe even your pants—off: "don't change / your mind / for me, // not if / you grind / for me."
Mark Scroggins. Author of Red Arcadia
BRACKISH WATER
Michael Blaine
In "Brackish Water" Michael Blaine's haiku often startle with a surprising jolt in line three. His ekphrastic poems peer beneath the paint deep into the underlying metaphor. Whether he is celebrating being a father, a husband or a teacher, his images are hard and clear and they make his old, old subjects sparkle in new light.
I like the voice of the teacher evident in this collection, a teacher aware he is walking with his children (and his readers) to points of growth which are also points of no return, moments when familiar realities feel fundamental and life-sustaining, though they also seem to usher each of us off into our own privacies. Often it's the haiku in this collection that present these moments most magically; for instance, "Cicada shell/I find her college photos/in the trash can." Or, "just noticing/the countless scratches –/wedding band." Or, "only brown moths/around the last zinnia blooms/our breath visible."
David McAleavey, Author of Holding Obsidian
In Brackish Water, Michael Blaine navigates the complicated habitats of desire, marriage, fatherhood, and loss. He reminds us that "[r]eal isn't enough"—that something more must be "added to make/the eye believe." Blaine's poems, in effect, become a kind of tide themselves, carrying the reader from Rehoboth Bay to as far away as the Gulf of Mexico and Haiti. And yet, the spare imagery of these finely crafted poems—the silky muck, the tractor discs, the rock and shale—keeps us firmly rooted in the earth. Blaine's remarkable collection affirms our shared consciousness, and in the end, he shows us it is possible to sift among the wreckage, "to pick up and rebuild/what [is] salvageable."
LOVE, WAR, & MUSIC
Franetta McMillian
Franetta McMillian's poems are deliciously awash in the (often overlooked) inherent musicality found in the word, and in an infectious, riveting, and unabashedly singular vision. You cannot help but follow these rhythmic narrative journeys. You want to know where the poems are going — what you will see, hear, and feel on the way. You'll also want to revisit each poem's questions and/or implications. I often found myself thinking of a line from another poet—Rainer Maria Rilke— "Love the questions like locked doors."Ms. Mc Millan's work is a reminder that there are still infinite linguistic songs to be sung—what Patti Smith dubbed "a sea of possibilities." Let this fine volume into your heart.
Reuben Jackson, Author, fingering the keys and Host of "Friday Night Jazz" Vermont Public Radio
Franetta McMillian writes in a language both clear and meditative, tackling subject matter as wide ranging as the title of her work suggests. She evokes the imagery of everything from popular television shows to vehement bigotry, and each time provokes the readers to challenge their perceptions on the matter. This poetry is not preaching, nor is it pushing boundaries for the sake of it—McMillian engages in a deep exploration of her various subjects with each line, and that sort of depth can't do anything but force the audience to think in a new way.
Joshua D. Isard, Director MFA Program in Creative Writing, Arcadia University
Susanne Bostick
Long-time government writer Susanne Bostick Allen advises that "[r]ed is vital to our mission" and "[b]eige has practical applications", but "the sentences are up to no good". She chastens bureaucracy with understated humor, then escapes to clear-eyed remembrance of childhood visits to relatives in rural Alabama.Highway 78 cogently contrasts both ways of life to reveal a life well examined and honestly reported.
Howard Gofreed, author of Postcard from Bologna
From the rich bottom land of Alabama to the slick highways circumventing Washington D.C. , Susanne Bostick Allen takes us on a sojourn of unsentimental power with her skillfully balanced poetry. The subtext is a woman's identity, probing into corners with intelligent humor. Allen's calm observations become poetry as the rhythm of language governs narrative, and we then enter an extended map of a poet's fine senses.
Grace Cavalieri, Producer/Host "The Poet and the Poem from the Library of Congress."
DUTIFUL HEART
Joy Gaines-Friedler
A beautiful collection of clear, grounded, surprising and moving poems about creating friendships and letting go loved ones, taking in whatever good there is to be had, and cutting out the damaged parts, and letting them go. Never over-poetic, simply graceful, smart, and necessary.
Heather Sellers, Author of Georgia Under Water
So fine to have Ms. Gaines-Friedler's poems in the world — recording as they do with grace and proper gravitas the shift between generations, seasons, those watershed moments that move one day irretrievably into another.
Thomas Lynch, Author of Walking Papers
Like the bird that 'curves its tiny bones around the twigs of wobbly branches,' these poems adapt to and ride the most fierce and fragile of circumstances. Whether from the nursing home or the broken relationship — and with humor and forgiveness — the poems in Dutiful Heart bloom where they are planted. Joy Gaines-Friedler's tender work reminds us to stay tethered, to keep refilling the feeder and always bring 'something sweet for the table.'
Terry Blackhawk, Author of The Dropped Hand
SPEED ENFORCED BY AIRCRAFT
Richard Peabody
Pulitzer Prize Nominee
Peabody's latest collection of poetry is a testament to the many facets of his career. Though Peabody is a writer, poet, publisher, editor and long-time literary maven who has dedicated a large part of his own life to promoting other writers, especially young and/or emerging writers, this one-time wunderkind of American letters' own style has matured and his work has taken on a depth and complexity, and the richness of a fine vintage.
The Publishers
CONSTRUCTING FICTION
James C.L. Brown
Constructing Fiction is a gift to the young or would-be writers of short stories and novels. In plain, no-nonsense prose, Jamie Brown takes the reader for a walk through the world of fiction writing—avoiding the alleys and dead-end streets that so often lure new writers with promises of shortcuts. Here is advice that all writers—those young in the work, and old hands—can actually use.
H. A. Maxson
Constructing Fiction is a must for green writers looking to cut their teeth with short fiction, especially for those who over-think their prose, their process. From notes on character names to telling the author to trust the subconscious and "to get out of the way," Brown, like Frank O'Hara, dares the writer to go "on your nerve."
Scott Whitaker (NBCC)
THE YEAR OF THE DOG THROWERS
Sid Gold is a teacher of writing, and a poet as well. That Sid Gold should come to poetry is a remarkably apt occurrence, for few people are quite so excited by words and their meanings as is the Harlem-born, Bronx and Manhattan-raised Gold. Words, words, words, words. Sid talks, and there is a danger in talking for most poets – the danger that they will have given as deep a consideration for the verbal as they do to their written language. In this, Gold is a sort of amphibian, able to breathe in two mediums…But where he may be, on the one hand, conversationally-speaking, broad-ranging and effusive, to say nothing of excitable and plangent, his poetry is finely-tuned, striking exactly the chord he seeks to strike with a minimum of effort. It is as if all of the words that bubble out of him are part of the creative fermentation process, so much excess verbiage, and somehow, what is left (on the page) is high-octane language. Merrill Leffler (Dryad Press) calls him "an urban storyteller whose poems….ride the back of a rhythmic jazz-like line. What may seem conversational is deceptively lyrical, nearly every poem a deliberate — and deliberative — riff in an assured, distinctive voice…"
ICE-SOLSTICE
Kelley Jean White
Kelley Jean White's poetry crackles with electricity. There is science here, math, the bones of the dead, Bach, and the music of despair which is a radio filling a boxcar. White's poems are tense, strong, full of big, jaunty, precise language that evoke the range of human loss, spiritual, emotional, sexual. Whether she writes about the loss of childhood memories or our mundane world of gasoline prices and nap-weary adults, White brings energy, immediacy and power.
S. Scott Whitaker (National Book Critics Circle)

redpajama_set_name: RedPajamaCommonCrawl