In encoding the io_err xdr. We used the xdr_rewind_stream API when we run out of space and want to encode the last accumulated error. We can avoid that by splitting the encoding API into two. first call: to reserved space. Second: do the encoding. If reserving space fails we can now use the previous place for the accumulated error Signed-off-by: Boaz Harrosh <bharrosh@xxxxxxxxxxx> --- fs/nfs/objlayout/objlayout.c | 25 ++++++++++++-------- fs/nfs/objlayout/pnfs_osd_xdr_cli.c | 41 ++++++++++++++-------------------- include/linux/pnfs_osd_xdr.h | 14 +++-------- 3 files changed, 36 insertions(+), 44 deletions(-) diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index e3c42fc..8892130 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c @@ -532,7 +532,7 @@ merge_ioerr(struct pnfs_osd_ioerr *dest_err, } static void -encode_accumulated_error(struct objlayout *objlay, struct xdr_stream *xdr) +encode_accumulated_error(struct objlayout *objlay, __be32 *p) { struct objlayout_io_state *state, *tmp; struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0}; @@ -564,7 +564,7 @@ encode_accumulated_error(struct objlayout *objlay, struct xdr_stream *xdr) objlayout_free_io_state(state); } - BUG_ON(pnfs_osd_xdr_encode_ioerr(xdr, &accumulated_err)); + pnfs_osd_xdr_encode_ioerr(p, &accumulated_err); } void @@ -574,7 +574,7 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay, { struct objlayout *objlay = OBJLAYOUT(pnfslay); struct objlayout_io_state *state, *tmp; - __be32 *start, *uninitialized_var(last_xdr); + __be32 *start; dprintk("%s: Begin\n", __func__); start = xdr_reserve_space(xdr, 4); @@ -583,10 +583,11 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay, spin_lock(&objlay->lock); list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) { + __be32 *last_xdr = NULL, *p; unsigned i; int res = 0; - for (i = 0; i < state->num_comps && !res; i++) { + for (i = 0; i < state->num_comps; i++) { struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i]; if (!ioerr->oer_errno) @@ -604,23 +605,27 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay, ioerr->oer_comp_offset, ioerr->oer_comp_length); - last_xdr = xdr->p; - res = pnfs_osd_xdr_encode_ioerr(xdr, &state->ioerrs[i]); + p = pnfs_osd_xdr_ioerr_reserve_space(xdr); + if (unlikely(!p)) { + res = -E2BIG; + break; /* accumulated_error */ + } + + last_xdr = p; + pnfs_osd_xdr_encode_ioerr(p, &state->ioerrs[i]); } /* TODO: use xdr_write_pages */ if (unlikely(res)) { /* no space for even one error descriptor */ - BUG_ON(last_xdr == start + 1); + BUG_ON(!last_xdr); /* we've encountered a situation with lots and lots of * errors and no space to encode them all. Use the last * available slot to report the union of all the * remaining errors. */ - xdr_rewind_stream(xdr, last_xdr - - pnfs_osd_ioerr_xdr_sz() / 4); - encode_accumulated_error(objlay, xdr); + encode_accumulated_error(objlay, last_xdr); goto loop_done; } list_del(&state->err_list); diff --git a/fs/nfs/objlayout/pnfs_osd_xdr_cli.c b/fs/nfs/objlayout/pnfs_osd_xdr_cli.c index b55131c..2aba671 100644 --- a/fs/nfs/objlayout/pnfs_osd_xdr_cli.c +++ b/fs/nfs/objlayout/pnfs_osd_xdr_cli.c @@ -369,22 +369,17 @@ pnfs_osd_xdr_encode_layoutupdate(struct xdr_stream *xdr, * struct pnfs_deviceid oid_device_id; * u64 oid_partition_id; * u64 oid_object_id; + * }; // xdr size 32 bytes */ -static inline int pnfs_osd_xdr_encode_objid(struct xdr_stream *xdr, - struct pnfs_osd_objid *object_id) +static inline __be32 * +pnfs_osd_xdr_encode_objid(__be32 *p, struct pnfs_osd_objid *object_id) { - __be32 *p; - - p = xdr_reserve_space(xdr, 32); - if (!p) - return -E2BIG; - p = xdr_encode_opaque_fixed(p, &object_id->oid_device_id.data, sizeof(object_id->oid_device_id.data)); p = xdr_encode_hyper(p, object_id->oid_partition_id); p = xdr_encode_hyper(p, object_id->oid_object_id); - return 0; + return p; } /* @@ -394,26 +389,24 @@ static inline int pnfs_osd_xdr_encode_objid(struct xdr_stream *xdr, * u64 oer_comp_length; * u32 oer_iswrite; * u32 oer_errno; - * }; + * }; // xdr size 32 + 24 bytes */ -int pnfs_osd_xdr_encode_ioerr(struct xdr_stream *xdr, - struct pnfs_osd_ioerr *ioerr) +void pnfs_osd_xdr_encode_ioerr(__be32 *p, struct pnfs_osd_ioerr *ioerr) { - __be32 *p; - int ret; - - ret = pnfs_osd_xdr_encode_objid(xdr, &ioerr->oer_component); - if (ret) - return ret; - - p = xdr_reserve_space(xdr, 24); - if (!p) - return -E2BIG; - + p = pnfs_osd_xdr_encode_objid(p, &ioerr->oer_component); p = xdr_encode_hyper(p, ioerr->oer_comp_offset); p = xdr_encode_hyper(p, ioerr->oer_comp_length); *p++ = cpu_to_be32(ioerr->oer_iswrite); *p = cpu_to_be32(ioerr->oer_errno); +} - return 0; +__be32 *pnfs_osd_xdr_ioerr_reserve_space(struct xdr_stream *xdr) +{ + __be32 * p; + + p = xdr_reserve_space(xdr, 32 + 24); + if (unlikely(!p)) + dprintk("%s: out of xdr space\n", __func__); + + return p; } diff --git a/include/linux/pnfs_osd_xdr.h b/include/linux/pnfs_osd_xdr.h index db22471..747d06d 100644 --- a/include/linux/pnfs_osd_xdr.h +++ b/include/linux/pnfs_osd_xdr.h @@ -279,14 +279,6 @@ struct pnfs_osd_ioerr { u32 oer_errno; }; -/* FIXME: remove */ -static inline unsigned -pnfs_osd_ioerr_xdr_sz(void) -{ - return pnfs_osd_objid_xdr_sz() + 2 + 2 + 1 + 1; -} - - /* OSD XDR API */ /* Layout helpers */ /* Layout decoding is done in two parts: @@ -348,8 +340,10 @@ extern __be32 * pnfs_osd_xdr_decode_layoutupdate(struct pnfs_osd_layoutupdate *lou, __be32 *p); /* osd_ioerror encoding/decoding (layout_return) */ -extern int -pnfs_osd_xdr_encode_ioerr(struct xdr_stream *xdr, struct pnfs_osd_ioerr *ioerr); +/* Client */ +extern __be32 *pnfs_osd_xdr_ioerr_reserve_space(struct xdr_stream *xdr); +extern void pnfs_osd_xdr_encode_ioerr(__be32 *p, struct pnfs_osd_ioerr *ioerr); +/* Server*/ extern __be32 * pnfs_osd_xdr_decode_ioerr(struct pnfs_osd_ioerr *ioerr, __be32 *p); -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html