osd: cmpext operator should ignore -ENOENT on read

The operator already handles the case where the object is truncated. If
an RBD user performs a read + cmpext/write of a sparse image, the read
of the missing object would return a zeroed buffer. Using that zeroed
buffer for the cmpext test would fail since it wasn't ignoring the
-ENOENT read failure.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2017-07-27 07:48:59 -04:00
parent 06243931ad
commit ea33368c1e
2 changed files with 46 additions and 3 deletions

View File

@ -4694,7 +4694,13 @@ struct C_ExtentCmpRead : public Context {
}
void finish(int r) override {
fill_extent_ctx->complete(r);
if (r == -ENOENT) {
osd_op.rval = 0;
read_bl.clear();
delete fill_extent_ctx;
} else {
fill_extent_ctx->complete(r);
}
fill_extent_ctx = nullptr;
if (osd_op.rval >= 0) {
@ -4708,7 +4714,10 @@ int PrimaryLogPG::do_extent_cmp(OpContext *ctx, OSDOp& osd_op)
dout(20) << __func__ << dendl;
ceph_osd_op& op = osd_op.op;
if (pool.info.require_rollback()) {
if (!ctx->obs->exists || ctx->obs->oi.is_whiteout()) {
dout(20) << __func__ << " object DNE" << dendl;
return finish_extent_cmp(osd_op, {});
} else if (pool.info.require_rollback()) {
// If there is a data digest and it is possible we are reading
// entire object, pass the digest.
auto& oi = ctx->new_obs.oi;
@ -4745,7 +4754,7 @@ int PrimaryLogPG::do_extent_cmp(OpContext *ctx, OSDOp& osd_op)
int result = do_osd_ops(ctx, read_ops);
if (result < 0) {
derr << "do_extent_cmp do_osd_ops failed " << result << dendl;
derr << __func__ << " failed " << result << dendl;
return result;
}
return finish_extent_cmp(osd_op, read_op.outdata);

View File

@ -1230,6 +1230,23 @@ TEST_F(LibRadosIoPP, CmpExtPP) {
ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
}
TEST_F(LibRadosIoPP, CmpExtDNEPP) {
bufferlist bl;
bl.append(std::string(4, '\0'));
bufferlist new_bl;
new_bl.append("CEPH");
ObjectWriteOperation write;
write.cmpext(0, bl, nullptr);
write.write(0, new_bl);
ASSERT_EQ(0, ioctx.operate("foo", &write));
ObjectReadOperation read;
read.read(0, bl.length(), NULL, NULL);
ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
}
TEST_F(LibRadosIoPP, CmpExtMismatchPP) {
bufferlist bl;
bl.append("ceph");
@ -1270,6 +1287,23 @@ TEST_F(LibRadosIoECPP, CmpExtPP) {
ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
}
TEST_F(LibRadosIoECPP, CmpExtDNEPP) {
bufferlist bl;
bl.append(std::string(4, '\0'));
bufferlist new_bl;
new_bl.append("CEPH");
ObjectWriteOperation write;
write.cmpext(0, bl, nullptr);
write.write_full(new_bl);
ASSERT_EQ(0, ioctx.operate("foo", &write));
ObjectReadOperation read;
read.read(0, bl.length(), NULL, NULL);
ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
}
TEST_F(LibRadosIoECPP, CmpExtMismatchPP) {
bufferlist bl;
bl.append("ceph");