}
snap_name = s.c_str();
+ if (header->snap_seq > snap_id)
+ return -ESTALE;
+
const char *cur_snap_name;
for (cur_snap_name = snap_names; cur_snap_name < end; cur_snap_name += strlen(cur_snap_name) + 1) {
if (strncmp(cur_snap_name, snap_name, end - cur_snap_name) == 0)
return r;
Mutex::Locker l(ictx->md_lock);
- r = add_snap(ictx, snap_name);
+ do {
+ r = add_snap(ictx, snap_name);
+ } while (r == -ESTALE);
if (r < 0)
return r;
using ::librbd::parent_spec;
using ::librbd::cls_client::get_protection_status;
using ::librbd::cls_client::set_protection_status;
+using ::librbd::cls_client::old_snapshot_add;
static char *random_buf(size_t len)
{
ioctx.close();
ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
}
+
+TEST(cls_rbd, snapid_race)
+{
+ librados::Rados rados;
+ librados::IoCtx ioctx;
+ string pool_name = get_temp_pool_name();
+
+ ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
+ ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
+
+ buffer::list bl;
+ buffer::ptr bp(4096);
+ bp.zero();
+ bl.append(bp);
+
+ string oid = "foo";
+ ASSERT_EQ(4096, ioctx.write(oid, bl, 4096, 0));
+ ASSERT_EQ(0, old_snapshot_add(&ioctx, oid, 1, "test1"));
+ ASSERT_EQ(0, old_snapshot_add(&ioctx, oid, 3, "test3"));
+ ASSERT_EQ(-ESTALE, old_snapshot_add(&ioctx, oid, 2, "test2"));
+
+ ioctx.close();
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
+}