@@ -204,23 +204,56 @@ void PGBackend::rollback(
204204 struct RollbackVisitor : public ObjectModDesc ::Visitor {
205205 const hobject_t &hoid;
206206 PGBackend *pg;
207+ const pg_log_entry_t &entry;
207208 ObjectStore::Transaction t;
208209 RollbackVisitor (
209210 const hobject_t &hoid,
210- PGBackend *pg) : hoid(hoid), pg(pg) {}
211+ PGBackend *pg,
212+ const pg_log_entry_t &entry) : hoid(hoid), pg(pg), entry(entry) {}
211213 void append (uint64_t old_size) override {
212214 ObjectStore::Transaction temp;
213- int s = static_cast <int >(pg->get_parent ()->whoami_shard ().shard );
214- const uint64_t shard_size = pg->object_size_to_shard_size (old_size, s);
215+ auto dpp = pg->get_parent ()->get_dpp ();
216+ const uint64_t shard_size = pg->object_size_to_shard_size (old_size,
217+ pg->get_parent ()->whoami_shard ().shard );
218+ ldpp_dout (dpp, 20 ) << " entry " << entry.version
219+ << " rollback append object_size " << old_size
220+ << " shard_size " << shard_size << dendl;
215221 pg->rollback_append (hoid, shard_size, &temp);
216222 temp.append (t);
217223 temp.swap (t);
218224 }
219225 void setattrs (map<string, std::optional<bufferlist> > &attrs) override {
220- ObjectStore::Transaction temp;
221- pg->rollback_setattrs (hoid, attrs, &temp);
222- temp.append (t);
223- temp.swap (t);
226+ auto dpp = pg->get_parent ()->get_dpp ();
227+ const pg_pool_t &pool = pg->get_parent ()->get_pool ();
228+ if (pool.is_nonprimary_shard (pg->get_parent ()->whoami_shard ().shard )) {
229+ if (entry.is_written_shard (pg->get_parent ()->whoami_shard ().shard )) {
230+ // Written shard - only rollback OI attr
231+ ldpp_dout (dpp, 20 ) << " entry " << entry.version
232+ << " written shard OI attr rollback "
233+ << pg->get_parent ()->whoami_shard ().shard
234+ << dendl;
235+ ObjectStore::Transaction temp;
236+ pg->rollback_setattrs (hoid, attrs, &temp, true );
237+ temp.append (t);
238+ temp.swap (t);
239+ } else {
240+ // Unwritten shard - nothing to rollback
241+ ldpp_dout (dpp, 20 ) << " entry " << entry.version
242+ << " unwritten shard skipping attr rollback "
243+ << pg->get_parent ()->whoami_shard ().shard
244+ << dendl;
245+ }
246+ } else {
247+ // Primary shard - rollback all attrs
248+ ldpp_dout (dpp, 20 ) << " entry " << entry.version
249+ << " primary_shard attr rollback "
250+ << pg->get_parent ()->whoami_shard ().shard
251+ << dendl;
252+ ObjectStore::Transaction temp;
253+ pg->rollback_setattrs (hoid, attrs, &temp, false );
254+ temp.append (t);
255+ temp.swap (t);
256+ }
224257 }
225258 void rmobject (version_t old_version) override {
226259 ObjectStore::Transaction temp;
@@ -247,17 +280,58 @@ void PGBackend::rollback(
247280 temp.swap (t);
248281 }
249282 void rollback_extents (
250- version_t gen,
251- const vector<pair<uint64_t , uint64_t > > &extents) override {
283+ const version_t gen,
284+ const std::vector<std::pair<uint64_t , uint64_t >> &extents,
285+ const uint64_t object_size,
286+ const std::vector<shard_id_set> &shards) override {
252287 ObjectStore::Transaction temp;
253- pg->rollback_extents (gen, extents, hoid, &temp);
254- temp.append (t);
255- temp.swap (t);
288+ const pg_pool_t & pool = pg->get_parent ()->get_pool ();
289+ ceph_assert (entry.written_shards .empty () ||
290+ pool.allows_ecoptimizations ());
291+ auto dpp = pg->get_parent ()->get_dpp ();
292+ bool donework = false ;
293+ ceph_assert (shards.empty () || shards.size () == extents.size ());
294+ for (unsigned int i = 0 ; i < extents.size (); i++) {
295+ if (shards.empty () ||
296+ shards[i].empty () ||
297+ shards[i].contains (pg->get_parent ()->whoami_shard ().shard )) {
298+ // Written shard - rollback extents
299+ const uint64_t shard_size = pg->object_size_to_shard_size (
300+ object_size,
301+ pg->get_parent ()->whoami_shard ().shard );
302+ ldpp_dout (dpp, 20 ) << " entry " << entry.version
303+ << " written shard rollback_extents "
304+ << entry.written_shards
305+ << " shards "
306+ << (shards.empty () ? shard_id_set () : shards[i])
307+ << " " << pg->get_parent ()->whoami_shard ().shard
308+ << " " << object_size
309+ << " " << shard_size
310+ << dendl;
311+ pg->rollback_extents (gen, extents[i].first , extents[i].second ,
312+ hoid, shard_size, &temp);
313+ donework = true ;
314+ } else {
315+ // Unwritten shard - nothing to rollback
316+ ldpp_dout (dpp, 20 ) << " entry " << entry.version
317+ << " unwritten shard skipping rollback_extents "
318+ << entry.written_shards
319+ << " " << pg->get_parent ()->whoami_shard ().shard
320+ << dendl;
321+ }
322+ }
323+ if (donework) {
324+ t.remove (
325+ pg->coll ,
326+ ghobject_t (hoid, gen, pg->get_parent ()->whoami_shard ().shard ));
327+ temp.append (t);
328+ temp.swap (t);
329+ }
256330 }
257331 };
258332
259333 ceph_assert (entry.mod_desc .can_rollback ());
260- RollbackVisitor vis (entry.soid , this );
334+ RollbackVisitor vis (entry.soid , this , entry );
261335 entry.mod_desc .visit (&vis);
262336 t->append (vis.t );
263337}
@@ -279,12 +353,28 @@ struct Trimmer : public ObjectModDesc::Visitor {
279353 }
280354 // try_rmobject defaults to rmobject
281355 void rollback_extents (
282- version_t gen,
283- const vector<pair<uint64_t , uint64_t > > &extents) override {
284- pg->trim_rollback_object (
285- soid,
286- gen,
287- t);
356+ const version_t gen,
357+ const std::vector<std::pair<uint64_t , uint64_t >> &extents,
358+ const uint64_t object_size,
359+ const std::vector<shard_id_set> &shards) override {
360+ auto dpp = pg->get_parent ()->get_dpp ();
361+ ceph_assert (shards.empty () || shards.size () == extents.size ());
362+ for (unsigned int i = 0 ; i < extents.size (); i++) {
363+ if (shards.empty () ||
364+ shards[i].empty () ||
365+ shards[i].contains (pg->get_parent ()->whoami_shard ().shard )) {
366+ ldpp_dout (dpp, 30 ) << __func__ << " trim " << shards << " "
367+ << pg->get_parent ()->whoami_shard ().shard << dendl;
368+ pg->trim_rollback_object (
369+ soid,
370+ gen,
371+ t);
372+ break ;
373+ } else {
374+ ldpp_dout (dpp, 20 ) << __func__ << " skipping trim " << shards << " "
375+ << pg->get_parent ()->whoami_shard ().shard << dendl;
376+ }
377+ }
288378 }
289379};
290380
@@ -481,25 +571,34 @@ int PGBackend::objects_get_attrs(
481571void PGBackend::rollback_setattrs (
482572 const hobject_t &hoid,
483573 map<string, std::optional<bufferlist> > &old_attrs,
484- ObjectStore::Transaction *t) {
574+ ObjectStore::Transaction *t,
575+ bool only_oi) {
485576 map<string, bufferlist, less<>> to_set;
486577 ceph_assert (!hoid.is_temp ());
487578 for (map<string, std::optional<bufferlist> >::iterator i = old_attrs.begin ();
488579 i != old_attrs.end ();
489580 ++i) {
490581 if (i->second ) {
491582 to_set[i->first ] = *(i->second );
492- } else {
583+ } else if (!only_oi) {
493584 t->rmattr (
494585 coll,
495586 ghobject_t (hoid, ghobject_t ::NO_GEN, get_parent ()->whoami_shard ().shard ),
496587 i->first );
497588 }
498589 }
499- t->setattrs (
500- coll,
501- ghobject_t (hoid, ghobject_t ::NO_GEN, get_parent ()->whoami_shard ().shard ),
502- to_set);
590+ if (only_oi) {
591+ t->setattr (
592+ coll,
593+ ghobject_t (hoid, ghobject_t ::NO_GEN, get_parent ()->whoami_shard ().shard ),
594+ OI_ATTR,
595+ to_set[OI_ATTR]);
596+ } else {
597+ t->setattrs (
598+ coll,
599+ ghobject_t (hoid, ghobject_t ::NO_GEN, get_parent ()->whoami_shard ().shard ),
600+ to_set);
601+ }
503602}
504603
505604void PGBackend::rollback_append (
@@ -533,6 +632,7 @@ void PGBackend::rollback_try_stash(
533632 version_t old_version,
534633 ObjectStore::Transaction *t) {
535634 ceph_assert (!hoid.is_temp ());
635+ dout (20 ) << __func__ << " " << hoid << " " << old_version << dendl;
536636 t->remove (
537637 coll,
538638 ghobject_t (hoid, ghobject_t ::NO_GEN, get_parent ()->whoami_shard ().shard ));
@@ -544,29 +644,41 @@ void PGBackend::rollback_try_stash(
544644
545645void PGBackend::rollback_extents (
546646 version_t gen,
547- const vector<pair<uint64_t , uint64_t > > &extents,
647+ const uint64_t offset,
648+ uint64_t length,
548649 const hobject_t &hoid,
650+ const uint64_t shard_size,
549651 ObjectStore::Transaction *t) {
550652 auto shard = get_parent ()->whoami_shard ().shard ;
551- for (auto &&extent: extents) {
653+ if (offset >= shard_size) {
654+ // extent on this shard is beyond the end of the object - nothing to do
655+ dout (20 ) << __func__ << " " << hoid << " "
656+ << offset << " ~" << length << " is out of range "
657+ << shard_size << dendl;
658+ } else {
659+ if (offset + length > shard_size) {
660+ dout (20 ) << __func__ << " " << length << " is being truncated" << dendl;
661+ // extent on this shard goes beyond end of the object - truncate length
662+ length = shard_size - offset;
663+ }
664+ dout (20 ) << __func__ << " " << hoid << " " << offset << " ~" << length
665+ << dendl;
552666 t->clone_range (
553667 coll,
554668 ghobject_t (hoid, gen, shard),
555669 ghobject_t (hoid, ghobject_t ::NO_GEN, shard),
556- extent. first ,
557- extent. second ,
558- extent. first );
670+ offset ,
671+ length ,
672+ offset );
559673 }
560- t->remove (
561- coll,
562- ghobject_t (hoid, gen, shard));
563674}
564675
565676void PGBackend::trim_rollback_object (
566677 const hobject_t &hoid,
567678 version_t old_version,
568679 ObjectStore::Transaction *t) {
569680 ceph_assert (!hoid.is_temp ());
681+ dout (20 ) << __func__ << " trim " << hoid << " " << old_version << dendl;
570682 t->remove (
571683 coll, ghobject_t (hoid, old_version, get_parent ()->whoami_shard ().shard ));
572684}
0 commit comments