Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

librbd: optimize away unnecessary object map updates #10332

Merged
merged 2 commits into from Jul 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 12 additions & 15 deletions src/librbd/AioObjectRequest.cc
Expand Up @@ -402,22 +402,21 @@ namespace librbd {
} else {
// should have been flushed prior to releasing lock
assert(m_ictx->exclusive_lock->is_lock_owner());

m_object_exist = m_ictx->object_map->object_may_exist(m_object_no);

ldout(m_ictx->cct, 20) << "send_pre " << this << " " << m_oid << " "
<< m_object_off << "~" << m_object_len << dendl;
m_state = LIBRBD_AIO_WRITE_PRE;

uint8_t new_state;
boost::optional<uint8_t> current_state;
pre_object_map_update(&new_state);

RWLock::WLocker object_map_locker(m_ictx->object_map_lock);
if ((*m_ictx->object_map)[m_object_no] != new_state) {
if (m_ictx->object_map->update_required(m_object_no, new_state)) {
ldout(m_ictx->cct, 20) << "send_pre " << this << " " << m_oid << " "
<< m_object_off << "~" << m_object_len
<< dendl;
m_state = LIBRBD_AIO_WRITE_PRE;

Context *ctx = util::create_context_callback<AioObjectRequest>(this);
bool updated = m_ictx->object_map->aio_update(m_object_no, new_state,
current_state, ctx);
{}, ctx);
assert(updated);
} else {
write = true;
Expand All @@ -442,17 +441,15 @@ namespace librbd {
// should have been flushed prior to releasing lock
assert(m_ictx->exclusive_lock->is_lock_owner());

ldout(m_ictx->cct, 20) << "send_post " << this << " " << m_oid << " "
<< m_object_off << "~" << m_object_len << dendl;
m_state = LIBRBD_AIO_WRITE_POST;

RWLock::WLocker object_map_locker(m_ictx->object_map_lock);
uint8_t current_state = (*m_ictx->object_map)[m_object_no];
if (current_state != OBJECT_PENDING ||
current_state == OBJECT_NONEXISTENT) {
if (!m_ictx->object_map->update_required(m_object_no, OBJECT_NONEXISTENT)) {
return true;
}

ldout(m_ictx->cct, 20) << "send_post " << this << " " << m_oid << " "
<< m_object_off << "~" << m_object_len << dendl;
m_state = LIBRBD_AIO_WRITE_POST;

Context *ctx = util::create_context_callback<AioObjectRequest>(this);
bool updated = m_ictx->object_map->aio_update(m_object_no,
OBJECT_NONEXISTENT,
Expand Down
12 changes: 12 additions & 0 deletions src/librbd/ObjectMap.cc
Expand Up @@ -90,6 +90,18 @@ bool ObjectMap::object_may_exist(uint64_t object_no) const
return exists;
}

bool ObjectMap::update_required(uint64_t object_no, uint8_t new_state) {
assert(m_image_ctx.object_map_lock.is_wlocked());
uint8_t state = (*this)[object_no];

if ((state == new_state) ||
(new_state == OBJECT_PENDING && state == OBJECT_NONEXISTENT) ||
(new_state == OBJECT_NONEXISTENT && state != OBJECT_PENDING)) {
return false;
}
return true;
}

void ObjectMap::open(Context *on_finish) {
object_map::RefreshRequest<> *req = new object_map::RefreshRequest<>(
m_image_ctx, &m_object_map, m_snap_id, on_finish);
Expand Down
1 change: 1 addition & 0 deletions src/librbd/ObjectMap.h
Expand Up @@ -39,6 +39,7 @@ class ObjectMap {
void close(Context *on_finish);

bool object_may_exist(uint64_t object_no) const;
bool update_required(uint64_t object_no, uint8_t new_state);

void aio_save(Context *on_finish);
void aio_resize(uint64_t new_size, uint8_t default_object_state,
Expand Down
18 changes: 18 additions & 0 deletions src/rbd_replay/ActionTypes.cc
Expand Up @@ -288,12 +288,18 @@ void ActionEntry::decode(__u8 version, bufferlist::iterator &it) {
case ACTION_TYPE_WRITE:
action = WriteAction();
break;
case ACTION_TYPE_DISCARD:
action = DiscardAction();
break;
case ACTION_TYPE_AIO_READ:
action = AioReadAction();
break;
case ACTION_TYPE_AIO_WRITE:
action = AioWriteAction();
break;
case ACTION_TYPE_AIO_DISCARD:
action = AioDiscardAction();
break;
case ACTION_TYPE_OPEN_IMAGE:
action = OpenImageAction();
break;
Expand Down Expand Up @@ -330,12 +336,18 @@ void ActionEntry::generate_test_instances(std::list<ActionEntry *> &o) {
o.push_back(new ActionEntry(WriteAction()));
o.push_back(new ActionEntry(WriteAction(1, 123456789, dependencies, 3, 4,
5)));
o.push_back(new ActionEntry(DiscardAction()));
o.push_back(new ActionEntry(DiscardAction(1, 123456789, dependencies, 3, 4,
5)));
o.push_back(new ActionEntry(AioReadAction()));
o.push_back(new ActionEntry(AioReadAction(1, 123456789, dependencies, 3, 4,
5)));
o.push_back(new ActionEntry(AioWriteAction()));
o.push_back(new ActionEntry(AioWriteAction(1, 123456789, dependencies, 3, 4,
5)));
o.push_back(new ActionEntry(AioDiscardAction()));
o.push_back(new ActionEntry(AioDiscardAction(1, 123456789, dependencies, 3, 4,
5)));

o.push_back(new ActionEntry(OpenImageAction()));
o.push_back(new ActionEntry(OpenImageAction(1, 123456789, dependencies, 3,
Expand Down Expand Up @@ -372,12 +384,18 @@ std::ostream &operator<<(std::ostream &out,
case ACTION_TYPE_WRITE:
out << "Write";
break;
case ACTION_TYPE_DISCARD:
out << "Discard";
break;
case ACTION_TYPE_AIO_READ:
out << "AioRead";
break;
case ACTION_TYPE_AIO_WRITE:
out << "AioWrite";
break;
case ACTION_TYPE_AIO_DISCARD:
out << "AioDiscard";
break;
case ACTION_TYPE_OPEN_IMAGE:
out << "OpenImage";
break;
Expand Down
28 changes: 28 additions & 0 deletions src/rbd_replay/ActionTypes.h
Expand Up @@ -72,6 +72,8 @@ enum ActionType {
ACTION_TYPE_CLOSE_IMAGE = 7,
ACTION_TYPE_AIO_OPEN_IMAGE = 8,
ACTION_TYPE_AIO_CLOSE_IMAGE = 9,
ACTION_TYPE_DISCARD = 10,
ACTION_TYPE_AIO_DISCARD = 11
};

struct ActionBase {
Expand Down Expand Up @@ -170,6 +172,18 @@ struct WriteAction : public IoActionBase {
}
};

struct DiscardAction : public IoActionBase {
static const ActionType ACTION_TYPE = ACTION_TYPE_DISCARD;

DiscardAction() {
}
DiscardAction(action_id_t id, thread_id_t thread_id,
const Dependencies &dependencies, imagectx_id_t imagectx_id,
uint64_t offset, uint64_t length)
: IoActionBase(id, thread_id, dependencies, imagectx_id, offset, length) {
}
};

struct AioReadAction : public IoActionBase {
static const ActionType ACTION_TYPE = ACTION_TYPE_AIO_READ;

Expand All @@ -194,6 +208,18 @@ struct AioWriteAction : public IoActionBase {
}
};

struct AioDiscardAction : public IoActionBase {
static const ActionType ACTION_TYPE = ACTION_TYPE_AIO_DISCARD;

AioDiscardAction() {
}
AioDiscardAction(action_id_t id, thread_id_t thread_id,
const Dependencies &dependencies, imagectx_id_t imagectx_id,
uint64_t offset, uint64_t length)
: IoActionBase(id, thread_id, dependencies, imagectx_id, offset, length) {
}
};

struct OpenImageAction : public ImageActionBase {
static const ActionType ACTION_TYPE = ACTION_TYPE_OPEN_IMAGE;

Expand Down Expand Up @@ -272,8 +298,10 @@ typedef boost::variant<StartThreadAction,
StopThreadAction,
ReadAction,
WriteAction,
DiscardAction,
AioReadAction,
AioWriteAction,
AioDiscardAction,
OpenImageAction,
CloseImageAction,
AioOpenImageAction,
Expand Down
34 changes: 33 additions & 1 deletion src/rbd_replay/actions.cc
Expand Up @@ -57,6 +57,14 @@ struct ConstructVisitor : public boost::static_visitor<Action::ptr> {
return Action::ptr(new AioWriteAction(action));
}

inline Action::ptr operator()(const action::DiscardAction &action) const {
return Action::ptr(new DiscardAction(action));
}

inline Action::ptr operator()(const action::AioDiscardAction &action) const {
return Action::ptr(new AioDiscardAction(action));
}

inline Action::ptr operator()(const action::OpenImageAction &action) const {
return Action::ptr(new OpenImageAction(action));
}
Expand Down Expand Up @@ -118,7 +126,6 @@ void ReadAction::perform(ActionCtx &worker) {
worker.remove_pending(io);
}


void AioWriteAction::perform(ActionCtx &worker) {
static const std::string fake_data(create_fake_data());
dout(ACTION_LEVEL) << "Performing " << *this << dendl;
Expand Down Expand Up @@ -152,6 +159,31 @@ void WriteAction::perform(ActionCtx &worker) {
worker.remove_pending(io);
}

void AioDiscardAction::perform(ActionCtx &worker) {
dout(ACTION_LEVEL) << "Performing " << *this << dendl;
librbd::Image *image = worker.get_image(m_action.imagectx_id);
PendingIO::ptr io(new PendingIO(pending_io_id(), worker));
worker.add_pending(io);
if (worker.readonly()) {
worker.remove_pending(io);
} else {
int r = image->aio_discard(m_action.offset, m_action.length, &io->completion());
assertf(r >= 0, "id = %d, r = %d", id(), r);
}
}

void DiscardAction::perform(ActionCtx &worker) {
dout(ACTION_LEVEL) << "Performing " << *this << dendl;
librbd::Image *image = worker.get_image(m_action.imagectx_id);
PendingIO::ptr io(new PendingIO(pending_io_id(), worker));
worker.add_pending(io);
if (!worker.readonly()) {
ssize_t r = image->discard(m_action.offset, m_action.length);
assertf(r >= 0, "id = %d, r = %d", id(), r);
}
worker.remove_pending(io);
}

void OpenImageAction::perform(ActionCtx &worker) {
dout(ACTION_LEVEL) << "Performing " << *this << dendl;
PendingIO::ptr io(new PendingIO(pending_io_id(), worker));
Expand Down
30 changes: 30 additions & 0 deletions src/rbd_replay/actions.hpp
Expand Up @@ -251,6 +251,36 @@ class WriteAction : public TypedAction<action::WriteAction> {
};


class AioDiscardAction : public TypedAction<action::AioDiscardAction> {
public:
explicit AioDiscardAction(const action::AioDiscardAction &action)
: TypedAction<action::AioDiscardAction>(action) {
}

virtual void perform(ActionCtx &ctx);

protected:
virtual const char *get_action_name() const {
return "AioDiscardAction";
}
};


class DiscardAction : public TypedAction<action::DiscardAction> {
public:
explicit DiscardAction(const action::DiscardAction &action)
: TypedAction<action::DiscardAction>(action) {
}

virtual void perform(ActionCtx &ctx);

protected:
virtual const char *get_action_name() const {
return "DiscardAction";
}
};


class OpenImageAction : public TypedAction<action::OpenImageAction> {
public:
explicit OpenImageAction(const action::OpenImageAction &action)
Expand Down
24 changes: 24 additions & 0 deletions src/rbd_replay/ios.cc
Expand Up @@ -111,6 +111,18 @@ void WriteIO::write_debug(std::ostream& out) const {
out << ", imagectx=" << m_imagectx << ", offset=" << m_offset << ", length=" << m_length << "]";
}

void DiscardIO::encode(bufferlist &bl) const {
action::Action action((action::DiscardAction(
ionum(), thread_id(), convert_dependencies(start_time(), dependencies()),
m_imagectx, m_offset, m_length)));
::encode(action, bl);
}

void DiscardIO::write_debug(std::ostream& out) const {
write_debug_base(out, "discard");
out << ", imagectx=" << m_imagectx << ", offset=" << m_offset << ", length=" << m_length << "]";
}

void AioReadIO::encode(bufferlist &bl) const {
action::Action action((action::AioReadAction(
ionum(), thread_id(), convert_dependencies(start_time(), dependencies()),
Expand All @@ -135,6 +147,18 @@ void AioWriteIO::write_debug(std::ostream& out) const {
out << ", imagectx=" << m_imagectx << ", offset=" << m_offset << ", length=" << m_length << "]";
}

void AioDiscardIO::encode(bufferlist &bl) const {
action::Action action((action::AioDiscardAction(
ionum(), thread_id(), convert_dependencies(start_time(), dependencies()),
m_imagectx, m_offset, m_length)));
::encode(action, bl);
}

void AioDiscardIO::write_debug(std::ostream& out) const {
write_debug_base(out, "aio discard");
out << ", imagectx=" << m_imagectx << ", offset=" << m_offset << ", length=" << m_length << "]";
}

void OpenImageIO::encode(bufferlist &bl) const {
action::Action action((action::OpenImageAction(
ionum(), thread_id(), convert_dependencies(start_time(), dependencies()),
Expand Down
50 changes: 50 additions & 0 deletions src/rbd_replay/ios.hpp
Expand Up @@ -186,6 +186,31 @@ class WriteIO : public IO {
uint64_t m_length;
};

class DiscardIO : public IO {
public:
DiscardIO(action_id_t ionum,
uint64_t start_time,
thread_id_t thread_id,
const io_set_t& deps,
imagectx_id_t imagectx,
uint64_t offset,
uint64_t length)
: IO(ionum, start_time, thread_id, deps),
m_imagectx(imagectx),
m_offset(offset),
m_length(length) {
}

virtual void encode(bufferlist &bl) const;

void write_debug(std::ostream& out) const;

private:
imagectx_id_t m_imagectx;
uint64_t m_offset;
uint64_t m_length;
};

class AioReadIO : public IO {
public:
AioReadIO(action_id_t ionum,
Expand Down Expand Up @@ -236,6 +261,31 @@ class AioWriteIO : public IO {
uint64_t m_length;
};

class AioDiscardIO : public IO {
public:
AioDiscardIO(action_id_t ionum,
uint64_t start_time,
thread_id_t thread_id,
const io_set_t& deps,
imagectx_id_t imagectx,
uint64_t offset,
uint64_t length)
: IO(ionum, start_time, thread_id, deps),
m_imagectx(imagectx),
m_offset(offset),
m_length(length) {
}

virtual void encode(bufferlist &bl) const;

void write_debug(std::ostream& out) const;

private:
imagectx_id_t m_imagectx;
uint64_t m_offset;
uint64_t m_length;
};

class OpenImageIO : public IO {
public:
OpenImageIO(action_id_t ionum,
Expand Down