mirror of
https://github.com/ceph/ceph
synced 2025-04-07 01:54:01 +00:00
rbd: add rbd_resize2 for allow_shrink option
This commit is contained in:
parent
e489cd4f07
commit
d1f2c557b2
src
include/rbd
librbd
ImageWatcher.ccImageWatcher.hOperations.ccOperations.hWatchNotifyTypes.ccWatchNotifyTypes.h
journal
librbd.ccoperation
test
tools/rbd/action
@ -272,6 +272,8 @@ CEPH_RBD_API int rbd_aio_open_read_only(rados_ioctx_t io, const char *name,
|
|||||||
CEPH_RBD_API int rbd_close(rbd_image_t image);
|
CEPH_RBD_API int rbd_close(rbd_image_t image);
|
||||||
CEPH_RBD_API int rbd_aio_close(rbd_image_t image, rbd_completion_t c);
|
CEPH_RBD_API int rbd_aio_close(rbd_image_t image, rbd_completion_t c);
|
||||||
CEPH_RBD_API int rbd_resize(rbd_image_t image, uint64_t size);
|
CEPH_RBD_API int rbd_resize(rbd_image_t image, uint64_t size);
|
||||||
|
CEPH_RBD_API int rbd_resize2(rbd_image_t image, uint64_t size, bool allow_shrink,
|
||||||
|
librbd_progress_fn_t cb, void *cbdata);
|
||||||
CEPH_RBD_API int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
|
CEPH_RBD_API int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
|
||||||
librbd_progress_fn_t cb, void *cbdata);
|
librbd_progress_fn_t cb, void *cbdata);
|
||||||
CEPH_RBD_API int rbd_stat(rbd_image_t image, rbd_image_info_t *info,
|
CEPH_RBD_API int rbd_stat(rbd_image_t image, rbd_image_info_t *info,
|
||||||
|
@ -191,6 +191,7 @@ public:
|
|||||||
int aio_close(RBD::AioCompletion *c);
|
int aio_close(RBD::AioCompletion *c);
|
||||||
|
|
||||||
int resize(uint64_t size);
|
int resize(uint64_t size);
|
||||||
|
int resize2(uint64_t size, bool allow_shrink, ProgressContext& pctx);
|
||||||
int resize_with_progress(uint64_t size, ProgressContext& pctx);
|
int resize_with_progress(uint64_t size, ProgressContext& pctx);
|
||||||
int stat(image_info_t &info, size_t infosize);
|
int stat(image_info_t &info, size_t infosize);
|
||||||
int parent_info(std::string *parent_poolname, std::string *parent_name,
|
int parent_info(std::string *parent_poolname, std::string *parent_name,
|
||||||
|
@ -213,7 +213,7 @@ void ImageWatcher::notify_flatten(uint64_t request_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImageWatcher::notify_resize(uint64_t request_id, uint64_t size,
|
void ImageWatcher::notify_resize(uint64_t request_id, uint64_t size,
|
||||||
ProgressContext &prog_ctx,
|
bool allow_shrink, ProgressContext &prog_ctx,
|
||||||
Context *on_finish) {
|
Context *on_finish) {
|
||||||
assert(m_image_ctx.owner_lock.is_locked());
|
assert(m_image_ctx.owner_lock.is_locked());
|
||||||
assert(m_image_ctx.exclusive_lock &&
|
assert(m_image_ctx.exclusive_lock &&
|
||||||
@ -222,7 +222,7 @@ void ImageWatcher::notify_resize(uint64_t request_id, uint64_t size,
|
|||||||
AsyncRequestId async_request_id(get_client_id(), request_id);
|
AsyncRequestId async_request_id(get_client_id(), request_id);
|
||||||
|
|
||||||
bufferlist bl;
|
bufferlist bl;
|
||||||
::encode(NotifyMessage(ResizePayload(size, async_request_id)), bl);
|
::encode(NotifyMessage(ResizePayload(size, allow_shrink, async_request_id)), bl);
|
||||||
notify_async_request(async_request_id, std::move(bl), prog_ctx, on_finish);
|
notify_async_request(async_request_id, std::move(bl), prog_ctx, on_finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -711,8 +711,9 @@ bool ImageWatcher::handle_payload(const ResizePayload &payload,
|
|||||||
if (new_request) {
|
if (new_request) {
|
||||||
ldout(m_image_ctx.cct, 10) << this << " remote resize request: "
|
ldout(m_image_ctx.cct, 10) << this << " remote resize request: "
|
||||||
<< payload.async_request_id << " "
|
<< payload.async_request_id << " "
|
||||||
<< payload.size << dendl;
|
<< payload.size << " "
|
||||||
m_image_ctx.operations->execute_resize(payload.size, *prog_ctx, ctx, 0);
|
<< payload.allow_shrink << dendl;
|
||||||
|
m_image_ctx.operations->execute_resize(payload.size, payload.allow_shrink, *prog_ctx, ctx, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
::encode(ResponseMessage(r), ack_ctx->out);
|
::encode(ResponseMessage(r), ack_ctx->out);
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
|
|
||||||
void notify_flatten(uint64_t request_id, ProgressContext &prog_ctx,
|
void notify_flatten(uint64_t request_id, ProgressContext &prog_ctx,
|
||||||
Context *on_finish);
|
Context *on_finish);
|
||||||
void notify_resize(uint64_t request_id, uint64_t size,
|
void notify_resize(uint64_t request_id, uint64_t size, bool allow_shrink,
|
||||||
ProgressContext &prog_ctx, Context *on_finish);
|
ProgressContext &prog_ctx, Context *on_finish);
|
||||||
void notify_snap_create(const std::string &snap_name, Context *on_finish);
|
void notify_snap_create(const std::string &snap_name, Context *on_finish);
|
||||||
void notify_snap_rename(const snapid_t &src_snap_id,
|
void notify_snap_rename(const snapid_t &src_snap_id,
|
||||||
|
@ -558,7 +558,7 @@ void Operations<I>::execute_rename(const char *dstname, Context *on_finish) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
int Operations<I>::resize(uint64_t size, ProgressContext& prog_ctx) {
|
int Operations<I>::resize(uint64_t size, bool allow_shrink, ProgressContext& prog_ctx) {
|
||||||
CephContext *cct = m_image_ctx.cct;
|
CephContext *cct = m_image_ctx.cct;
|
||||||
|
|
||||||
m_image_ctx.snap_lock.get_read();
|
m_image_ctx.snap_lock.get_read();
|
||||||
@ -581,10 +581,10 @@ int Operations<I>::resize(uint64_t size, ProgressContext& prog_ctx) {
|
|||||||
uint64_t request_id = ++m_async_request_seq;
|
uint64_t request_id = ++m_async_request_seq;
|
||||||
r = invoke_async_request("resize", false,
|
r = invoke_async_request("resize", false,
|
||||||
boost::bind(&Operations<I>::execute_resize, this,
|
boost::bind(&Operations<I>::execute_resize, this,
|
||||||
size, boost::ref(prog_ctx), _1, 0),
|
size, allow_shrink, boost::ref(prog_ctx), _1, 0),
|
||||||
boost::bind(&ImageWatcher::notify_resize,
|
boost::bind(&ImageWatcher::notify_resize,
|
||||||
m_image_ctx.image_watcher, request_id,
|
m_image_ctx.image_watcher, request_id,
|
||||||
size, boost::ref(prog_ctx), _1));
|
size, allow_shrink, boost::ref(prog_ctx), _1));
|
||||||
|
|
||||||
m_image_ctx.perfcounter->inc(l_librbd_resize);
|
m_image_ctx.perfcounter->inc(l_librbd_resize);
|
||||||
ldout(cct, 2) << "resize finished" << dendl;
|
ldout(cct, 2) << "resize finished" << dendl;
|
||||||
@ -592,7 +592,7 @@ int Operations<I>::resize(uint64_t size, ProgressContext& prog_ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
void Operations<I>::execute_resize(uint64_t size, ProgressContext &prog_ctx,
|
void Operations<I>::execute_resize(uint64_t size, bool allow_shrink, ProgressContext &prog_ctx,
|
||||||
Context *on_finish,
|
Context *on_finish,
|
||||||
uint64_t journal_op_tid) {
|
uint64_t journal_op_tid) {
|
||||||
assert(m_image_ctx.owner_lock.is_locked());
|
assert(m_image_ctx.owner_lock.is_locked());
|
||||||
@ -619,8 +619,8 @@ void Operations<I>::execute_resize(uint64_t size, ProgressContext &prog_ctx,
|
|||||||
m_image_ctx.snap_lock.put_read();
|
m_image_ctx.snap_lock.put_read();
|
||||||
|
|
||||||
operation::ResizeRequest<I> *req = new operation::ResizeRequest<I>(
|
operation::ResizeRequest<I> *req = new operation::ResizeRequest<I>(
|
||||||
m_image_ctx, new C_NotifyUpdate<I>(m_image_ctx, on_finish), size, prog_ctx,
|
m_image_ctx, new C_NotifyUpdate<I>(m_image_ctx, on_finish), size, allow_shrink,
|
||||||
journal_op_tid, false);
|
prog_ctx, journal_op_tid, false);
|
||||||
req->send();
|
req->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ public:
|
|||||||
int rename(const char *dstname);
|
int rename(const char *dstname);
|
||||||
void execute_rename(const char *dstname, Context *on_finish);
|
void execute_rename(const char *dstname, Context *on_finish);
|
||||||
|
|
||||||
int resize(uint64_t size, ProgressContext& prog_ctx);
|
int resize(uint64_t size, bool allow_shrink, ProgressContext& prog_ctx);
|
||||||
void execute_resize(uint64_t size, ProgressContext &prog_ctx,
|
void execute_resize(uint64_t size, bool allow_shrink, ProgressContext &prog_ctx,
|
||||||
Context *on_finish, uint64_t journal_op_tid);
|
Context *on_finish, uint64_t journal_op_tid);
|
||||||
|
|
||||||
int snap_create(const char *snap_name);
|
int snap_create(const char *snap_name);
|
||||||
|
@ -207,17 +207,23 @@ void AsyncCompletePayload::dump(Formatter *f) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ResizePayload::encode(bufferlist &bl) const {
|
void ResizePayload::encode(bufferlist &bl) const {
|
||||||
::encode(size, bl);
|
|
||||||
AsyncRequestPayloadBase::encode(bl);
|
AsyncRequestPayloadBase::encode(bl);
|
||||||
|
::encode(size, bl);
|
||||||
|
::encode(allow_shrink, bl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResizePayload::decode(__u8 version, bufferlist::iterator &iter) {
|
void ResizePayload::decode(__u8 version, bufferlist::iterator &iter) {
|
||||||
::decode(size, iter);
|
|
||||||
AsyncRequestPayloadBase::decode(version, iter);
|
AsyncRequestPayloadBase::decode(version, iter);
|
||||||
|
::decode(size, iter);
|
||||||
|
|
||||||
|
if (version >= 4) {
|
||||||
|
::decode(allow_shrink, iter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResizePayload::dump(Formatter *f) const {
|
void ResizePayload::dump(Formatter *f) const {
|
||||||
f->dump_unsigned("size", size);
|
f->dump_unsigned("size", size);
|
||||||
|
f->dump_bool("allow_shrink", allow_shrink);
|
||||||
AsyncRequestPayloadBase::dump(f);
|
AsyncRequestPayloadBase::dump(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +281,7 @@ bool NotifyMessage::check_for_refresh() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NotifyMessage::encode(bufferlist& bl) const {
|
void NotifyMessage::encode(bufferlist& bl) const {
|
||||||
ENCODE_START(3, 1, bl);
|
ENCODE_START(4, 1, bl);
|
||||||
boost::apply_visitor(EncodePayloadVisitor(bl), payload);
|
boost::apply_visitor(EncodePayloadVisitor(bl), payload);
|
||||||
ENCODE_FINISH(bl);
|
ENCODE_FINISH(bl);
|
||||||
}
|
}
|
||||||
@ -354,7 +360,7 @@ void NotifyMessage::generate_test_instances(std::list<NotifyMessage *> &o) {
|
|||||||
o.push_back(new NotifyMessage(AsyncProgressPayload(AsyncRequestId(ClientId(0, 1), 2), 3, 4)));
|
o.push_back(new NotifyMessage(AsyncProgressPayload(AsyncRequestId(ClientId(0, 1), 2), 3, 4)));
|
||||||
o.push_back(new NotifyMessage(AsyncCompletePayload(AsyncRequestId(ClientId(0, 1), 2), 3)));
|
o.push_back(new NotifyMessage(AsyncCompletePayload(AsyncRequestId(ClientId(0, 1), 2), 3)));
|
||||||
o.push_back(new NotifyMessage(FlattenPayload(AsyncRequestId(ClientId(0, 1), 2))));
|
o.push_back(new NotifyMessage(FlattenPayload(AsyncRequestId(ClientId(0, 1), 2))));
|
||||||
o.push_back(new NotifyMessage(ResizePayload(123, AsyncRequestId(ClientId(0, 1), 2))));
|
o.push_back(new NotifyMessage(ResizePayload(123, true, AsyncRequestId(ClientId(0, 1), 2))));
|
||||||
o.push_back(new NotifyMessage(SnapCreatePayload("foo")));
|
o.push_back(new NotifyMessage(SnapCreatePayload("foo")));
|
||||||
o.push_back(new NotifyMessage(SnapRemovePayload("foo")));
|
o.push_back(new NotifyMessage(SnapRemovePayload("foo")));
|
||||||
o.push_back(new NotifyMessage(SnapProtectPayload("foo")));
|
o.push_back(new NotifyMessage(SnapProtectPayload("foo")));
|
||||||
|
@ -200,11 +200,12 @@ struct ResizePayload : public AsyncRequestPayloadBase {
|
|||||||
static const NotifyOp NOTIFY_OP = NOTIFY_OP_RESIZE;
|
static const NotifyOp NOTIFY_OP = NOTIFY_OP_RESIZE;
|
||||||
static const bool CHECK_FOR_REFRESH = true;
|
static const bool CHECK_FOR_REFRESH = true;
|
||||||
|
|
||||||
ResizePayload() : size(0) {}
|
ResizePayload() : size(0), allow_shrink(true) {}
|
||||||
ResizePayload(uint64_t size_, const AsyncRequestId &id)
|
ResizePayload(uint64_t size_, bool allow_shrink_, const AsyncRequestId &id)
|
||||||
: AsyncRequestPayloadBase(id), size(size_) {}
|
: AsyncRequestPayloadBase(id), size(size_), allow_shrink(allow_shrink_) {}
|
||||||
|
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
|
bool allow_shrink;
|
||||||
|
|
||||||
void encode(bufferlist &bl) const;
|
void encode(bufferlist &bl) const;
|
||||||
void decode(__u8 version, bufferlist::iterator &iter);
|
void decode(__u8 version, bufferlist::iterator &iter);
|
||||||
|
@ -76,7 +76,7 @@ struct ExecuteOp : public Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void execute(const journal::ResizeEvent &_) {
|
void execute(const journal::ResizeEvent &_) {
|
||||||
image_ctx.operations->execute_resize(event.size, no_op_progress_callback,
|
image_ctx.operations->execute_resize(event.size, true, no_op_progress_callback,
|
||||||
on_op_complete, event.op_tid);
|
on_op_complete, event.op_tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,7 +615,16 @@ namespace librbd {
|
|||||||
ImageCtx *ictx = (ImageCtx *)ctx;
|
ImageCtx *ictx = (ImageCtx *)ctx;
|
||||||
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
||||||
librbd::NoOpProgressContext prog_ctx;
|
librbd::NoOpProgressContext prog_ctx;
|
||||||
int r = ictx->operations->resize(size, prog_ctx);
|
int r = ictx->operations->resize(size, true, prog_ctx);
|
||||||
|
tracepoint(librbd, resize_exit, r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Image::resize2(uint64_t size, bool allow_shrink, librbd::ProgressContext& pctx)
|
||||||
|
{
|
||||||
|
ImageCtx *ictx = (ImageCtx *)ctx;
|
||||||
|
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
||||||
|
int r = ictx->operations->resize(size, allow_shrink, pctx);
|
||||||
tracepoint(librbd, resize_exit, r);
|
tracepoint(librbd, resize_exit, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -624,7 +633,7 @@ namespace librbd {
|
|||||||
{
|
{
|
||||||
ImageCtx *ictx = (ImageCtx *)ctx;
|
ImageCtx *ictx = (ImageCtx *)ctx;
|
||||||
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
||||||
int r = ictx->operations->resize(size, pctx);
|
int r = ictx->operations->resize(size, true, pctx);
|
||||||
tracepoint(librbd, resize_exit, r);
|
tracepoint(librbd, resize_exit, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1969,7 +1978,18 @@ extern "C" int rbd_resize(rbd_image_t image, uint64_t size)
|
|||||||
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
|
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
|
||||||
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
||||||
librbd::NoOpProgressContext prog_ctx;
|
librbd::NoOpProgressContext prog_ctx;
|
||||||
int r = ictx->operations->resize(size, prog_ctx);
|
int r = ictx->operations->resize(size, true, prog_ctx);
|
||||||
|
tracepoint(librbd, resize_exit, r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int rbd_resize2(rbd_image_t image, uint64_t size, bool allow_shrink,
|
||||||
|
librbd_progress_fn_t cb, void *cbdata)
|
||||||
|
{
|
||||||
|
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
|
||||||
|
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
||||||
|
librbd::CProgressContext prog_ctx(cb, cbdata);
|
||||||
|
int r = ictx->operations->resize(size, allow_shrink, prog_ctx);
|
||||||
tracepoint(librbd, resize_exit, r);
|
tracepoint(librbd, resize_exit, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1980,7 +2000,7 @@ extern "C" int rbd_resize_with_progress(rbd_image_t image, uint64_t size,
|
|||||||
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
|
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
|
||||||
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
tracepoint(librbd, resize_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, size);
|
||||||
librbd::CProgressContext prog_ctx(cb, cbdata);
|
librbd::CProgressContext prog_ctx(cb, cbdata);
|
||||||
int r = ictx->operations->resize(size, prog_ctx);
|
int r = ictx->operations->resize(size, true, prog_ctx);
|
||||||
tracepoint(librbd, resize_exit, r);
|
tracepoint(librbd, resize_exit, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,11 @@ using util::create_rados_safe_callback;
|
|||||||
|
|
||||||
template <typename I>
|
template <typename I>
|
||||||
ResizeRequest<I>::ResizeRequest(I &image_ctx, Context *on_finish,
|
ResizeRequest<I>::ResizeRequest(I &image_ctx, Context *on_finish,
|
||||||
uint64_t new_size, ProgressContext &prog_ctx,
|
uint64_t new_size, bool allow_shrink, ProgressContext &prog_ctx,
|
||||||
uint64_t journal_op_tid, bool disable_journal)
|
uint64_t journal_op_tid, bool disable_journal)
|
||||||
: Request<I>(image_ctx, on_finish, journal_op_tid),
|
: Request<I>(image_ctx, on_finish, journal_op_tid),
|
||||||
m_original_size(0), m_new_size(new_size), m_prog_ctx(prog_ctx),
|
m_original_size(0), m_new_size(new_size), m_allow_shrink(allow_shrink),
|
||||||
m_new_parent_overlap(0), m_disable_journal(disable_journal),
|
m_prog_ctx(prog_ctx), m_new_parent_overlap(0), m_disable_journal(disable_journal),
|
||||||
m_xlist_item(this)
|
m_xlist_item(this)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -114,12 +114,19 @@ Context *ResizeRequest<I>::handle_pre_block_writes(int *result) {
|
|||||||
template <typename I>
|
template <typename I>
|
||||||
Context *ResizeRequest<I>::send_append_op_event() {
|
Context *ResizeRequest<I>::send_append_op_event() {
|
||||||
I &image_ctx = this->m_image_ctx;
|
I &image_ctx = this->m_image_ctx;
|
||||||
|
CephContext *cct = image_ctx.cct;
|
||||||
|
|
||||||
|
if (m_new_size < m_original_size && !m_allow_shrink) {
|
||||||
|
ldout(cct, 1) << " shrinking the image is not permitted" << dendl;
|
||||||
|
this->async_complete(-EINVAL);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_disable_journal || !this->template append_op_event<
|
if (m_disable_journal || !this->template append_op_event<
|
||||||
ResizeRequest<I>, &ResizeRequest<I>::handle_append_op_event>(this)) {
|
ResizeRequest<I>, &ResizeRequest<I>::handle_append_op_event>(this)) {
|
||||||
return send_grow_object_map();
|
return send_grow_object_map();
|
||||||
}
|
}
|
||||||
|
|
||||||
CephContext *cct = image_ctx.cct;
|
|
||||||
ldout(cct, 5) << this << " " << __func__ << dendl;
|
ldout(cct, 5) << this << " " << __func__ << dendl;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,15 @@ template <typename ImageCtxT = ImageCtx>
|
|||||||
class ResizeRequest : public Request<ImageCtxT> {
|
class ResizeRequest : public Request<ImageCtxT> {
|
||||||
public:
|
public:
|
||||||
static ResizeRequest *create(ImageCtxT &image_ctx, Context *on_finish,
|
static ResizeRequest *create(ImageCtxT &image_ctx, Context *on_finish,
|
||||||
uint64_t new_size, ProgressContext &prog_ctx,
|
uint64_t new_size, bool allow_shrink,
|
||||||
uint64_t journal_op_tid, bool disable_journal) {
|
ProgressContext &prog_ctx, uint64_t journal_op_tid,
|
||||||
return new ResizeRequest(image_ctx, on_finish, new_size, prog_ctx,
|
bool disable_journal) {
|
||||||
|
return new ResizeRequest(image_ctx, on_finish, new_size, allow_shrink, prog_ctx,
|
||||||
journal_op_tid, disable_journal);
|
journal_op_tid, disable_journal);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResizeRequest(ImageCtxT &image_ctx, Context *on_finish, uint64_t new_size,
|
ResizeRequest(ImageCtxT &image_ctx, Context *on_finish, uint64_t new_size,
|
||||||
ProgressContext &prog_ctx, uint64_t journal_op_tid,
|
bool allow_shrink, ProgressContext &prog_ctx, uint64_t journal_op_tid,
|
||||||
bool disable_journal);
|
bool disable_journal);
|
||||||
virtual ~ResizeRequest();
|
virtual ~ResizeRequest();
|
||||||
|
|
||||||
@ -106,6 +107,7 @@ private:
|
|||||||
|
|
||||||
uint64_t m_original_size;
|
uint64_t m_original_size;
|
||||||
uint64_t m_new_size;
|
uint64_t m_new_size;
|
||||||
|
bool m_allow_shrink = true;
|
||||||
ProgressContext &m_prog_ctx;
|
ProgressContext &m_prog_ctx;
|
||||||
uint64_t m_new_parent_overlap;
|
uint64_t m_new_parent_overlap;
|
||||||
bool m_shrink_size_visible = false;
|
bool m_shrink_size_visible = false;
|
||||||
|
@ -137,7 +137,7 @@ void SnapshotRollbackRequest<I>::send_resize_image() {
|
|||||||
SnapshotRollbackRequest<I>,
|
SnapshotRollbackRequest<I>,
|
||||||
&SnapshotRollbackRequest<I>::handle_resize_image>(this);
|
&SnapshotRollbackRequest<I>::handle_resize_image>(this);
|
||||||
ResizeRequest<I> *req = ResizeRequest<I>::create(image_ctx, ctx, m_snap_size,
|
ResizeRequest<I> *req = ResizeRequest<I>::create(image_ctx, ctx, m_snap_size,
|
||||||
m_no_op_prog_ctx, 0, true);
|
true, m_no_op_prog_ctx, 0, true);
|
||||||
req->send();
|
req->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +617,7 @@ TEST_F(TestJournalReplay, Resize) {
|
|||||||
|
|
||||||
// verify lock ordering constraints
|
// verify lock ordering constraints
|
||||||
librbd::NoOpProgressContext no_op_progress;
|
librbd::NoOpProgressContext no_op_progress;
|
||||||
ASSERT_EQ(0, ictx->operations->resize(0, no_op_progress));
|
ASSERT_EQ(0, ictx->operations->resize(0, true, no_op_progress));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestJournalReplay, Flatten) {
|
TEST_F(TestJournalReplay, Flatten) {
|
||||||
|
@ -138,8 +138,8 @@ public:
|
|||||||
|
|
||||||
void expect_resize(MockReplayImageCtx &mock_image_ctx, Context **on_finish,
|
void expect_resize(MockReplayImageCtx &mock_image_ctx, Context **on_finish,
|
||||||
uint64_t size, uint64_t op_tid) {
|
uint64_t size, uint64_t op_tid) {
|
||||||
EXPECT_CALL(*mock_image_ctx.operations, execute_resize(size, _, _, op_tid))
|
EXPECT_CALL(*mock_image_ctx.operations, execute_resize(size, _, _, _, op_tid))
|
||||||
.WillOnce(DoAll(SaveArg<2>(on_finish),
|
.WillOnce(DoAll(SaveArg<3>(on_finish),
|
||||||
NotifyInvoke(&m_invoke_lock, &m_invoke_cond)));
|
NotifyInvoke(&m_invoke_lock, &m_invoke_cond)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ struct MockOperations {
|
|||||||
MOCK_METHOD2(execute_rebuild_object_map, void(ProgressContext &prog_ctx,
|
MOCK_METHOD2(execute_rebuild_object_map, void(ProgressContext &prog_ctx,
|
||||||
Context *on_finish));
|
Context *on_finish));
|
||||||
MOCK_METHOD2(execute_rename, void(const char *dstname, Context *on_finish));
|
MOCK_METHOD2(execute_rename, void(const char *dstname, Context *on_finish));
|
||||||
MOCK_METHOD4(execute_resize, void(uint64_t size, ProgressContext &prog_ctx,
|
MOCK_METHOD5(execute_resize, void(uint64_t size, bool allow_shrink,
|
||||||
Context *on_finish,
|
ProgressContext &prog_ctx, Context *on_finish,
|
||||||
uint64_t journal_op_tid));
|
uint64_t journal_op_tid));
|
||||||
MOCK_METHOD2(snap_create, void(const char *snap_name, Context *on_finish));
|
MOCK_METHOD2(snap_create, void(const char *snap_name, Context *on_finish));
|
||||||
MOCK_METHOD4(execute_snap_create, void(const char *snap_name,
|
MOCK_METHOD4(execute_snap_create, void(const char *snap_name,
|
||||||
|
@ -129,12 +129,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int when_resize(MockImageCtx &mock_image_ctx, uint64_t new_size,
|
int when_resize(MockImageCtx &mock_image_ctx, uint64_t new_size,
|
||||||
uint64_t journal_op_tid, bool disable_journal) {
|
bool allow_shrink, uint64_t journal_op_tid,
|
||||||
|
bool disable_journal) {
|
||||||
C_SaferCond cond_ctx;
|
C_SaferCond cond_ctx;
|
||||||
librbd::NoOpProgressContext prog_ctx;
|
librbd::NoOpProgressContext prog_ctx;
|
||||||
MockResizeRequest *req = new MockResizeRequest(
|
MockResizeRequest *req = new MockResizeRequest(
|
||||||
mock_image_ctx, &cond_ctx, new_size, prog_ctx, journal_op_tid,
|
mock_image_ctx, &cond_ctx, new_size, allow_shrink, prog_ctx,
|
||||||
disable_journal);
|
journal_op_tid, disable_journal);
|
||||||
{
|
{
|
||||||
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
|
RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
|
||||||
req->send();
|
req->send();
|
||||||
@ -159,7 +160,7 @@ TEST_F(TestMockOperationResizeRequest, NoOpSuccess) {
|
|||||||
expect_append_op_event(mock_image_ctx, 0);
|
expect_append_op_event(mock_image_ctx, 0);
|
||||||
expect_unblock_writes(mock_image_ctx);
|
expect_unblock_writes(mock_image_ctx);
|
||||||
expect_commit_op_event(mock_image_ctx, 0);
|
expect_commit_op_event(mock_image_ctx, 0);
|
||||||
ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size, 0, false));
|
ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size, true, 0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockOperationResizeRequest, GrowSuccess) {
|
TEST_F(TestMockOperationResizeRequest, GrowSuccess) {
|
||||||
@ -182,7 +183,7 @@ TEST_F(TestMockOperationResizeRequest, GrowSuccess) {
|
|||||||
expect_update_header(mock_image_ctx, 0);
|
expect_update_header(mock_image_ctx, 0);
|
||||||
expect_commit_op_event(mock_image_ctx, 0);
|
expect_commit_op_event(mock_image_ctx, 0);
|
||||||
expect_unblock_writes(mock_image_ctx);
|
expect_unblock_writes(mock_image_ctx);
|
||||||
ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size * 2, 0, false));
|
ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size * 2, true, 0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockOperationResizeRequest, ShrinkSuccess) {
|
TEST_F(TestMockOperationResizeRequest, ShrinkSuccess) {
|
||||||
@ -209,7 +210,25 @@ TEST_F(TestMockOperationResizeRequest, ShrinkSuccess) {
|
|||||||
expect_commit_op_event(mock_image_ctx, 0);
|
expect_commit_op_event(mock_image_ctx, 0);
|
||||||
expect_shrink_object_map(mock_image_ctx);
|
expect_shrink_object_map(mock_image_ctx);
|
||||||
expect_unblock_writes(mock_image_ctx);
|
expect_unblock_writes(mock_image_ctx);
|
||||||
ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size / 2, 0, false));
|
ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size / 2, true, 0, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TestMockOperationResizeRequest, ShrinkError) {
|
||||||
|
librbd::ImageCtx *ictx;
|
||||||
|
ASSERT_EQ(0, open_image(m_image_name, &ictx));
|
||||||
|
|
||||||
|
MockImageCtx mock_image_ctx(*ictx);
|
||||||
|
MockExclusiveLock mock_exclusive_lock;
|
||||||
|
MockJournal mock_journal;
|
||||||
|
MockObjectMap mock_object_map;
|
||||||
|
initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
|
||||||
|
mock_object_map);
|
||||||
|
|
||||||
|
InSequence seq;
|
||||||
|
expect_block_writes(mock_image_ctx, -EINVAL);
|
||||||
|
expect_unblock_writes(mock_image_ctx);
|
||||||
|
|
||||||
|
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, false, 0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockOperationResizeRequest, PreBlockWritesError) {
|
TEST_F(TestMockOperationResizeRequest, PreBlockWritesError) {
|
||||||
@ -226,7 +245,7 @@ TEST_F(TestMockOperationResizeRequest, PreBlockWritesError) {
|
|||||||
InSequence seq;
|
InSequence seq;
|
||||||
expect_block_writes(mock_image_ctx, -EINVAL);
|
expect_block_writes(mock_image_ctx, -EINVAL);
|
||||||
expect_unblock_writes(mock_image_ctx);
|
expect_unblock_writes(mock_image_ctx);
|
||||||
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size, 0, false));
|
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size, true, 0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockOperationResizeRequest, TrimError) {
|
TEST_F(TestMockOperationResizeRequest, TrimError) {
|
||||||
@ -248,7 +267,7 @@ TEST_F(TestMockOperationResizeRequest, TrimError) {
|
|||||||
MockTrimRequest mock_trim_request;
|
MockTrimRequest mock_trim_request;
|
||||||
expect_trim(mock_image_ctx, mock_trim_request, -EINVAL);
|
expect_trim(mock_image_ctx, mock_trim_request, -EINVAL);
|
||||||
expect_commit_op_event(mock_image_ctx, -EINVAL);
|
expect_commit_op_event(mock_image_ctx, -EINVAL);
|
||||||
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, 0, false));
|
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, true, 0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockOperationResizeRequest, InvalidateCacheError) {
|
TEST_F(TestMockOperationResizeRequest, InvalidateCacheError) {
|
||||||
@ -271,7 +290,7 @@ TEST_F(TestMockOperationResizeRequest, InvalidateCacheError) {
|
|||||||
expect_trim(mock_image_ctx, mock_trim_request, 0);
|
expect_trim(mock_image_ctx, mock_trim_request, 0);
|
||||||
expect_invalidate_cache(mock_image_ctx, -EINVAL);
|
expect_invalidate_cache(mock_image_ctx, -EINVAL);
|
||||||
expect_commit_op_event(mock_image_ctx, -EINVAL);
|
expect_commit_op_event(mock_image_ctx, -EINVAL);
|
||||||
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, 0, false));
|
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, true, 0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockOperationResizeRequest, PostBlockWritesError) {
|
TEST_F(TestMockOperationResizeRequest, PostBlockWritesError) {
|
||||||
@ -293,7 +312,7 @@ TEST_F(TestMockOperationResizeRequest, PostBlockWritesError) {
|
|||||||
expect_block_writes(mock_image_ctx, -EINVAL);
|
expect_block_writes(mock_image_ctx, -EINVAL);
|
||||||
expect_unblock_writes(mock_image_ctx);
|
expect_unblock_writes(mock_image_ctx);
|
||||||
expect_commit_op_event(mock_image_ctx, -EINVAL);
|
expect_commit_op_event(mock_image_ctx, -EINVAL);
|
||||||
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size * 2, 0, false));
|
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size * 2, true, 0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockOperationResizeRequest, UpdateHeaderError) {
|
TEST_F(TestMockOperationResizeRequest, UpdateHeaderError) {
|
||||||
@ -316,7 +335,7 @@ TEST_F(TestMockOperationResizeRequest, UpdateHeaderError) {
|
|||||||
expect_update_header(mock_image_ctx, -EINVAL);
|
expect_update_header(mock_image_ctx, -EINVAL);
|
||||||
expect_unblock_writes(mock_image_ctx);
|
expect_unblock_writes(mock_image_ctx);
|
||||||
expect_commit_op_event(mock_image_ctx, -EINVAL);
|
expect_commit_op_event(mock_image_ctx, -EINVAL);
|
||||||
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size * 2, 0, false));
|
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size * 2, true, 0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockOperationResizeRequest, JournalAppendError) {
|
TEST_F(TestMockOperationResizeRequest, JournalAppendError) {
|
||||||
@ -336,7 +355,7 @@ TEST_F(TestMockOperationResizeRequest, JournalAppendError) {
|
|||||||
expect_block_writes(mock_image_ctx, 0);
|
expect_block_writes(mock_image_ctx, 0);
|
||||||
expect_append_op_event(mock_image_ctx, -EINVAL);
|
expect_append_op_event(mock_image_ctx, -EINVAL);
|
||||||
expect_unblock_writes(mock_image_ctx);
|
expect_unblock_writes(mock_image_ctx);
|
||||||
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size, 0, false));
|
ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size, true, 0, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestMockOperationResizeRequest, JournalDisabled) {
|
TEST_F(TestMockOperationResizeRequest, JournalDisabled) {
|
||||||
@ -353,7 +372,7 @@ TEST_F(TestMockOperationResizeRequest, JournalDisabled) {
|
|||||||
InSequence seq;
|
InSequence seq;
|
||||||
expect_block_writes(mock_image_ctx, 0);
|
expect_block_writes(mock_image_ctx, 0);
|
||||||
expect_unblock_writes(mock_image_ctx);
|
expect_unblock_writes(mock_image_ctx);
|
||||||
ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size, 0, true));
|
ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size, true, 0, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace operation
|
} // namespace operation
|
||||||
|
@ -32,8 +32,9 @@ struct ResizeRequest<MockOperationImageCtx> {
|
|||||||
Context *on_finish = nullptr;
|
Context *on_finish = nullptr;
|
||||||
|
|
||||||
static ResizeRequest* create(MockOperationImageCtx &image_ctx, Context *on_finish,
|
static ResizeRequest* create(MockOperationImageCtx &image_ctx, Context *on_finish,
|
||||||
uint64_t new_size, ProgressContext &prog_ctx,
|
uint64_t new_size, bool allow_shrink,
|
||||||
uint64_t journal_op_tid, bool disable_journal) {
|
ProgressContext &prog_ctx, uint64_t journal_op_tid,
|
||||||
|
bool disable_journal) {
|
||||||
assert(s_instance != nullptr);
|
assert(s_instance != nullptr);
|
||||||
assert(journal_op_tid == 0);
|
assert(journal_op_tid == 0);
|
||||||
assert(disable_journal);
|
assert(disable_journal);
|
||||||
|
@ -274,7 +274,7 @@ struct ResizeTask {
|
|||||||
void operator()() {
|
void operator()() {
|
||||||
RWLock::RLocker l(ictx->owner_lock);
|
RWLock::RLocker l(ictx->owner_lock);
|
||||||
C_SaferCond ctx;
|
C_SaferCond ctx;
|
||||||
ictx->image_watcher->notify_resize(0, 0, *progress_context, &ctx);
|
ictx->image_watcher->notify_resize(0, 0, true, *progress_context, &ctx);
|
||||||
result = ctx.wait();
|
result = ctx.wait();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -113,7 +113,7 @@ TEST_F(TestInternal, ResizeLocksImage) {
|
|||||||
ASSERT_EQ(0, open_image(m_image_name, &ictx));
|
ASSERT_EQ(0, open_image(m_image_name, &ictx));
|
||||||
|
|
||||||
librbd::NoOpProgressContext no_op;
|
librbd::NoOpProgressContext no_op;
|
||||||
ASSERT_EQ(0, ictx->operations->resize(m_image_size >> 1, no_op));
|
ASSERT_EQ(0, ictx->operations->resize(m_image_size >> 1, true, no_op));
|
||||||
|
|
||||||
bool is_owner;
|
bool is_owner;
|
||||||
ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &is_owner));
|
ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &is_owner));
|
||||||
@ -128,7 +128,7 @@ TEST_F(TestInternal, ResizeFailsToLockImage) {
|
|||||||
ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE, "manually locked"));
|
ASSERT_EQ(0, lock_image(*ictx, LOCK_EXCLUSIVE, "manually locked"));
|
||||||
|
|
||||||
librbd::NoOpProgressContext no_op;
|
librbd::NoOpProgressContext no_op;
|
||||||
ASSERT_EQ(-EROFS, ictx->operations->resize(m_image_size >> 1, no_op));
|
ASSERT_EQ(-EROFS, ictx->operations->resize(m_image_size >> 1, true, no_op));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestInternal, SnapCreateLocksImage) {
|
TEST_F(TestInternal, SnapCreateLocksImage) {
|
||||||
@ -336,7 +336,7 @@ TEST_F(TestInternal, CancelAsyncResize) {
|
|||||||
size -= MIN(size, 1<<18);
|
size -= MIN(size, 1<<18);
|
||||||
{
|
{
|
||||||
RWLock::RLocker l(ictx->owner_lock);
|
RWLock::RLocker l(ictx->owner_lock);
|
||||||
ictx->operations->execute_resize(size, prog_ctx, &ctx, 0);
|
ictx->operations->execute_resize(size, true, prog_ctx, &ctx, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to interrupt the in-progress resize
|
// try to interrupt the in-progress resize
|
||||||
@ -384,7 +384,7 @@ TEST_F(TestInternal, MultipleResize) {
|
|||||||
|
|
||||||
RWLock::RLocker l(ictx->owner_lock);
|
RWLock::RLocker l(ictx->owner_lock);
|
||||||
contexts.push_back(new C_SaferCond());
|
contexts.push_back(new C_SaferCond());
|
||||||
ictx->operations->execute_resize(new_size, prog_ctx, contexts.back(), 0);
|
ictx->operations->execute_resize(new_size, true, prog_ctx, contexts.back(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < contexts.size(); ++i) {
|
for (uint32_t i = 0; i < contexts.size(); ++i) {
|
||||||
@ -610,9 +610,9 @@ TEST_F(TestInternal, ResizeCopyup)
|
|||||||
// verify full / partial object removal properly copyup
|
// verify full / partial object removal properly copyup
|
||||||
librbd::NoOpProgressContext no_op;
|
librbd::NoOpProgressContext no_op;
|
||||||
ASSERT_EQ(0, ictx2->operations->resize(m_image_size - (1 << order) - 32,
|
ASSERT_EQ(0, ictx2->operations->resize(m_image_size - (1 << order) - 32,
|
||||||
no_op));
|
true, no_op));
|
||||||
ASSERT_EQ(0, ictx2->operations->resize(m_image_size - (2 << order) - 32,
|
ASSERT_EQ(0, ictx2->operations->resize(m_image_size - (2 << order) - 32,
|
||||||
no_op));
|
true, no_op));
|
||||||
ASSERT_EQ(0, librbd::snap_set(ictx2, "snap1"));
|
ASSERT_EQ(0, librbd::snap_set(ictx2, "snap1"));
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -699,7 +699,7 @@ TEST_F(TestInternal, ShrinkFlushesCache) {
|
|||||||
ictx->aio_work_queue->aio_write(c, 0, buffer.size(), buffer.c_str(), 0);
|
ictx->aio_work_queue->aio_write(c, 0, buffer.size(), buffer.c_str(), 0);
|
||||||
|
|
||||||
librbd::NoOpProgressContext no_op;
|
librbd::NoOpProgressContext no_op;
|
||||||
ASSERT_EQ(0, ictx->operations->resize(m_image_size >> 1, no_op));
|
ASSERT_EQ(0, ictx->operations->resize(m_image_size >> 1, true, no_op));
|
||||||
|
|
||||||
ASSERT_TRUE(c->is_complete());
|
ASSERT_TRUE(c->is_complete());
|
||||||
ASSERT_EQ(0, c->wait_for_complete());
|
ASSERT_EQ(0, c->wait_for_complete());
|
||||||
@ -781,7 +781,7 @@ TEST_F(TestInternal, WriteFullCopyup) {
|
|||||||
ASSERT_EQ(0, open_image(m_image_name, &ictx));
|
ASSERT_EQ(0, open_image(m_image_name, &ictx));
|
||||||
|
|
||||||
librbd::NoOpProgressContext no_op;
|
librbd::NoOpProgressContext no_op;
|
||||||
ASSERT_EQ(0, ictx->operations->resize(1 << ictx->order, no_op));
|
ASSERT_EQ(0, ictx->operations->resize(1 << ictx->order, true, no_op));
|
||||||
|
|
||||||
bufferlist bl;
|
bufferlist bl;
|
||||||
bl.append(std::string(1 << ictx->order, '1'));
|
bl.append(std::string(1 << ictx->order, '1'));
|
||||||
|
@ -420,6 +420,16 @@ TEST_F(TestLibRBD, ResizeAndStat)
|
|||||||
ASSERT_EQ(0, rbd_stat(image, &info, sizeof(info)));
|
ASSERT_EQ(0, rbd_stat(image, &info, sizeof(info)));
|
||||||
ASSERT_EQ(info.size, size / 2);
|
ASSERT_EQ(info.size, size / 2);
|
||||||
|
|
||||||
|
// downsizing without allowing shrink should fail
|
||||||
|
// and image size should not change
|
||||||
|
ASSERT_EQ(-EINVAL, rbd_resize2(image, size / 4, false, NULL, NULL));
|
||||||
|
ASSERT_EQ(0, rbd_stat(image, &info, sizeof(info)));
|
||||||
|
ASSERT_EQ(info.size, size / 2);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, rbd_resize2(image, size / 4, true, NULL, NULL));
|
||||||
|
ASSERT_EQ(0, rbd_stat(image, &info, sizeof(info)));
|
||||||
|
ASSERT_EQ(info.size, size / 4);
|
||||||
|
|
||||||
ASSERT_PASSED(validate_object_map, image);
|
ASSERT_PASSED(validate_object_map, image);
|
||||||
ASSERT_EQ(0, rbd_close(image));
|
ASSERT_EQ(0, rbd_close(image));
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ TEST_F(TestImageSync, SnapshotStress) {
|
|||||||
|
|
||||||
librbd::NoOpProgressContext no_op_progress_ctx;
|
librbd::NoOpProgressContext no_op_progress_ctx;
|
||||||
uint64_t size = 1 + rand() % m_image_size;
|
uint64_t size = 1 + rand() % m_image_size;
|
||||||
ASSERT_EQ(0, m_remote_image_ctx->operations->resize(size,
|
ASSERT_EQ(0, m_remote_image_ctx->operations->resize(size, true,
|
||||||
no_op_progress_ctx));
|
no_op_progress_ctx));
|
||||||
ASSERT_EQ(0, m_remote_image_ctx->state->refresh());
|
ASSERT_EQ(0, m_remote_image_ctx->state->refresh());
|
||||||
|
|
||||||
|
@ -15,10 +15,10 @@ namespace resize {
|
|||||||
namespace at = argument_types;
|
namespace at = argument_types;
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
static int do_resize(librbd::Image& image, uint64_t size, bool no_progress)
|
static int do_resize(librbd::Image& image, uint64_t size, bool allow_shrink, bool no_progress)
|
||||||
{
|
{
|
||||||
utils::ProgressContext pc("Resizing image", no_progress);
|
utils::ProgressContext pc("Resizing image", no_progress);
|
||||||
int r = image.resize_with_progress(size, pc);
|
int r = image.resize2(size, allow_shrink, pc);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
pc.fail();
|
pc.fail();
|
||||||
return r;
|
return r;
|
||||||
@ -70,14 +70,13 @@ int execute(const po::variables_map &vm) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.size > size && !vm["allow-shrink"].as<bool>()) {
|
r = do_resize(image, size, vm["allow-shrink"].as<bool>(), vm[at::NO_PROGRESS].as<bool>());
|
||||||
std::cerr << "rbd: shrinking an image is only allowed with the "
|
|
||||||
<< "--allow-shrink flag" << std::endl;
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = do_resize(image, size, vm[at::NO_PROGRESS].as<bool>());
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
if (r == -EINVAL && !vm["allow-shrink"].as<bool>()) {
|
||||||
|
std::cerr << "rbd: shrinking an image is only allowed with the "
|
||||||
|
<< "--allow-shrink flag" << std::endl;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
std::cerr << "rbd: resize error: " << cpp_strerror(r) << std::endl;
|
std::cerr << "rbd: resize error: " << cpp_strerror(r) << std::endl;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user