const char *snapname,
librbd_progress_fn_t cb,
void *cbdata);
+CEPH_RBD_API int rbd_snap_rename(rbd_image_t image, const char *snapname,
+ const char* dstsnapsname);
/**
* Prevent a snapshot from being deleted until it is unprotected.
*
int snap_unprotect(const char *snap_name);
int snap_is_protected(const char *snap_name, bool *is_protected);
int snap_set(const char *snap_name);
+ int snap_rename(const char *srcname, const char *dstname);
/* I/O */
ssize_t read(uint64_t ofs, size_t len, ceph::bufferlist& bl);
plb.add_u64_counter(l_librbd_snap_create, "snap_create", "Snap creations");
plb.add_u64_counter(l_librbd_snap_remove, "snap_remove", "Snap removals");
plb.add_u64_counter(l_librbd_snap_rollback, "snap_rollback", "Snap rollbacks");
+ plb.add_u64_counter(l_librbd_snap_rename, "snap_rename", "Snap rename");
plb.add_u64_counter(l_librbd_notify, "notify", "Updated header notifications");
plb.add_u64_counter(l_librbd_resize, "resize", "Resizes");
plb.add_u64_counter(l_librbd_readahead, "readahead", "Read ahead");
return notify_lock_owner(bl);
}
+int ImageWatcher::notify_snap_rename(const snapid_t &src_snap_id,
+ const std::string &dst_snap_name) {
+ assert(m_image_ctx.owner_lock.is_locked());
+ assert(!is_lock_owner());
+
+ bufferlist bl;
+ ::encode(NotifyMessage(SnapRenamePayload(src_snap_id, dst_snap_name)), bl);
+
+ return notify_lock_owner(bl);
+}
int ImageWatcher::notify_snap_remove(const std::string &snap_name) {
assert(m_image_ctx.owner_lock.is_locked());
assert(!is_lock_owner());
int notify_resize(uint64_t request_id, uint64_t size,
ProgressContext &prog_ctx);
int notify_snap_create(const std::string &snap_name);
+ int notify_snap_rename(const snapid_t &src_snap_id, const std::string &dst_snap_name);
int notify_snap_remove(const std::string &snap_name);
int notify_rebuild_object_map(uint64_t request_id,
ProgressContext &prog_ctx);
return 0;
}
+ int snap_rename(ImageCtx *ictx, const char *srcname, const char *dstname)
+ {
+ ldout(ictx->cct, 20) << "snap_rename " << ictx << " from " << srcname << " to " << dstname << dendl;
+
+ snapid_t snap_id;
+ if (ictx->read_only) {
+ return -EROFS;
+ }
+
+ int r = ictx_check(ictx);
+ if (r < 0)
+ return r;
+
+ {
+ RWLock::RLocker l(ictx->snap_lock);
+ snap_id = ictx->get_snap_id(srcname);
+ if (snap_id == CEPH_NOSNAP) {
+ return -ENOENT;
+ }
+ if (ictx->get_snap_id(dstname) != CEPH_NOSNAP) {
+ return -EEXIST;
+ }
+ }
+
+ r = invoke_async_request(ictx, "snap_rename", true,
+ boost::bind(&snap_rename_helper, ictx, _1,
+ snap_id, dstname),
+ boost::bind(&ImageWatcher::notify_snap_rename,
+ ictx->image_watcher, snap_id,
+ dstname));
+ if (r < 0 && r != -EEXIST) {
+ return r;
+ }
+
+ ictx->perfcounter->inc(l_librbd_snap_rename);
+ notify_change(ictx->md_ctx, ictx->header_oid, ictx);
+ return 0;
+ }
+
int snap_rename_helper(ImageCtx* ictx, Context* ctx,
const uint64_t src_snap_id,
const char* dst_name) {
l_librbd_snap_create,
l_librbd_snap_remove,
l_librbd_snap_rollback,
+ l_librbd_snap_rename,
l_librbd_notify,
l_librbd_resize,
int snap_remove_helper(ImageCtx *ictx, Context* ctx, const char *snap_name);
int snap_rename_helper(ImageCtx *ictx, Context* ctx, const uint64_t src_snap_id,
const char *dst_name);
+ int snap_rename(ImageCtx *ictx, const char *srcname, const char *dstname);
int snap_protect(ImageCtx *ictx, const char *snap_name);
int snap_unprotect(ImageCtx *ictx, const char *snap_name);
int snap_is_protected(ImageCtx *ictx, const char *snap_name,
return r;
}
+ int Image::snap_rename(const char *srcname, const char *dstname)
+ {
+ ImageCtx *ictx = (ImageCtx *)ctx;
+ tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
+ int r = librbd::snap_rename(ictx, srcname, dstname);
+ tracepoint(librbd, snap_rename_exit, r);
+ return r;
+ }
+
int Image::snap_rollback_with_progress(const char *snap_name,
ProgressContext& prog_ctx)
{
return r;
}
+extern "C" int rbd_snap_rename(rbd_image_t image, const char *srcname, const char *dstname)
+{
+ librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+ tracepoint(librbd, snap_rename_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, srcname, dstname);
+ int r = librbd::snap_rename(ictx, srcname, dstname);
+ tracepoint(librbd, snap_rename_exit, r);
+ return r;
+}
+
extern "C" int rbd_snap_remove(rbd_image_t image, const char *snap_name)
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
" snap purge <image-spec> deletes all snapshots\n"
" snap protect <snap-spec> prevent a snapshot from being deleted\n"
" snap unprotect <snap-spec> allow a snapshot to be deleted\n"
+" snap rename <src-snap-spec> <dst-snap-spec> rename a snapshot\n"
" watch <image-spec> watch events on image\n"
" status <image-spec> show the status of this image\n"
" map <image-spec> | <snap-spec> map image to a block device\n"
return 0;
}
+static int do_rename_snap(librbd::Image& image, const char *srcname, const char *dstname)
+{
+ int r = image.snap_rename(srcname, dstname);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
static int do_purge_snaps(librbd::Image& image)
{
MyProgressContext pc("Removing all snapshots");
OPT_SNAP_PURGE,
OPT_SNAP_PROTECT,
OPT_SNAP_UNPROTECT,
+ OPT_SNAP_RENAME,
OPT_WATCH,
OPT_STATUS,
OPT_MAP,
return OPT_SNAP_PROTECT;
if (strcmp(cmd, "unprotect") == 0)
return OPT_SNAP_UNPROTECT;
+ if (strcmp(cmd, "rename") == 0)
+ return OPT_SNAP_RENAME;
break;
case COMMAND_TYPE_METADATA:
if (strcmp(cmd, "list") == 0)
case OPT_COPY:
case OPT_RENAME:
case OPT_CLONE:
+ case OPT_SNAP_RENAME:
SET_CONF_PARAM(v, &imgname, &destname, NULL);
break;
case OPT_SHOWMAPPED:
opt_cmd != OPT_MAP && opt_cmd != OPT_UNMAP && opt_cmd != OPT_CLONE &&
opt_cmd != OPT_SNAP_PROTECT && opt_cmd != OPT_SNAP_UNPROTECT &&
opt_cmd != OPT_CHILDREN && opt_cmd != OPT_OBJECT_MAP_REBUILD &&
- opt_cmd != OPT_DISK_USAGE) {
+ opt_cmd != OPT_DISK_USAGE && opt_cmd != OPT_SNAP_RENAME) {
cerr << "rbd: snapname specified for a command that doesn't use it"
<< std::endl;
return EXIT_FAILURE;
if ((opt_cmd == OPT_SNAP_CREATE || opt_cmd == OPT_SNAP_ROLLBACK ||
opt_cmd == OPT_SNAP_REMOVE || opt_cmd == OPT_CLONE ||
opt_cmd == OPT_SNAP_PROTECT || opt_cmd == OPT_SNAP_UNPROTECT ||
- opt_cmd == OPT_CHILDREN) && !snapname) {
+ opt_cmd == OPT_CHILDREN || opt_cmd == OPT_SNAP_RENAME) && !snapname) {
cerr << "rbd: snap name was not specified" << std::endl;
return EXIT_FAILURE;
}
set_pool_image_name(destname, (char **)&dest_poolname,
(char **)&destname, (char **)&dest_snapname);
- if (dest_snapname) {
+ if (dest_snapname && opt_cmd != OPT_SNAP_RENAME) {
// no command uses dest_snapname
cerr << "rbd: destination snapname specified for a command that doesn't use it"
<< std::endl;
return EXIT_FAILURE;
}
+ if (opt_cmd == OPT_SNAP_RENAME && !dest_snapname) {
+ cerr << "rbd: destination snap name was not specified" << std::endl;
+ return EXIT_FAILURE;
+ }
if (opt_cmd == OPT_IMPORT) {
if (poolname && dest_poolname) {
opt_cmd == OPT_METADATA_SET || opt_cmd == OPT_METADATA_LIST ||
opt_cmd == OPT_METADATA_REMOVE || opt_cmd == OPT_METADATA_GET ||
opt_cmd == OPT_FEATURE_DISABLE || opt_cmd == OPT_FEATURE_ENABLE ||
- opt_cmd == OPT_OBJECT_MAP_REBUILD || opt_cmd == OPT_DISK_USAGE)) {
+ opt_cmd == OPT_OBJECT_MAP_REBUILD || opt_cmd == OPT_DISK_USAGE ||
+ opt_cmd == OPT_SNAP_RENAME)) {
if (opt_cmd == OPT_INFO || opt_cmd == OPT_SNAP_LIST ||
opt_cmd == OPT_EXPORT || opt_cmd == OPT_EXPORT || opt_cmd == OPT_COPY ||
}
break;
+ case OPT_SNAP_RENAME:
+ r = do_rename_snap(image, snapname, dest_snapname);
+ if (r < 0) {
+ cerr << "rbd: failed to rename snapshot: " << cpp_strerror(-r)
+ << std::endl;
+ return -r;
+ }
+ break;
+
case OPT_SNAP_ROLLBACK:
r = do_rollback_snap(image, snapname);
if (r < 0) {
)
)
+TRACEPOINT_EVENT(librbd, snap_rename_enter,
+ TP_ARGS(
+ void*, imagectx,
+ const char*, name,
+ const char*, snap_name,
+ char, read_only,
+ const char*, src_snap_name,
+ const char*, dst_snap_name),
+ TP_FIELDS(
+ ctf_integer_hex(void*, imagectx, imagectx)
+ ctf_string(name, name)
+ ctf_string(snap_name, snap_name)
+ ctf_integer(char, read_only, read_only)
+ ctf_string(src_snap_name, src_snap_name)
+ ctf_string(dst_snap_name, dst_snap_name)
+ )
+)
+
+TRACEPOINT_EVENT(librbd, snap_rename_exit,
+ TP_ARGS(
+ int, retval),
+ TP_FIELDS(
+ ctf_integer(int, retval, retval)
+ )
+)
+
TRACEPOINT_EVENT(librbd, snap_list_enter,
TP_ARGS(
void*, imagectx,