Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1acbbb4e authored by Fred Isaman's avatar Fred Isaman Committed by Trond Myklebust
Browse files

NFS4.1: make pnfs_ld_[read|write]_done consistent



The two functions had diverged quite a bit, with the write function
being a bit more robust than the read.

However, these still break badly in the desc->pg_bsize < PAGE_CACHE_SIZE case,
as then there is nothing hanging on the data->pages list, and the resend
ends up doing nothing.  This will be fixed in a patch later in the series.

Signed-off-by: default avatarFred Isaman <iisaman@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent a20c6bec
Loading
Loading
Loading
Loading
+38 −26
Original line number Diff line number Diff line
@@ -1189,27 +1189,27 @@ static int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head *
	return 0;
}

/*
 * Called by non rpc-based layout drivers
 */
void pnfs_ld_write_done(struct nfs_write_data *data)
static void pnfs_ld_handle_write_error(struct nfs_write_data *data)
{
	if (likely(!data->pnfs_error)) {
		pnfs_set_layoutcommit(data);
		data->mds_ops->rpc_call_done(&data->task, data);
	} else {
	dprintk("pnfs write error = %d\n", data->pnfs_error);
	if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags &
	    PNFS_LAYOUTRET_ON_ERROR) {
			/* Don't lo_commit on error, Server will needs to
			 * preform a file recovery.
			 */
			clear_bit(NFS_INO_LAYOUTCOMMIT,
				  &NFS_I(data->inode)->flags);
		clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(data->inode)->flags);
		pnfs_return_layout(data->inode);
	}
	data->task.tk_status = pnfs_write_done_resend_to_mds(data->inode, &data->pages);
}

/*
 * Called by non rpc-based layout drivers
 */
void pnfs_ld_write_done(struct nfs_write_data *data)
{
	if (likely(!data->pnfs_error)) {
		pnfs_set_layoutcommit(data);
		data->mds_ops->rpc_call_done(&data->task, data);
	} else
		pnfs_ld_handle_write_error(data);
	put_lseg(data->lseg);
	data->mds_ops->rpc_release(data);
}
@@ -1293,26 +1293,38 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
}
EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);

static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
static int pnfs_read_done_resend_to_mds(struct inode *inode, struct list_head *head)
{
	struct nfs_pageio_descriptor pgio;
	LIST_HEAD(failed);

	put_lseg(data->lseg);
	data->lseg = NULL;
	dprintk("pnfs write error = %d\n", data->pnfs_error);
	if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags &
						PNFS_LAYOUTRET_ON_ERROR)
		pnfs_return_layout(data->inode);

	nfs_pageio_init_read_mds(&pgio, data->inode);

	while (!list_empty(&data->pages)) {
		struct nfs_page *req = nfs_list_entry(data->pages.next);
	/* Resend all requests through the MDS */
	nfs_pageio_init_read_mds(&pgio, inode);
	while (!list_empty(head)) {
		struct nfs_page *req = nfs_list_entry(head->next);

		nfs_list_remove_request(req);
		nfs_pageio_add_request(&pgio, req);
		if (!nfs_pageio_add_request(&pgio, req))
			nfs_list_add_request(req, &failed);
	}
	nfs_pageio_complete(&pgio);

	if (!list_empty(&failed)) {
		list_move(&failed, head);
		return -EIO;
	}
	return 0;
}

static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
{
	dprintk("pnfs read error = %d\n", data->pnfs_error);
	if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags &
	    PNFS_LAYOUTRET_ON_ERROR) {
		clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(data->inode)->flags);
		pnfs_return_layout(data->inode);
	}
	data->task.tk_status = pnfs_read_done_resend_to_mds(data->inode, &data->pages);
}

/*