Commit 35a21b42 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

* '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
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/bio.h> /* struct bio */ #include <linux/bio.h> /* struct bio */
#include <linux/buffer_head.h> /* various write calls */ #include <linux/buffer_head.h> /* various write calls */
#include <linux/prefetch.h>
#include "blocklayout.h" #include "blocklayout.h"
......
...@@ -38,6 +38,7 @@ enum nfs4_callback_opnum { ...@@ -38,6 +38,7 @@ enum nfs4_callback_opnum {
struct cb_process_state { struct cb_process_state {
__be32 drc_status; __be32 drc_status;
struct nfs_client *clp; struct nfs_client *clp;
int slotid;
}; };
struct cb_compound_hdr_arg { struct cb_compound_hdr_arg {
...@@ -166,7 +167,6 @@ extern unsigned nfs4_callback_layoutrecall( ...@@ -166,7 +167,6 @@ extern unsigned nfs4_callback_layoutrecall(
void *dummy, struct cb_process_state *cps); void *dummy, struct cb_process_state *cps);
extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses); extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses);
extern void nfs4_cb_take_slot(struct nfs_client *clp);
struct cb_devicenotifyitem { struct cb_devicenotifyitem {
uint32_t cbd_notify_type; uint32_t cbd_notify_type;
......
...@@ -348,7 +348,7 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args) ...@@ -348,7 +348,7 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
/* Normal */ /* Normal */
if (likely(args->csa_sequenceid == slot->seq_nr + 1)) { if (likely(args->csa_sequenceid == slot->seq_nr + 1)) {
slot->seq_nr++; slot->seq_nr++;
return htonl(NFS4_OK); goto out_ok;
} }
/* Replay */ /* Replay */
...@@ -367,11 +367,14 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args) ...@@ -367,11 +367,14 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
/* Wraparound */ /* Wraparound */
if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) { if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) {
slot->seq_nr = 1; slot->seq_nr = 1;
return htonl(NFS4_OK); goto out_ok;
} }
/* Misordered request */ /* Misordered request */
return htonl(NFS4ERR_SEQ_MISORDERED); 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, ...@@ -433,26 +436,37 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
struct cb_sequenceres *res, struct cb_sequenceres *res,
struct cb_process_state *cps) struct cb_process_state *cps)
{ {
struct nfs4_slot_table *tbl;
struct nfs_client *clp; struct nfs_client *clp;
int i; int i;
__be32 status = htonl(NFS4ERR_BADSESSION); __be32 status = htonl(NFS4ERR_BADSESSION);
cps->clp = NULL;
clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid); clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid);
if (clp == NULL) if (clp == NULL)
goto out; goto out;
tbl = &clp->cl_session->bc_slot_table;
spin_lock(&tbl->slot_tbl_lock);
/* state manager is resetting the session */ /* state manager is resetting the session */
if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) { 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; goto out;
} }
status = validate_seqid(&clp->cl_session->bc_slot_table, args); status = validate_seqid(&clp->cl_session->bc_slot_table, args);
spin_unlock(&tbl->slot_tbl_lock);
if (status) if (status)
goto out; goto out;
cps->slotid = args->csa_slotid;
/* /*
* Check for pending referring calls. If a match is found, a * Check for pending referring calls. If a match is found, a
* related callback was received before the response to the original * related callback was received before the response to the original
...@@ -469,7 +483,6 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args, ...@@ -469,7 +483,6 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
res->csr_slotid = args->csa_slotid; res->csr_slotid = args->csa_slotid;
res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
nfs4_cb_take_slot(clp);
out: out:
cps->clp = clp; /* put in nfs4_callback_compound */ cps->clp = clp; /* put in nfs4_callback_compound */
......
...@@ -754,26 +754,15 @@ static void nfs4_callback_free_slot(struct nfs4_session *session) ...@@ -754,26 +754,15 @@ static void nfs4_callback_free_slot(struct nfs4_session *session)
* Let the state manager know callback processing done. * Let the state manager know callback processing done.
* A single slot, so highest used slotid is either 0 or -1 * 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); nfs4_check_drain_bc_complete(session);
spin_unlock(&tbl->slot_tbl_lock); 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) if (cps->slotid != -1)
nfs4_callback_free_slot(clp->cl_session); nfs4_callback_free_slot(cps->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);
} }
#else /* CONFIG_NFS_V4_1 */ #else /* CONFIG_NFS_V4_1 */
...@@ -784,7 +773,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) ...@@ -784,7 +773,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
return htonl(NFS4ERR_MINOR_VERS_MISMATCH); 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 */ #endif /* CONFIG_NFS_V4_1 */
...@@ -866,6 +855,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r ...@@ -866,6 +855,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
struct cb_process_state cps = { struct cb_process_state cps = {
.drc_status = 0, .drc_status = 0,
.clp = NULL, .clp = NULL,
.slotid = -1,
}; };
unsigned int nops = 0; unsigned int nops = 0;
...@@ -906,7 +896,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r ...@@ -906,7 +896,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
*hdr_res.status = status; *hdr_res.status = status;
*hdr_res.nops = htonl(nops); *hdr_res.nops = htonl(nops);
nfs4_cb_free_slot(cps.clp); nfs4_cb_free_slot(&cps);
nfs_put_client(cps.clp); nfs_put_client(cps.clp);
dprintk("%s: done, status = %u\n", __func__, ntohl(status)); dprintk("%s: done, status = %u\n", __func__, ntohl(status));
return rpc_success; return rpc_success;
......
...@@ -479,7 +479,6 @@ static int _io_check(struct objio_state *ios, bool is_write) ...@@ -479,7 +479,6 @@ static int _io_check(struct objio_state *ios, bool is_write)
for (i = 0; i < ios->numdevs; i++) { for (i = 0; i < ios->numdevs; i++) {
struct osd_sense_info osi; struct osd_sense_info osi;
struct osd_request *or = ios->per_dev[i].or; struct osd_request *or = ios->per_dev[i].or;
unsigned dev;
int ret; int ret;
if (!or) if (!or)
...@@ -500,9 +499,8 @@ static int _io_check(struct objio_state *ios, bool is_write) ...@@ -500,9 +499,8 @@ static int _io_check(struct objio_state *ios, bool is_write)
continue; /* we recovered */ continue; /* we recovered */
} }
dev = ios->per_dev[i].dev; objlayout_io_set_result(&ios->ol_state, i,
objlayout_io_set_result(&ios->ol_state, dev, &ios->layout->comps[i].oc_object_id,
&ios->layout->comps[dev].oc_object_id,
osd_pri_2_pnfs_err(osi.osd_err_pri), osd_pri_2_pnfs_err(osi.osd_err_pri),
ios->per_dev[i].offset, ios->per_dev[i].offset,
ios->per_dev[i].length, ios->per_dev[i].length,
...@@ -589,22 +587,19 @@ static void _calc_stripe_info(struct objio_state *ios, u64 file_offset, ...@@ -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, 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) gfp_t gfp_flags)
{ {
unsigned pg = *cur_pg; unsigned pg = *cur_pg;
int cur_len = len;
struct request_queue *q = struct request_queue *q =
osd_request_queue(_io_od(ios, per_dev->dev)); osd_request_queue(_io_od(ios, per_dev->dev));
per_dev->length += cur_len;
if (per_dev->bio == NULL) { if (per_dev->bio == NULL) {
unsigned stripes = ios->layout->num_comps / unsigned pages_in_stripe = ios->layout->group_width *
ios->layout->mirrors_p1;
unsigned pages_in_stripe = stripes *
(ios->layout->stripe_unit / PAGE_SIZE); (ios->layout->stripe_unit / PAGE_SIZE);
unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) / unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) /
stripes; ios->layout->group_width;
if (BIO_MAX_PAGES_KMALLOC < bio_size) if (BIO_MAX_PAGES_KMALLOC < bio_size)
bio_size = BIO_MAX_PAGES_KMALLOC; bio_size = BIO_MAX_PAGES_KMALLOC;
...@@ -632,6 +627,7 @@ static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg, ...@@ -632,6 +627,7 @@ static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg,
} }
BUG_ON(cur_len); BUG_ON(cur_len);
per_dev->length += len;
*cur_pg = pg; *cur_pg = pg;
return 0; return 0;
} }
...@@ -650,7 +646,7 @@ static int _prepare_one_group(struct objio_state *ios, u64 length, ...@@ -650,7 +646,7 @@ static int _prepare_one_group(struct objio_state *ios, u64 length,
int ret = 0; int ret = 0;
while (length) { 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; unsigned cur_len, page_off = 0;
if (!per_dev->length) { if (!per_dev->length) {
...@@ -670,8 +666,8 @@ static int _prepare_one_group(struct objio_state *ios, u64 length, ...@@ -670,8 +666,8 @@ static int _prepare_one_group(struct objio_state *ios, u64 length,
cur_len = stripe_unit; cur_len = stripe_unit;
} }
if (max_comp < dev) if (max_comp < dev - first_dev)
max_comp = dev; max_comp = dev - first_dev;
} else { } else {
cur_len = stripe_unit; cur_len = stripe_unit;
} }
...@@ -806,7 +802,7 @@ static int _read_mirrors(struct objio_state *ios, unsigned cur_comp) ...@@ -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]; struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp];
unsigned dev = per_dev->dev; unsigned dev = per_dev->dev;
struct pnfs_osd_object_cred *cred = struct pnfs_osd_object_cred *cred =
&ios->layout->comps[dev]; &ios->layout->comps[cur_comp];
struct osd_obj_id obj = { struct osd_obj_id obj = {
.partition = cred->oc_object_id.oid_partition_id, .partition = cred->oc_object_id.oid_partition_id,
.id = cred->oc_object_id.oid_object_id, .id = cred->oc_object_id.oid_object_id,
...@@ -904,7 +900,7 @@ static int _write_mirrors(struct objio_state *ios, unsigned cur_comp) ...@@ -904,7 +900,7 @@ static int _write_mirrors(struct objio_state *ios, unsigned cur_comp)
for (; cur_comp < last_comp; ++cur_comp, ++dev) { for (; cur_comp < last_comp; ++cur_comp, ++dev) {
struct osd_request *or = NULL; struct osd_request *or = NULL;
struct pnfs_osd_object_cred *cred = struct pnfs_osd_object_cred *cred =
&ios->layout->comps[dev]; &ios->layout->comps[cur_comp];
struct osd_obj_id obj = { struct osd_obj_id obj = {
.partition = cred->oc_object_id.oid_partition_id, .partition = cred->oc_object_id.oid_partition_id,
.id = cred->oc_object_id.oid_object_id, .id = cred->oc_object_id.oid_object_id,
......
...@@ -170,6 +170,9 @@ int pnfs_osd_xdr_decode_layout_map(struct pnfs_osd_layout *layout, ...@@ -170,6 +170,9 @@ int pnfs_osd_xdr_decode_layout_map(struct pnfs_osd_layout *layout,
p = _osd_xdr_decode_data_map(p, &layout->olo_map); p = _osd_xdr_decode_data_map(p, &layout->olo_map);
layout->olo_comps_index = be32_to_cpup(p++); layout->olo_comps_index = be32_to_cpup(p++);
layout->olo_num_comps = be32_to_cpup(p++); layout->olo_num_comps = be32_to_cpup(p++);
dprintk("%s: olo_comps_index=%d olo_num_comps=%d\n", __func__,
layout->olo_comps_index, layout->olo_num_comps);
iter->total_comps = layout->olo_num_comps; iter->total_comps = layout->olo_num_comps;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment