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

Commit 942e3d72 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

Merge branch 'pnfs_generic'

* pnfs_generic:
  NFSv4.1/pNFS: Cleanup constify struct pnfs_layout_range arguments
  NFSv4.1/pnfs: Cleanup copying of pnfs_layout_range structures
  NFSv4.1/pNFS: Cleanup pnfs_mark_matching_lsegs_invalid()
  NFSv4.1/pNFS: Fix a race in initiate_file_draining()
  NFSv4.1/pNFS: pnfs_error_mark_layout_for_return() must always return layout
  NFSv4.1/pNFS: pnfs_mark_matching_lsegs_return() should set the iomode
  NFSv4.1/pNFS: Use nfs4_stateid_copy for copying stateids
  NFSv4.1/pNFS: Don't pass stateids by value to pnfs_send_layoutreturn()
  NFS: Relax requirements in nfs_flush_incompatible
  NFSv4.1/pNFS: Don't queue up a new commit if the layout segment is invalid
  NFS: Allow multiple commit requests in flight per file
  NFS/pNFS: Fix up pNFS write reschedule layering violations and bugs
  NFSv4: List stateid information in the callback tracepoints
  NFSv4.1/pNFS: Don't return NFS4ERR_DELAY unnecessarily in CB_LAYOUTRECALL
  NFSv4.1/pNFS: Ensure we enforce RFC5661 Section 12.5.5.2.1
  pNFS: If we have to delay the layout callback, mark the layout for return
  NFSv4.1/pNFS: Add a helper to mark the layout as returned
  pNFS: Ensure nfs4_layoutget_prepare returns the correct error
parents 58baac0a 506c0d68
Loading
Loading
Loading
Loading
+45 −7
Original line number Diff line number Diff line
@@ -83,8 +83,11 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,

	res = htonl(NFS4ERR_BADHANDLE);
	inode = nfs_delegation_find_inode(cps->clp, &args->fh);
	if (inode == NULL)
	if (inode == NULL) {
		trace_nfs4_cb_recall(cps->clp, &args->fh, NULL,
				&args->stateid, -ntohl(res));
		goto out;
	}
	/* Set up a helper thread to actually return the delegation */
	switch (nfs_async_inode_return_delegation(inode, &args->stateid)) {
	case 0:
@@ -96,7 +99,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
	default:
		res = htonl(NFS4ERR_RESOURCE);
	}
	trace_nfs4_recall_delegation(inode, -ntohl(res));
	trace_nfs4_cb_recall(cps->clp, &args->fh, inode,
			&args->stateid, -ntohl(res));
	iput(inode);
out:
	dprintk("%s: exit with status = %d\n", __func__, ntohl(res));
@@ -160,6 +164,22 @@ static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp,
	return lo;
}

/*
 * Enforce RFC5661 section 12.5.5.2.1. (Layout Recall and Return Sequencing)
 */
static bool pnfs_check_stateid_sequence(struct pnfs_layout_hdr *lo,
					const nfs4_stateid *new)
{
	u32 oldseq, newseq;

	oldseq = be32_to_cpu(lo->plh_stateid.seqid);
	newseq = be32_to_cpu(new->seqid);

	if (newseq > oldseq + 1)
		return false;
	return true;
}

static u32 initiate_file_draining(struct nfs_client *clp,
				  struct cb_layoutrecallargs *args)
{
@@ -169,34 +189,52 @@ static u32 initiate_file_draining(struct nfs_client *clp,
	LIST_HEAD(free_me_list);

	lo = get_layout_by_fh(clp, &args->cbl_fh, &args->cbl_stateid);
	if (!lo)
	if (!lo) {
		trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, NULL,
				&args->cbl_stateid, -rv);
		goto out;
	}

	ino = lo->plh_inode;

	spin_lock(&ino->i_lock);
	if (!pnfs_check_stateid_sequence(lo, &args->cbl_stateid)) {
		rv = NFS4ERR_DELAY;
		goto unlock;
	}
	pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
	spin_unlock(&ino->i_lock);

	pnfs_layoutcommit_inode(ino, false);

	spin_lock(&ino->i_lock);
	if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) ||
	    pnfs_mark_matching_lsegs_invalid(lo, &free_me_list,
					&args->cbl_range)) {
	/*
	 * Enforce RFC5661 Section 12.5.5.2.1.5 (Bulk Recall and Return)
	 */
	if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) {
		rv = NFS4ERR_DELAY;
		goto unlock;
	}

	if (pnfs_mark_matching_lsegs_return(lo, &free_me_list,
					&args->cbl_range)) {
		rv = NFS4_OK;
		goto unlock;
	}

	if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
		NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
			&args->cbl_range);
	}
	pnfs_mark_layout_returned_if_empty(lo);
unlock:
	spin_unlock(&ino->i_lock);
	pnfs_free_lseg_list(&free_me_list);
	/* Free all lsegs that are attached to commit buckets */
	nfs_commit_inode(ino, 0);
	pnfs_put_layout_hdr(lo);
	trace_nfs4_cb_layoutrecall_inode(clp, &args->cbl_fh, ino, -rv);
	trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino,
			&args->cbl_stateid, -rv);
	iput(ino);
out:
	return rv;
+24 −9
Original line number Diff line number Diff line
@@ -117,12 +117,6 @@ static inline int put_dreq(struct nfs_direct_req *dreq)
	return atomic_dec_and_test(&dreq->io_count);
}

void nfs_direct_set_resched_writes(struct nfs_direct_req *dreq)
{
	dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
}
EXPORT_SYMBOL_GPL(nfs_direct_set_resched_writes);

static void
nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr)
{
@@ -735,14 +729,20 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
		nfs_direct_write_complete(dreq, data->inode);
}

static void nfs_direct_error_cleanup(struct nfs_inode *nfsi)
static void nfs_direct_resched_write(struct nfs_commit_info *cinfo,
		struct nfs_page *req)
{
	/* There is no lock to clear */
	struct nfs_direct_req *dreq = cinfo->dreq;

	spin_lock(&dreq->lock);
	dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
	spin_unlock(&dreq->lock);
	nfs_mark_request_commit(req, NULL, cinfo, 0);
}

static const struct nfs_commit_completion_ops nfs_direct_commit_completion_ops = {
	.completion = nfs_direct_commit_complete,
	.error_cleanup = nfs_direct_error_cleanup,
	.resched_write = nfs_direct_resched_write,
};

static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
@@ -847,10 +847,25 @@ static void nfs_write_sync_pgio_error(struct list_head *head)
	}
}

static void nfs_direct_write_reschedule_io(struct nfs_pgio_header *hdr)
{
	struct nfs_direct_req *dreq = hdr->dreq;

	spin_lock(&dreq->lock);
	if (dreq->error == 0) {
		dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
		/* fake unstable write to let common nfs resend pages */
		hdr->verf.committed = NFS_UNSTABLE;
		hdr->good_bytes = hdr->args.count;
	}
	spin_unlock(&dreq->lock);
}

static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = {
	.error_cleanup = nfs_write_sync_pgio_error,
	.init_hdr = nfs_direct_pgio_init,
	.completion = nfs_direct_write_completion,
	.reschedule_io = nfs_direct_write_reschedule_io,
};


+1 −1
Original line number Diff line number Diff line
@@ -514,7 +514,7 @@ static void nfs_check_dirty_writeback(struct page *page,
	 * so it will not block due to pages that will shortly be freeable.
	 */
	nfsi = NFS_I(mapping->host);
	if (test_bit(NFS_INO_COMMIT, &nfsi->flags)) {
	if (atomic_read(&nfsi->commit_info.rpcs_out)) {
		*writeback = true;
		return;
	}
+1 −12
Original line number Diff line number Diff line
@@ -941,18 +941,7 @@ static void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs)
			hdr->args.count,
			(unsigned long long)hdr->args.offset);

		if (!hdr->dreq) {
			struct nfs_open_context *ctx;

			ctx = nfs_list_entry(hdr->pages.next)->wb_context;
			set_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
			hdr->completion_ops->error_cleanup(&hdr->pages);
		} else {
			nfs_direct_set_resched_writes(hdr->dreq);
			/* fake unstable write to let common nfs resend pages */
			hdr->verf.committed = NFS_UNSTABLE;
			hdr->good_bytes = hdr->args.count;
		}
		hdr->completion_ops->reschedule_io(hdr);
		return;
	}

+6 −1
Original line number Diff line number Diff line
@@ -264,6 +264,12 @@ static inline bool nfs_pgio_has_mirroring(struct nfs_pageio_descriptor *desc)
	return desc->pg_mirror_count > 1;
}

static inline bool nfs_match_open_context(const struct nfs_open_context *ctx1,
		const struct nfs_open_context *ctx2)
{
	return ctx1->cred == ctx2->cred && ctx1->state == ctx2->state;
}

/* nfs2xdr.c */
extern struct rpc_procinfo nfs_procedures[];
extern int nfs2_decode_dirent(struct xdr_stream *,
@@ -519,7 +525,6 @@ static inline void nfs_inode_dio_wait(struct inode *inode)
	inode_dio_wait(inode);
}
extern ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq);
extern void nfs_direct_set_resched_writes(struct nfs_direct_req *dreq);

/* nfs4proc.c */
extern void __nfs4_read_done_cb(struct nfs_pgio_header *);
Loading