summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-10-22 18:06:41 -0700
committerSage Weil <sage@inktank.com>2013-10-22 18:07:35 -0700
commitcd3a35aac7b2fbc5080c780e855ab1afcdf98cdb (patch)
tree9e9f9882d1bd41101766a43fabd949169a90c0f5
parent0e63847bba82e40cd14da9f36b318bb28de55f0e (diff)
downloadceph-cd3a35aac7b2fbc5080c780e855ab1afcdf98cdb.tar.gz
osd/ReplicatedPG: handle is_whiteout in do_osd_ops()
Most of the time we handle whiteouts by returning ENOENT before we even get this far. However, for a mixed read/write transaction (e.g., a guard) or certain ops (like create exclusive) we need to deal with the exists == true and whiteout flag set case explicitly. Signed-off-by: Sage Weil <sage@inktank.com>
-rw-r--r--src/osd/ReplicatedPG.cc19
1 files changed, 10 insertions, 9 deletions
diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc
index 849a68ac41c..94a8e0ab62b 100644
--- a/src/osd/ReplicatedPG.cc
+++ b/src/osd/ReplicatedPG.cc
@@ -2713,7 +2713,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
case CEPH_OSD_OP_STAT:
// note: stat does not require RD
{
- if (obs.exists) {
+ if (obs.exists && !oi.is_whiteout()) {
::encode(oi.size, osd_op.outdata);
::encode(oi.mtime, osd_op.outdata);
dout(10) << "stat oi has " << oi.size << " " << oi.mtime << dendl;
@@ -3059,7 +3059,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
}
if (op.extent.truncate_seq > seq) {
// write arrives before trimtrunc
- if (obs.exists) {
+ if (obs.exists && !oi.is_whiteout()) {
dout(10) << " truncate_seq " << op.extent.truncate_seq << " > current " << seq
<< ", truncating to " << op.extent.truncate_size << dendl;
t.truncate(coll, soid, op.extent.truncate_size);
@@ -3133,7 +3133,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
if (result < 0)
break;
assert(op.extent.length);
- if (obs.exists) {
+ if (obs.exists && !oi.is_whiteout()) {
t.zero(coll, soid, op.extent.offset, op.extent.length);
interval_set<uint64_t> ch;
ch.insert(op.extent.offset, op.extent.length);
@@ -3148,7 +3148,8 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
++ctx->num_write;
{
int flags = le32_to_cpu(op.flags);
- if (obs.exists && (flags & CEPH_OSD_OP_FLAG_EXCL)) {
+ if (obs.exists && !oi.is_whiteout() &&
+ (flags & CEPH_OSD_OP_FLAG_EXCL)) {
result = -EEXIST; /* this is an exclusive create */
} else {
if (osd_op.indata.length()) {
@@ -3162,7 +3163,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
goto fail;
}
if (category.size()) {
- if (obs.exists) {
+ if (obs.exists && !oi.is_whiteout()) {
if (obs.oi.category != category)
result = -EEXIST; // category cannot be reset
} else {
@@ -3187,7 +3188,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
++ctx->num_write;
{
// truncate
- if (!obs.exists) {
+ if (!obs.exists || oi.is_whiteout()) {
dout(10) << " object dne, truncate is a no-op" << dendl;
break;
}
@@ -3543,7 +3544,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
case CEPH_OSD_OP_OMAP_CMP:
++ctx->num_read;
{
- if (!obs.exists) {
+ if (!obs.exists || oi.is_whiteout()) {
result = -ENOENT;
break;
}
@@ -3650,7 +3651,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
case CEPH_OSD_OP_OMAPCLEAR:
++ctx->num_write;
{
- if (!obs.exists) {
+ if (!obs.exists || oi.is_whiteout()) {
result = -ENOENT;
break;
}
@@ -3663,7 +3664,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
case CEPH_OSD_OP_OMAPRMKEYS:
++ctx->num_write;
{
- if (!obs.exists) {
+ if (!obs.exists || oi.is_whiteout()) {
result = -ENOENT;
break;
}