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

Commit 35a21b42 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  NFSv4.1: Return NFS4ERR_BADSESSION to callbacks during session resets
  NFSv4.1: Fix the callback 'highest_used_slotid' behaviour
  pnfs-obj: Fix the comp_index != 0 case
  pnfs-obj: Bug when we are running out of bio
  nfs: add missing prefetch.h include
parents 5c80c71b 910ac68a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/namei.h>
#include <linux/bio.h>		/* struct bio */
#include <linux/buffer_head.h>	/* various write calls */
#include <linux/prefetch.h>

#include "blocklayout.h"

+1 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ enum nfs4_callback_opnum {
struct cb_process_state {
	__be32			drc_status;
	struct nfs_client	*clp;
	int			slotid;
};

struct cb_compound_hdr_arg {
@@ -166,7 +167,6 @@ extern unsigned nfs4_callback_layoutrecall(
	void *dummy, struct cb_process_state *cps);

extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses);
extern void nfs4_cb_take_slot(struct nfs_client *clp);

struct cb_devicenotifyitem {
	uint32_t		cbd_notify_type;
+19 −6
Original line number Diff line number Diff line
@@ -348,7 +348,7 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
	/* Normal */
	if (likely(args->csa_sequenceid == slot->seq_nr + 1)) {
		slot->seq_nr++;
		return htonl(NFS4_OK);
		goto out_ok;
	}

	/* Replay */
@@ -367,11 +367,14 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
	/* Wraparound */
	if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) {
		slot->seq_nr = 1;
		return htonl(NFS4_OK);
		goto out_ok;
	}

	/* Misordered request */
	return htonl(NFS4ERR_SEQ_MISORDERED);
out_ok:
	tbl->highest_used_slotid = args->csa_slotid;
	return htonl(NFS4_OK);
}

/*
@@ -433,26 +436,37 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
			      struct cb_sequenceres *res,
			      struct cb_process_state *cps)
{
	struct nfs4_slot_table *tbl;
	struct nfs_client *clp;
	int i;
	__be32 status = htonl(NFS4ERR_BADSESSION);

	cps->clp = NULL;

	clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid);
	if (clp == NULL)
		goto out;

	tbl = &clp->cl_session->bc_slot_table;

	spin_lock(&tbl->slot_tbl_lock);
	/* state manager is resetting the session */
	if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) {
		status = NFS4ERR_DELAY;
		spin_unlock(&tbl->slot_tbl_lock);
		status = htonl(NFS4ERR_DELAY);
		/* Return NFS4ERR_BADSESSION if we're draining the session
		 * in order to reset it.
		 */
		if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
			status = htonl(NFS4ERR_BADSESSION);
		goto out;
	}

	status = validate_seqid(&clp->cl_session->bc_slot_table, args);
	spin_unlock(&tbl->slot_tbl_lock);
	if (status)
		goto out;

	cps->slotid = args->csa_slotid;

	/*
	 * Check for pending referring calls.  If a match is found, a
	 * related callback was received before the response to the original
@@ -469,7 +483,6 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
	res->csr_slotid = args->csa_slotid;
	res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
	res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
	nfs4_cb_take_slot(clp);

out:
	cps->clp = clp; /* put in nfs4_callback_compound */
+7 −17
Original line number Diff line number Diff line
@@ -754,26 +754,15 @@ static void nfs4_callback_free_slot(struct nfs4_session *session)
	 * Let the state manager know callback processing done.
	 * A single slot, so highest used slotid is either 0 or -1
	 */
	tbl->highest_used_slotid--;
	tbl->highest_used_slotid = -1;
	nfs4_check_drain_bc_complete(session);
	spin_unlock(&tbl->slot_tbl_lock);
}

static void nfs4_cb_free_slot(struct nfs_client *clp)
static void nfs4_cb_free_slot(struct cb_process_state *cps)
{
	if (clp && clp->cl_session)
		nfs4_callback_free_slot(clp->cl_session);
}

/* A single slot, so highest used slotid is either 0 or -1 */
void nfs4_cb_take_slot(struct nfs_client *clp)
{
	struct nfs4_slot_table *tbl = &clp->cl_session->bc_slot_table;

	spin_lock(&tbl->slot_tbl_lock);
	tbl->highest_used_slotid++;
	BUG_ON(tbl->highest_used_slotid != 0);
	spin_unlock(&tbl->slot_tbl_lock);
	if (cps->slotid != -1)
		nfs4_callback_free_slot(cps->clp->cl_session);
}

#else /* CONFIG_NFS_V4_1 */
@@ -784,7 +773,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
	return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
}

static void nfs4_cb_free_slot(struct nfs_client *clp)
static void nfs4_cb_free_slot(struct cb_process_state *cps)
{
}
#endif /* CONFIG_NFS_V4_1 */
@@ -866,6 +855,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
	struct cb_process_state cps = {
		.drc_status = 0,
		.clp = NULL,
		.slotid = -1,
	};
	unsigned int nops = 0;

@@ -906,7 +896,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r

	*hdr_res.status = status;
	*hdr_res.nops = htonl(nops);
	nfs4_cb_free_slot(cps.clp);
	nfs4_cb_free_slot(&cps);
	nfs_put_client(cps.clp);
	dprintk("%s: done, status = %u\n", __func__, ntohl(status));
	return rpc_success;
+12 −16
Original line number Diff line number Diff line
@@ -479,7 +479,6 @@ static int _io_check(struct objio_state *ios, bool is_write)
	for (i = 0; i <  ios->numdevs; i++) {
		struct osd_sense_info osi;
		struct osd_request *or = ios->per_dev[i].or;
		unsigned dev;
		int ret;

		if (!or)
@@ -500,9 +499,8 @@ static int _io_check(struct objio_state *ios, bool is_write)

			continue; /* we recovered */
		}
		dev = ios->per_dev[i].dev;
		objlayout_io_set_result(&ios->ol_state, dev,
					&ios->layout->comps[dev].oc_object_id,
		objlayout_io_set_result(&ios->ol_state, i,
					&ios->layout->comps[i].oc_object_id,
					osd_pri_2_pnfs_err(osi.osd_err_pri),
					ios->per_dev[i].offset,
					ios->per_dev[i].length,
@@ -589,22 +587,19 @@ static void _calc_stripe_info(struct objio_state *ios, u64 file_offset,
}

static int _add_stripe_unit(struct objio_state *ios,  unsigned *cur_pg,
		unsigned pgbase, struct _objio_per_comp *per_dev, int cur_len,
		unsigned pgbase, struct _objio_per_comp *per_dev, int len,
		gfp_t gfp_flags)
{
	unsigned pg = *cur_pg;
	int cur_len = len;
	struct request_queue *q =
			osd_request_queue(_io_od(ios, per_dev->dev));

	per_dev->length += cur_len;

	if (per_dev->bio == NULL) {
		unsigned stripes = ios->layout->num_comps /
						     ios->layout->mirrors_p1;
		unsigned pages_in_stripe = stripes *
		unsigned pages_in_stripe = ios->layout->group_width *
				      (ios->layout->stripe_unit / PAGE_SIZE);
		unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) /
				    stripes;
				    ios->layout->group_width;

		if (BIO_MAX_PAGES_KMALLOC < bio_size)
			bio_size = BIO_MAX_PAGES_KMALLOC;
@@ -632,6 +627,7 @@ static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg,
	}
	BUG_ON(cur_len);

	per_dev->length += len;
	*cur_pg = pg;
	return 0;
}
@@ -650,7 +646,7 @@ static int _prepare_one_group(struct objio_state *ios, u64 length,
	int ret = 0;

	while (length) {
		struct _objio_per_comp *per_dev = &ios->per_dev[dev];
		struct _objio_per_comp *per_dev = &ios->per_dev[dev - first_dev];
		unsigned cur_len, page_off = 0;

		if (!per_dev->length) {
@@ -670,8 +666,8 @@ static int _prepare_one_group(struct objio_state *ios, u64 length,
				cur_len = stripe_unit;
			}

			if (max_comp < dev)
				max_comp = dev;
			if (max_comp < dev - first_dev)
				max_comp = dev - first_dev;
		} else {
			cur_len = stripe_unit;
		}
@@ -806,7 +802,7 @@ static int _read_mirrors(struct objio_state *ios, unsigned cur_comp)
	struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp];
	unsigned dev = per_dev->dev;
	struct pnfs_osd_object_cred *cred =
			&ios->layout->comps[dev];
			&ios->layout->comps[cur_comp];
	struct osd_obj_id obj = {
		.partition = cred->oc_object_id.oid_partition_id,
		.id = cred->oc_object_id.oid_object_id,
@@ -904,7 +900,7 @@ static int _write_mirrors(struct objio_state *ios, unsigned cur_comp)
	for (; cur_comp < last_comp; ++cur_comp, ++dev) {
		struct osd_request *or = NULL;
		struct pnfs_osd_object_cred *cred =
					&ios->layout->comps[dev];
					&ios->layout->comps[cur_comp];
		struct osd_obj_id obj = {
			.partition = cred->oc_object_id.oid_partition_id,
			.id = cred->oc_object_id.oid_object_id,
Loading