mirror of
https://github.com/ceph/ceph
synced 2025-02-16 07:17:21 +00:00
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:
parent
1c381b3ca8
commit
46515971ed
@ -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);
|
||||
|
@ -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() {}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user