librbd: simplify AioRequest constructor parameters

Moved all parent overlap computation to within AioRequest so that
callers don't need to independently compute the overlap.  Also
removed the need to pass the snap_id for write operations since
it can only be CEPH_NOSNAP.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2015-03-31 12:28:11 -04:00
parent 1c381b3ca8
commit 46515971ed
6 changed files with 166 additions and 302 deletions

View File

@ -24,21 +24,21 @@
namespace librbd {
AioRequest::AioRequest() :
m_ictx(NULL),
m_object_no(0), m_object_off(0), m_object_len(0),
m_snap_id(CEPH_NOSNAP), m_completion(NULL), m_parent_completion(NULL),
m_hide_enoent(false) {}
AioRequest::AioRequest(ImageCtx *ictx, const std::string &oid,
uint64_t objectno, uint64_t off, uint64_t len,
const ::SnapContext &snapc, librados::snap_t snap_id,
librados::snap_t snap_id,
Context *completion,
bool hide_enoent) :
m_ictx(ictx), m_oid(oid), m_object_no(objectno),
m_object_off(off), m_object_len(len), m_snap_id(snap_id),
m_completion(completion), m_parent_completion(NULL),
m_hide_enoent(hide_enoent) {
m_snaps.insert(m_snaps.end(), snapc.snaps.begin(), snapc.snaps.end());
bool hide_enoent)
: m_ictx(ictx), m_oid(oid), m_object_no(objectno), m_object_off(off),
m_object_len(len), m_snap_id(snap_id), m_completion(completion),
m_parent_completion(NULL), m_hide_enoent(hide_enoent) {
Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, m_object_no,
0, m_ictx->layout.fl_object_size, m_parent_extents);
RWLock::RLocker snap_locker(m_ictx->snap_lock);
RWLock::RLocker parent_locker(m_ictx->parent_lock);
compute_parent_extents();
}
AioRequest::~AioRequest() {
@ -60,7 +60,34 @@ namespace librbd {
}
}
void AioRequest::read_from_parent(vector<pair<uint64_t,uint64_t> >& image_extents,
bool AioRequest::compute_parent_extents() {
assert(m_ictx->snap_lock.is_locked());
assert(m_ictx->parent_lock.is_locked());
uint64_t parent_overlap;
int r = m_ictx->get_parent_overlap(m_snap_id, &parent_overlap);
if (r < 0) {
// NOTE: it's possible for a snapshot to be deleted while we are
// still reading from it
lderr(m_ictx->cct) << this << " compute_parent_extents: failed to "
<< "retrieve parent overlap: " << cpp_strerror(r)
<< dendl;
m_parent_extents.clear();
return false;
}
uint64_t object_overlap =
m_ictx->prune_parent_extents(m_parent_extents, parent_overlap);
if (object_overlap > 0) {
ldout(m_ictx->cct, 20) << this << " compute_parent_extents: "
<< "overlap " << parent_overlap << " "
<< "extents " << m_parent_extents << dendl;
return true;
}
return false;
}
void AioRequest::read_from_parent(const vector<pair<uint64_t,uint64_t> >& parent_extents,
bool block_completion)
{
assert(!m_parent_completion);
@ -74,9 +101,9 @@ namespace librbd {
ldout(m_ictx->cct, 20) << "read_from_parent this = " << this
<< " parent completion " << m_parent_completion
<< " extents " << image_extents
<< " extents " << parent_extents
<< dendl;
int r = aio_read(m_ictx->parent, image_extents, NULL, &m_read_data,
int r = aio_read(m_ictx->parent, parent_extents, NULL, &m_read_data,
m_parent_completion, 0);
if (r < 0) {
lderr(m_ictx->cct) << "read_from_parent " << this
@ -98,32 +125,21 @@ namespace librbd {
AioRead::AioRead(ImageCtx *ictx, const std::string &oid,
uint64_t objectno, uint64_t offset, uint64_t len,
vector<pair<uint64_t,uint64_t> >& be,
const ::SnapContext &snapc,
librados::snap_t snap_id, bool sparse,
Context *completion, int op_flags)
: AioRequest(ictx, oid, objectno, offset, len, snapc, snap_id, completion,
false),
m_buffer_extents(be), m_tried_parent(false),
m_sparse(sparse), m_op_flags(op_flags), m_state(LIBRBD_AIO_READ_FLAT) {
RWLock::RLocker l(m_ictx->snap_lock);
RWLock::RLocker l2(m_ictx->parent_lock);
Striper::extent_to_file(m_ictx->cct, &m_ictx->layout,
m_object_no, 0, m_ictx->layout.fl_object_size,
m_image_extents);
: AioRequest(ictx, oid, objectno, offset, len, snap_id, completion, false),
m_buffer_extents(be), m_tried_parent(false), m_sparse(sparse),
m_op_flags(op_flags), m_state(LIBRBD_AIO_READ_FLAT) {
guard_read();
}
void AioRead::guard_read()
{
assert(m_ictx->snap_lock.is_locked());
RWLock::RLocker snap_locker(m_ictx->snap_lock);
RWLock::RLocker parent_locker(m_ictx->parent_lock);
uint64_t image_overlap = 0;
m_ictx->get_parent_overlap(m_snap_id, &image_overlap);
uint64_t object_overlap =
m_ictx->prune_parent_extents(m_image_extents, image_overlap);
if (object_overlap) {
if (has_parent()) {
ldout(m_ictx->cct, 20) << __func__ << " guarding read" << dendl;
m_state = LIBRBD_AIO_READ_GUARD;
}
@ -131,7 +147,8 @@ namespace librbd {
bool AioRead::should_complete(int r)
{
ldout(m_ictx->cct, 20) << "should_complete " << this << " " << m_oid << " " << m_object_off << "~" << m_object_len
ldout(m_ictx->cct, 20) << "should_complete " << this << " " << m_oid << " "
<< m_object_off << "~" << m_object_len
<< " r = " << r << dendl;
bool finished = true;
@ -154,25 +171,25 @@ namespace librbd {
}
// calculate reverse mapping onto the image
vector<pair<uint64_t,uint64_t> > image_extents;
Striper::extent_to_file(m_ictx->cct, &m_ictx->layout,
m_object_no, m_object_off, m_object_len,
image_extents);
vector<pair<uint64_t,uint64_t> > parent_extents;
Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, m_object_no,
m_object_off, m_object_len, parent_extents);
uint64_t image_overlap = 0;
r = m_ictx->get_parent_overlap(m_snap_id, &image_overlap);
if (r < 0) {
assert(0 == "FIXME");
uint64_t parent_overlap = 0;
uint64_t object_overlap = 0;
r = m_ictx->get_parent_overlap(m_snap_id, &parent_overlap);
if (r == 0) {
object_overlap = m_ictx->prune_parent_extents(parent_extents,
parent_overlap);
}
uint64_t object_overlap = m_ictx->prune_parent_extents(image_extents,
image_overlap);
if (object_overlap) {
if (object_overlap > 0) {
m_tried_parent = true;
if (is_copy_on_read(m_ictx, m_snap_id)) {
m_state = LIBRBD_AIO_READ_COPYUP;
}
read_from_parent(image_extents, true);
read_from_parent(parent_extents, true);
finished = false;
}
}
@ -187,7 +204,8 @@ namespace librbd {
}
break;
case LIBRBD_AIO_READ_COPYUP:
ldout(m_ictx->cct, 20) << "should_complete " << this << " READ_COPYUP" << dendl;
ldout(m_ictx->cct, 20) << "should_complete " << this << " READ_COPYUP"
<< dendl;
// This is the extra step for copy-on-read: kick off an asynchronous copyup.
// It is different from copy-on-write as asynchronous copyup will finish
// by itself so state won't go back to LIBRBD_AIO_READ_GUARD.
@ -201,25 +219,13 @@ namespace librbd {
map<uint64_t, CopyupRequest*>::iterator it =
m_ictx->copyup_list.find(m_object_no);
if (it == m_ictx->copyup_list.end()) {
RWLock::RLocker l(m_ictx->snap_lock);
RWLock::RLocker l2(m_ictx->parent_lock);
if (m_ictx->parent == NULL) {
ldout(m_ictx->cct, 20) << "parent is gone; do nothing" << dendl;
break;
}
// If parent still exists, overlap might also have changed.
uint64_t parent_overlap;
r = m_ictx->get_parent_overlap(CEPH_NOSNAP, &parent_overlap);
assert(r == 0);
uint64_t newlen = m_ictx->prune_parent_extents(
m_image_extents, parent_overlap);
if (newlen != 0) {
RWLock::RLocker snap_locker(m_ictx->snap_lock);
RWLock::RLocker parent_locker(m_ictx->parent_lock);
if (compute_parent_extents()) {
// create and kick off a CopyupRequest
CopyupRequest *new_req = new CopyupRequest(m_ictx, m_oid,
m_object_no,
m_image_extents);
m_parent_extents);
m_ictx->copyup_list[m_object_no] = new_req;
new_req->queue_send();
}
@ -227,7 +233,8 @@ namespace librbd {
}
break;
case LIBRBD_AIO_READ_FLAT:
ldout(m_ictx->cct, 20) << "should_complete " << this << " READ_FLAT" << dendl;
ldout(m_ictx->cct, 20) << "should_complete " << this << " READ_FLAT"
<< dendl;
// The read content should be deposit in m_read_data
break;
default:
@ -239,7 +246,8 @@ namespace librbd {
}
int AioRead::send() {
ldout(m_ictx->cct, 20) << "send " << this << " " << m_oid << " " << m_object_off << "~" << m_object_len << dendl;
ldout(m_ictx->cct, 20) << "send " << this << " " << m_oid << " "
<< m_object_off << "~" << m_object_len << dendl;
// send read request to parent if the object doesn't exist locally
if (!m_ictx->object_map.object_may_exist(m_object_no)) {
@ -267,24 +275,16 @@ namespace librbd {
/** write **/
AbstractWrite::AbstractWrite()
: m_state(LIBRBD_AIO_WRITE_FLAT),
m_parent_overlap(0),
m_snap_seq(0) {}
AbstractWrite::AbstractWrite(ImageCtx *ictx, const std::string &oid,
uint64_t object_no, uint64_t object_off, uint64_t len,
vector<pair<uint64_t,uint64_t> >& objectx,
uint64_t object_overlap,
const ::SnapContext &snapc, librados::snap_t snap_id,
Context *completion,
bool hide_enoent)
: AioRequest(ictx, oid, object_no, object_off, len, snapc, snap_id,
completion, hide_enoent),
uint64_t object_no, uint64_t object_off,
uint64_t len, const ::SnapContext &snapc,
Context *completion, bool hide_enoent)
: AioRequest(ictx, oid, object_no, object_off, len, CEPH_NOSNAP, completion,
hide_enoent),
m_state(LIBRBD_AIO_WRITE_FLAT), m_snap_seq(snapc.seq.val),
m_entire_object(NULL)
{
m_object_image_extents = objectx;
m_parent_overlap = object_overlap;
m_snaps.insert(m_snaps.end(), snapc.snaps.begin(), snapc.snaps.end());
}
void AbstractWrite::guard_write()
@ -298,7 +298,8 @@ namespace librbd {
bool AbstractWrite::should_complete(int r)
{
ldout(m_ictx->cct, 20) << "write " << this << " " << m_oid << " " << m_object_off << "~" << m_object_len
ldout(m_ictx->cct, 20) << "write " << this << " " << m_oid << " "
<< m_object_off << "~" << m_object_len
<< " should_complete: r = " << r << dendl;
map<uint64_t, CopyupRequest*>::iterator it;
@ -326,48 +327,18 @@ namespace librbd {
RWLock::RLocker l(m_ictx->snap_lock);
RWLock::RLocker l2(m_ictx->parent_lock);
/*
* Parent may have disappeared; if so, recover by using
* send_copyup() to send the original write req (the copyup
* operation itself will be a no-op, since someone must have
* populated the child object while we weren't looking).
* Move to WRITE_FLAT state as we'll be done with the
* operation once the null copyup completes.
*/
if (m_ictx->parent == NULL) {
ldout(m_ictx->cct, 20) << "parent is gone; do null copyup " << dendl;
m_state = LIBRBD_AIO_WRITE_FLAT;
send_copyup();
finished = false;
break;
}
// If parent still exists, overlap might also have changed.
uint64_t parent_overlap;
r = m_ictx->get_parent_overlap(CEPH_NOSNAP, &parent_overlap);
assert(r == 0);
uint64_t newlen = m_ictx->prune_parent_extents(
m_object_image_extents, parent_overlap);
// copyup the entire object up to the overlap point, if any
if (newlen != 0) {
ldout(m_ictx->cct, 20) << "should_complete(" << this << ") overlap "
<< parent_overlap << " newlen "
<< newlen << " image_extents"
<< m_object_image_extents << dendl;
if (compute_parent_extents()) {
m_state = LIBRBD_AIO_WRITE_COPYUP;
if (is_copy_on_read(m_ictx, m_snap_id)) {
if (is_copy_on_read(m_ictx, CEPH_NOSNAP)) {
m_ictx->copyup_list_lock.Lock();
it = m_ictx->copyup_list.find(m_object_no);
if (it == m_ictx->copyup_list.end()) {
// If it is not in the list, create a CopyupRequest and wait for it.
// If it is not in the list, create a CopyupRequest and wait
CopyupRequest *new_req = new CopyupRequest(m_ictx, m_oid,
m_object_no,
m_object_image_extents);
m_parent_extents);
// make sure to wait on this CopyupRequest
new_req->append_request(this);
m_ictx->copyup_list[m_object_no] = new_req;
@ -381,12 +352,19 @@ namespace librbd {
m_ictx->copyup_list_lock.Unlock();
}
} else {
read_from_parent(m_object_image_extents, false);
read_from_parent(m_parent_extents, false);
}
} else {
/*
* Parent may have disappeared; if so, recover by using
* send_copyup() to send the original write req (the copyup
* operation itself will be a no-op, since someone must have
* populated the child object while we weren't looking).
* Move to WRITE_FLAT state as we'll be done with the
* operation once the null copyup completes.
*/
ldout(m_ictx->cct, 20) << "should_complete(" << this
<< "): parent overlap now 0" << dendl;
m_object_image_extents.clear();
m_state = LIBRBD_AIO_WRITE_FLAT;
send_copyup();
}
@ -430,7 +408,7 @@ namespace librbd {
case LIBRBD_AIO_WRITE_ERROR:
assert(r < 0);
lderr(m_ictx->cct) << "WRITE_ERROR: " << cpp_strerror(r)
<< dendl;
<< dendl;
break;
default:
@ -536,7 +514,8 @@ namespace librbd {
}
void AbstractWrite::send_copyup() {
ldout(m_ictx->cct, 20) << "send_copyup " << this << " " << m_oid << " " << m_object_off << "~" << m_object_len << dendl;
ldout(m_ictx->cct, 20) << "send_copyup " << this << " " << m_oid << " "
<< m_object_off << "~" << m_object_len << dendl;
librados::ObjectWriteOperation op;
if (!m_read_data.is_zero()) {
op.exec("rbd", "copyup", m_read_data);

View File

@ -27,10 +27,9 @@ namespace librbd {
class AioRequest
{
public:
AioRequest();
AioRequest(ImageCtx *ictx, const std::string &oid,
uint64_t objectno, uint64_t off, uint64_t len,
const ::SnapContext &snapc, librados::snap_t snap_id,
librados::snap_t snap_id,
Context *completion, bool hide_enoent);
virtual ~AioRequest();
@ -39,8 +38,13 @@ namespace librbd {
virtual bool should_complete(int r) = 0;
virtual int send() = 0;
bool has_parent() const {
return !m_parent_extents.empty();
}
protected:
void read_from_parent(vector<pair<uint64_t,uint64_t> >& image_extents,
bool compute_parent_extents();
void read_from_parent(const vector<pair<uint64_t,uint64_t> >& image_extents,
bool block_completion);
ImageCtx *m_ictx;
@ -48,17 +52,17 @@ namespace librbd {
uint64_t m_object_no, m_object_off, m_object_len;
librados::snap_t m_snap_id;
Context *m_completion;
std::vector<std::pair<uint64_t,uint64_t> > m_parent_extents;
AioCompletion *m_parent_completion;
ceph::bufferlist m_read_data;
bool m_hide_enoent;
std::vector<librados::snap_t> m_snaps;
};
class AioRead : public AioRequest {
public:
AioRead(ImageCtx *ictx, const std::string &oid,
uint64_t objectno, uint64_t offset, uint64_t len,
vector<pair<uint64_t,uint64_t> >& be, const ::SnapContext &snapc,
vector<pair<uint64_t,uint64_t> >& be,
librados::snap_t snap_id, bool sparse,
Context *completion, int op_flags);
virtual ~AioRead() {}
@ -79,7 +83,6 @@ namespace librbd {
bool m_tried_parent;
bool m_sparse;
int m_op_flags;
vector<pair<uint64_t,uint64_t> > m_image_extents;
/**
* Reads go through the following state machine to deal with
@ -108,22 +111,14 @@ namespace librbd {
class AbstractWrite : public AioRequest {
public:
AbstractWrite();
AbstractWrite(ImageCtx *ictx, const std::string &oid,
uint64_t object_no, uint64_t object_off, uint64_t len,
vector<pair<uint64_t,uint64_t> >& objectx, uint64_t object_overlap,
const ::SnapContext &snapc,
librados::snap_t snap_id,
Context *completion,
bool hide_enoent);
AbstractWrite(ImageCtx *ictx, const std::string &oid, uint64_t object_no,
uint64_t object_off, uint64_t len, const ::SnapContext &snapc,
Context *completion, bool hide_enoent);
virtual ~AbstractWrite() {}
virtual bool should_complete(int r);
virtual int send();
bool has_parent() const {
return !m_object_image_extents.empty();
}
private:
/**
* Writes go through the following state machine to deal with
@ -134,7 +129,7 @@ namespace librbd {
* . |
* . \---> LIBRBD_AIO_WRITE_PRE
* . | |
* . . . . . . | . . . . | . . . . . . . . . . .
* . . . . . . | . . . . | . . . . . . . . . . .
* . | -or- | .
* . | | v
* . | \----------------> LIBRBD_AIO_WRITE_FLAT . . .
@ -150,7 +145,7 @@ namespace librbd {
* . LIBRBD_AIO_WRITE_POST .
* . | .
* . v .
* . . . . . . . . . . . . . . > <finish> < . . . . . . . . . . . . . .
* . . . . . . . . . . . . . . > <finish> < . . . . . . . . . . . . . .
*
* The _PRE_REMOVE/_POST_REMOVE states are skipped if the object map
* is disabled. The write starts in _WRITE_GUARD or _FLAT depending on
@ -167,10 +162,9 @@ namespace librbd {
protected:
write_state_d m_state;
vector<pair<uint64_t,uint64_t> > m_object_image_extents;
uint64_t m_parent_overlap;
librados::ObjectWriteOperation m_write;
uint64_t m_snap_seq;
std::vector<librados::snap_t> m_snaps;
ceph::bufferlist *m_entire_object;
virtual void add_write_ops(librados::ObjectWriteOperation *wr) = 0;
@ -189,16 +183,10 @@ namespace librbd {
class AioWrite : public AbstractWrite {
public:
AioWrite(ImageCtx *ictx, const std::string &oid,
uint64_t object_no, uint64_t object_off,
vector<pair<uint64_t,uint64_t> >& objectx, uint64_t object_overlap,
const ceph::bufferlist &data, const ::SnapContext &snapc,
librados::snap_t snap_id,
Context *completion)
: AbstractWrite(ictx, oid,
object_no, object_off, data.length(),
objectx, object_overlap,
snapc, snap_id,
AioWrite(ImageCtx *ictx, const std::string &oid, uint64_t object_no,
uint64_t object_off, const ceph::bufferlist &data,
const ::SnapContext &snapc, Context *completion)
: AbstractWrite(ictx, oid, object_no, object_off, data.length(), snapc,
completion, false),
m_write_data(data), m_op_flags(0) {
}
@ -220,16 +208,9 @@ namespace librbd {
class AioRemove : public AbstractWrite {
public:
AioRemove(ImageCtx *ictx, const std::string &oid,
uint64_t object_no,
vector<pair<uint64_t,uint64_t> >& objectx, uint64_t object_overlap,
const ::SnapContext &snapc, librados::snap_t snap_id,
Context *completion)
: AbstractWrite(ictx, oid,
object_no, 0, 0,
objectx, object_overlap,
snapc, snap_id, completion,
true),
AioRemove(ImageCtx *ictx, const std::string &oid, uint64_t object_no,
const ::SnapContext &snapc, Context *completion)
: AbstractWrite(ictx, oid, object_no, 0, 0, snapc, completion, true),
m_object_state(OBJECT_NONEXISTENT) {
}
virtual ~AioRemove() {}
@ -269,16 +250,11 @@ namespace librbd {
class AioTruncate : public AbstractWrite {
public:
AioTruncate(ImageCtx *ictx, const std::string &oid,
uint64_t object_no, uint64_t object_off,
vector<pair<uint64_t,uint64_t> >& objectx, uint64_t object_overlap,
const ::SnapContext &snapc, librados::snap_t snap_id,
Context *completion)
: AbstractWrite(ictx, oid,
object_no, object_off, 0,
objectx, object_overlap,
snapc, snap_id, completion,
true) {
AioTruncate(ImageCtx *ictx, const std::string &oid, uint64_t object_no,
uint64_t object_off, const ::SnapContext &snapc,
Context *completion)
: AbstractWrite(ictx, oid, object_no, object_off, 0, snapc, completion,
true) {
}
virtual ~AioTruncate() {}
@ -294,16 +270,11 @@ namespace librbd {
class AioZero : public AbstractWrite {
public:
AioZero(ImageCtx *ictx, const std::string &oid,
uint64_t object_no, uint64_t object_off, uint64_t object_len,
vector<pair<uint64_t,uint64_t> >& objectx, uint64_t object_overlap,
const ::SnapContext &snapc, librados::snap_t snap_id,
Context *completion)
: AbstractWrite(ictx, oid,
object_no, object_off, object_len,
objectx, object_overlap,
snapc, snap_id, completion,
true) {
AioZero(ImageCtx *ictx, const std::string &oid, uint64_t object_no,
uint64_t object_off, uint64_t object_len,
const ::SnapContext &snapc, Context *completion)
: AbstractWrite(ictx, oid, object_no, object_off, object_len, snapc,
completion, true) {
}
virtual ~AioZero() {}

View File

@ -38,39 +38,17 @@ public:
return -ERESTART;
}
RWLock::RLocker l2(m_image_ctx.snap_lock);
uint64_t overlap;
{
RWLock::RLocker l3(m_image_ctx.parent_lock);
bufferlist bl;
string oid = m_image_ctx.get_object_name(m_object_no);
AioWrite *req = new AioWrite(&m_image_ctx, oid, m_object_no, 0, bl, m_snapc,
this);
if (!req->has_parent()) {
// stop early if the parent went away - it just means
// another flatten finished first, so this one is useless.
if (!m_image_ctx.parent) {
return 1;
}
// resize might have occurred while flatten is running
uint64_t parent_overlap;
int r = m_image_ctx.get_parent_overlap(CEPH_NOSNAP, &parent_overlap);
assert(r == 0);
overlap = min(m_image_ctx.size, parent_overlap);
}
// map child object onto the parent
vector<pair<uint64_t,uint64_t> > objectx;
Striper::extent_to_file(cct, &m_image_ctx.layout, m_object_no,
0, m_object_size, objectx);
uint64_t object_overlap = m_image_ctx.prune_parent_extents(objectx, overlap);
assert(object_overlap <= m_object_size);
if (object_overlap == 0) {
// resize shrunk image while flattening
// another flatten finished first or the image was resized
delete req;
return 1;
}
bufferlist bl;
string oid = m_image_ctx.get_object_name(m_object_no);
AioWrite *req = new AioWrite(&m_image_ctx, oid, m_object_no, 0, objectx,
object_overlap, bl, m_snapc, CEPH_NOSNAP,
this);
int r = req->send();
assert(r == 0);
return 0;

View File

@ -251,14 +251,9 @@ bool AsyncTrimRequest::send_clean_boundary() {
lost_exclusive_lock = true;
} else {
::SnapContext snapc;
uint64_t parent_overlap;
{
RWLock::RLocker l2(m_image_ctx.snap_lock);
snapc = m_image_ctx.snapc;
RWLock::RLocker l3(m_image_ctx.parent_lock);
int r = m_image_ctx.get_parent_overlap(CEPH_NOSNAP, &parent_overlap);
assert(r == 0);
}
// discard the weird boundary, if any
@ -273,21 +268,13 @@ bool AsyncTrimRequest::send_clean_boundary() {
ldout(cct, 20) << " ex " << *p << dendl;
Context *req_comp = new C_ContextCompletion(*completion);
// reverse map this object extent onto the parent
vector<pair<uint64_t,uint64_t> > objectx;
Striper::extent_to_file(cct, &m_image_ctx.layout, p->objectno, 0,
m_image_ctx.layout.fl_object_size, objectx);
uint64_t object_overlap =
m_image_ctx.prune_parent_extents(objectx, parent_overlap);
AbstractWrite *req;
if (p->offset == 0) {
req = new AioRemove(&m_image_ctx, p->oid.name, p->objectno, objectx,
object_overlap, snapc, CEPH_NOSNAP, req_comp);
req = new AioRemove(&m_image_ctx, p->oid.name, p->objectno, snapc,
req_comp);
} else {
req = new AioTruncate(&m_image_ctx, p->oid.name, p->objectno, p->offset,
objectx, object_overlap, snapc, CEPH_NOSNAP,
req_comp);
req = new AioTruncate(&m_image_ctx, p->oid.name, p->objectno,
p->offset, snapc, req_comp);
}
int r = req->send();
if (r < 0) {

View File

@ -157,30 +157,14 @@ namespace librbd {
uint64_t trunc_size, __u32 trunc_seq,
Context *oncommit)
{
m_ictx->snap_lock.get_read();
librados::snap_t snap_id = m_ictx->snap_id;
m_ictx->parent_lock.get_read();
uint64_t overlap = 0;
m_ictx->get_parent_overlap(snap_id, &overlap);
m_ictx->parent_lock.put_read();
m_ictx->snap_lock.put_read();
uint64_t object_no = oid_to_object_no(oid.name, m_ictx->object_prefix);
// reverse map this object extent onto the parent
vector<pair<uint64_t,uint64_t> > objectx;
Striper::extent_to_file(m_ictx->cct, &m_ictx->layout,
object_no, 0, m_ictx->layout.fl_object_size,
objectx);
uint64_t object_overlap = m_ictx->prune_parent_extents(objectx, overlap);
write_result_d *result = new write_result_d(oid.name, oncommit);
m_writes[oid.name].push(result);
ldout(m_ictx->cct, 20) << "write will wait for result " << result << dendl;
C_OrderedWrite *req_comp = new C_OrderedWrite(m_ictx->cct, result, this);
AioWrite *req = new AioWrite(m_ictx, oid.name,
object_no, off, objectx, object_overlap,
bl, snapc, snap_id,
req_comp);
AioWrite *req = new AioWrite(m_ictx, oid.name, object_no, off, bl, snapc,
req_comp);
req->send();
return ++m_tid;
}

View File

@ -3447,29 +3447,21 @@ reprotect_and_return_err:
RWLock::RLocker md_locker(ictx->md_lock);
uint64_t clip_len = len;
snapid_t snap_id;
::SnapContext snapc;
uint64_t overlap = 0;
{
// prevent image size from changing between computing clip and recording
// pending async operation
RWLock::RLocker snap_locker(ictx->snap_lock);
if (ictx->snap_id != CEPH_NOSNAP || ictx->read_only) {
return -EROFS;
}
r = clip_io(ictx, off, &clip_len);
if (r < 0) {
return r;
}
snap_id = ictx->snap_id;
snapc = ictx->snapc;
ictx->parent_lock.get_read();
ictx->get_parent_overlap(ictx->snap_id, &overlap);
ictx->parent_lock.put_read();
if (snap_id != CEPH_NOSNAP || ictx->read_only) {
return -EROFS;
}
ldout(cct, 20) << " parent overlap " << overlap << dendl;
c->get();
c->init_time(ictx, AIO_TYPE_WRITE);
@ -3505,16 +3497,8 @@ reprotect_and_return_err:
c->add_request();
ictx->write_to_cache(p->oid, bl, p->length, p->offset, req_comp, op_flags);
} else {
// reverse map this object extent onto the parent
vector<pair<uint64_t,uint64_t> > objectx;
Striper::extent_to_file(ictx->cct, &ictx->layout,
p->objectno, 0, ictx->layout.fl_object_size,
objectx);
uint64_t object_overlap = ictx->prune_parent_extents(objectx, overlap);
AioWrite *req = new AioWrite(ictx, p->oid.name, p->objectno, p->offset,
objectx, object_overlap,
bl, snapc, snap_id, req_comp);
bl, snapc, req_comp);
c->add_request();
req->set_op_flags(op_flags);
@ -3603,28 +3587,22 @@ reprotect_and_return_err:
RWLock::RLocker md_locker(ictx->md_lock);
uint64_t clip_len = len;
snapid_t snap_id;
::SnapContext snapc;
uint64_t overlap;
{
// prevent image size from changing between computing clip and recording
// pending async operation
RWLock::RLocker snap_locker(ictx->snap_lock);
if (ictx->snap_id != CEPH_NOSNAP || ictx->read_only) {
return -EROFS;
}
r = clip_io(ictx, off, &clip_len);
if (r < 0) {
return r;
}
// TODO: check for snap
snap_id = ictx->snap_id;
snapc = ictx->snapc;
ictx->parent_lock.get_read();
ictx->get_parent_overlap(ictx->snap_id, &overlap);
ictx->parent_lock.put_read();
if (snap_id != CEPH_NOSNAP || ictx->read_only) {
return -EROFS;
}
c->get();
c->init_time(ictx, AIO_TYPE_DISCARD);
@ -3651,30 +3629,17 @@ reprotect_and_return_err:
AbstractWrite *req;
c->add_request();
// reverse map this object extent onto the parent
vector<pair<uint64_t,uint64_t> > objectx;
uint64_t object_overlap = 0;
if (off < overlap) { // we might overlap...
Striper::extent_to_file(ictx->cct, &ictx->layout,
p->objectno, 0, ictx->layout.fl_object_size,
objectx);
object_overlap = ictx->prune_parent_extents(objectx, overlap);
}
if (p->offset == 0 && p->length == ictx->layout.fl_object_size) {
req = new AioRemove(ictx, p->oid.name, p->objectno, objectx, object_overlap,
snapc, snap_id, req_comp);
req = new AioRemove(ictx, p->oid.name, p->objectno, snapc, req_comp);
} else if (p->offset + p->length == ictx->layout.fl_object_size) {
req = new AioTruncate(ictx, p->oid.name, p->objectno, p->offset, objectx, object_overlap,
snapc, snap_id, req_comp);
req = new AioTruncate(ictx, p->oid.name, p->objectno, p->offset, snapc,
req_comp);
} else {
if(ictx->cct->_conf->rbd_skip_partial_discard) {
continue;
} else {
req = new AioZero(ictx, p->oid.name, p->objectno, p->offset, p->length,
objectx, object_overlap,
snapc, snap_id, req_comp);
}
req = new AioZero(ictx, p->oid.name, p->objectno, p->offset, p->length,
snapc, req_comp);
}
r = req->send();
@ -3791,7 +3756,6 @@ reprotect_and_return_err:
}
snap_t snap_id;
::SnapContext snapc;
map<object_t,vector<ObjectExtent> > object_extents;
uint64_t buffer_ofs = 0;
{
@ -3799,7 +3763,6 @@ reprotect_and_return_err:
// pending async operation
RWLock::RLocker snap_locker(ictx->snap_lock);
snap_id = ictx->snap_id;
snapc = ictx->snapc;
// map
for (vector<pair<uint64_t,uint64_t> >::const_iterator p =
@ -3828,16 +3791,18 @@ reprotect_and_return_err:
c->read_buf_len = buffer_ofs;
c->read_bl = pbl;
for (map<object_t,vector<ObjectExtent> >::iterator p = object_extents.begin(); p != object_extents.end(); ++p) {
for (vector<ObjectExtent>::iterator q = p->second.begin(); q != p->second.end(); ++q) {
ldout(ictx->cct, 20) << " oid " << q->oid << " " << q->offset << "~" << q->length
<< " from " << q->buffer_extents << dendl;
for (map<object_t,vector<ObjectExtent> >::iterator p = object_extents.begin();
p != object_extents.end(); ++p) {
for (vector<ObjectExtent>::iterator q = p->second.begin();
q != p->second.end(); ++q) {
ldout(ictx->cct, 20) << " oid " << q->oid << " " << q->offset << "~"
<< q->length << " from " << q->buffer_extents
<< dendl;
C_AioRead *req_comp = new C_AioRead(ictx->cct, c);
AioRead *req = new AioRead(ictx, q->oid.name,
q->objectno, q->offset, q->length,
q->buffer_extents, snapc,
snap_id, true, req_comp, op_flags);
AioRead *req = new AioRead(ictx, q->oid.name, q->objectno, q->offset,
q->length, q->buffer_extents, snap_id, true,
req_comp, op_flags);
req_comp->set_req(req);
c->add_request();