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() {
}
}
- 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);
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
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;
}
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;
}
// 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);
-
- uint64_t image_overlap = 0;
- r = m_ictx->get_parent_overlap(m_snap_id, &image_overlap);
- if (r < 0) {
- assert(0 == "FIXME");
+ 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 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;
}
}
}
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.
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();
}
}
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:
}
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)) {
/** 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()
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;
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;
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();
}
case LIBRBD_AIO_WRITE_ERROR:
assert(r < 0);
lderr(m_ictx->cct) << "WRITE_ERROR: " << cpp_strerror(r)
- << dendl;
+ << dendl;
break;
default:
}
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);
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();
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;
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() {}
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
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
* . |
* . \---> LIBRBD_AIO_WRITE_PRE
* . | |
- * . . . . . . | . . . . | . . . . . . . . . . .
+ * . . . . . . | . . . . | . . . . . . . . . . .
* . | -or- | .
* . | | v
* . | \----------------> LIBRBD_AIO_WRITE_FLAT . . .
* . 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
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;
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) {
}
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() {}
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() {}
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() {}
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;
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
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) {
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;
}
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);
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);
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);
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();
}
snap_t snap_id;
- ::SnapContext snapc;
map<object_t,vector<ObjectExtent> > object_extents;
uint64_t buffer_ofs = 0;
{
// 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 =
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();