We were somewhat inadvertantly returning a data payload for write
operations. This was a side-effect of the OpContext::ops field being a
reference to MOSDOp::ops: the return data would end up there, and then
the MOSDOpReply ctor would copy it.
Fix this by breaking the ref, and making the do_op() logic also claim
return result data for error values (so that errors can return data to the
caller).
Signed-off-by: Sage Weil <sage@inktank.com>
// possible to construct an operation that does a read, does a guard
// check (e.g., CMPXATTR), and then a write. Then we either succeed
// with the write, or return a CMPXATTR and the read value.
- if (ctx->op_t.empty() && !ctx->modify) {
+ if ((ctx->op_t.empty() && !ctx->modify) || result < 0) {
// read.
ctx->reply->claim_op_out_data(ctx->ops);
ctx->reply->get_header().data_off = ctx->data_off;
} else {
// write. normalize the result code.
- if (result > 0)
+ if (result > 0) {
+ dout(20) << " zeroing write result code " << result << dendl;
result = 0;
+ }
}
ctx->reply->set_result(result);
struct OpContext {
OpRequestRef op;
osd_reqid_t reqid;
- vector<OSDOp>& ops;
+ vector<OSDOp> ops;
const ObjectState *obs; // Old objectstate
const SnapSet *snapset; // Old snapset