ceph/src/librbd/AioRequest.h
Jason Dillaman 46515971ed 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>
2015-04-07 11:26:57 -04:00

294 lines
8.6 KiB
C++

// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#ifndef CEPH_LIBRBD_AIOREQUEST_H
#define CEPH_LIBRBD_AIOREQUEST_H
#include "include/int_types.h"
#include <map>
#include "common/snap_types.h"
#include "include/buffer.h"
#include "include/Context.h"
#include "include/rados/librados.hpp"
#include "librbd/ObjectMap.h"
namespace librbd {
struct AioCompletion;
struct ImageCtx;
class CopyupRequest;
/**
* This class represents an I/O operation to a single RBD data object.
* Its subclasses encapsulate logic for dealing with special cases
* for I/O due to layering.
*/
class AioRequest
{
public:
AioRequest(ImageCtx *ictx, const std::string &oid,
uint64_t objectno, uint64_t off, uint64_t len,
librados::snap_t snap_id,
Context *completion, bool hide_enoent);
virtual ~AioRequest();
void complete(int r);
virtual bool should_complete(int r) = 0;
virtual int send() = 0;
bool has_parent() const {
return !m_parent_extents.empty();
}
protected:
bool compute_parent_extents();
void read_from_parent(const vector<pair<uint64_t,uint64_t> >& image_extents,
bool block_completion);
ImageCtx *m_ictx;
std::string m_oid;
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;
};
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,
librados::snap_t snap_id, bool sparse,
Context *completion, int op_flags);
virtual ~AioRead() {}
virtual bool should_complete(int r);
virtual int send();
void guard_read();
ceph::bufferlist &data() {
return m_read_data;
}
std::map<uint64_t, uint64_t> m_ext_map;
friend class C_AioRead;
private:
vector<pair<uint64_t,uint64_t> > m_buffer_extents;
bool m_tried_parent;
bool m_sparse;
int m_op_flags;
/**
* Reads go through the following state machine to deal with
* layering:
*
* need copyup
* LIBRBD_AIO_READ_GUARD ---------------> LIBRBD_AIO_READ_COPYUP
* | |
* v |
* done <------------------------------------/
* ^
* |
* LIBRBD_AIO_READ_FLAT
*
* Reads start in LIBRBD_AIO_READ_GUARD or _FLAT, depending on
* whether there is a parent or not.
*/
enum read_state_d {
LIBRBD_AIO_READ_GUARD,
LIBRBD_AIO_READ_COPYUP,
LIBRBD_AIO_READ_FLAT
};
read_state_d m_state;
};
class AbstractWrite : public AioRequest {
public:
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();
private:
/**
* Writes go through the following state machine to deal with
* layering and the object map:
*
* <start>
* . |
* . |
* . \---> LIBRBD_AIO_WRITE_PRE
* . | |
* . . . . . . | . . . . | . . . . . . . . . . .
* . | -or- | .
* . | | v
* . | \----------------> LIBRBD_AIO_WRITE_FLAT . . .
* . | | .
* v v need copyup | .
* LIBRBD_AIO_WRITE_GUARD -----------> LIBRBD_AIO_WRITE_COPYUP | .
* . | ^ | | .
* . | | | | .
* . | \---------------------------/ | .
* . | | .
* . \-------------------\ /-------------------/ .
* . | | .
* . LIBRBD_AIO_WRITE_POST .
* . | .
* . v .
* . . . . . . . . . . . . . . > <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
* whether or not there is a parent overlap.
*/
enum write_state_d {
LIBRBD_AIO_WRITE_GUARD,
LIBRBD_AIO_WRITE_COPYUP,
LIBRBD_AIO_WRITE_FLAT,
LIBRBD_AIO_WRITE_PRE,
LIBRBD_AIO_WRITE_POST,
LIBRBD_AIO_WRITE_ERROR
};
protected:
write_state_d m_state;
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;
virtual void guard_write();
virtual void pre_object_map_update(uint8_t *new_state) = 0;
virtual bool post_object_map_update() {
return false;
}
private:
bool send_pre();
bool send_post();
void send_write();
void send_copyup();
};
class AioWrite : public AbstractWrite {
public:
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) {
}
virtual ~AioWrite() {}
void set_op_flags(int op_flags) {
m_op_flags = op_flags;
}
protected:
virtual void add_write_ops(librados::ObjectWriteOperation *wr);
virtual void pre_object_map_update(uint8_t *new_state) {
*new_state = OBJECT_EXISTS;
}
private:
ceph::bufferlist m_write_data;
int m_op_flags;
};
class AioRemove : public AbstractWrite {
public:
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() {}
protected:
virtual void add_write_ops(librados::ObjectWriteOperation *wr) {
if (has_parent()) {
wr->truncate(0);
} else {
wr->remove();
}
}
virtual void pre_object_map_update(uint8_t *new_state) {
if (has_parent()) {
m_object_state = OBJECT_EXISTS;
} else {
m_object_state = OBJECT_PENDING;
}
*new_state = m_object_state;
}
virtual bool post_object_map_update() {
if (m_object_state == OBJECT_EXISTS) {
return false;
}
return true;
}
virtual void guard_write() {
// do nothing to disable write guard
}
private:
uint8_t m_object_state;
};
class AioTruncate : public AbstractWrite {
public:
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() {}
protected:
virtual void add_write_ops(librados::ObjectWriteOperation *wr) {
wr->truncate(m_object_off);
}
virtual void pre_object_map_update(uint8_t *new_state) {
*new_state = OBJECT_EXISTS;
}
};
class AioZero : public AbstractWrite {
public:
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() {}
protected:
virtual void add_write_ops(librados::ObjectWriteOperation *wr) {
wr->zero(m_object_off, m_object_len);
}
virtual void pre_object_map_update(uint8_t *new_state) {
*new_state = OBJECT_EXISTS;
}
};
}
#endif