Skip to content

Commit

Permalink
Merge branch 'wip-16002' of https://github.com/gregsfortytwo/ceph int…
Browse files Browse the repository at this point in the history
…o greg-fs-testing

#9769
  • Loading branch information
gregsfortytwo committed Jun 28, 2016
2 parents 3f60a67 + 9ec6e7f commit d2a7358
Show file tree
Hide file tree
Showing 7 changed files with 428 additions and 6 deletions.
4 changes: 3 additions & 1 deletion qa/workunits/osdc/stress_objectcacher.sh
Expand Up @@ -14,7 +14,7 @@ do
do
for MAX_DIRTY in 0 25165824
do
ceph_test_objectcacher_stress --ops $OPS --percent-read $READS --delay-ns $DELAY --objects $OBJECTS --max-op-size $OP_SIZE --client-oc-max-dirty $MAX_DIRTY > /dev/null 2>&1
ceph_test_objectcacher_stress --ops $OPS --percent-read $READS --delay-ns $DELAY --objects $OBJECTS --max-op-size $OP_SIZE --client-oc-max-dirty $MAX_DIRTY --stress-test > /dev/null 2>&1
done
done
done
Expand All @@ -23,4 +23,6 @@ do
done
done

ceph_test_objectcacher_stress --correctness-test > /dev/null 2>&1

echo OK
19 changes: 19 additions & 0 deletions src/osd/osd_types.h
Expand Up @@ -3031,6 +3031,25 @@ ostream& operator<<(ostream& out, const osd_peer_stat_t &stat);
// -----------------------------------------

class ObjectExtent {
/**
* ObjectExtents are used for specifying IO behavior against RADOS
* objects when one is using the ObjectCacher.
*
* To use this in a real system, *every member* must be filled
* out correctly. In particular, make sure to initialize the
* oloc correctly, as its default values are deliberate poison
* and will cause internal ObjectCacher asserts.
*
* Similarly, your buffer_extents vector *must* specify a total
* size equal to your length. If the buffer_extents inadvertently
* contain less space than the length member specifies, you
* will get unintelligible asserts deep in the ObjectCacher.
*
* If you are trying to do testing and don't care about actual
* RADOS function, the simplest thing to do is to initialize
* the ObjectExtent (truncate_size can be 0), create a single entry
* in buffer_extents matching the length, and set oloc.pool to 0.
*/
public:
object_t oid; // object id
uint64_t objectno;
Expand Down
3 changes: 1 addition & 2 deletions src/osdc/ObjectCacher.cc
Expand Up @@ -833,7 +833,6 @@ void ObjectCacher::bh_read_finish(int64_t poolid, sobject_t oid,
if (bh->error < 0)
err = bh->error;

loff_t oldpos = opos;
opos = bh->end();

if (r == -ENOENT) {
Expand All @@ -853,7 +852,7 @@ void ObjectCacher::bh_read_finish(int64_t poolid, sobject_t oid,
mark_error(bh);
} else {
bh->bl.substr_of(bl,
oldpos-bh->start(),
bh->start() - start,
bh->length());
mark_clean(bh);
}
Expand Down
4 changes: 3 additions & 1 deletion src/test/Makefile.am
Expand Up @@ -473,7 +473,8 @@ endif

ceph_test_objectcacher_stress_SOURCES = \
test/osdc/object_cacher_stress.cc \
test/osdc/FakeWriteback.cc
test/osdc/FakeWriteback.cc \
test/osdc/MemWriteback.cc
ceph_test_objectcacher_stress_LDADD = $(LIBOSDC) $(CEPH_GLOBAL)
bin_DEBUGPROGRAMS += ceph_test_objectcacher_stress

Expand Down Expand Up @@ -510,6 +511,7 @@ noinst_HEADERS += \
test/ObjectMap/KeyValueDBMemory.h \
test/omap_bench.h \
test/osdc/FakeWriteback.h \
test/osdc/MemWriteback.h \
test/osd/Object.h \
test/osd/RadosModel.h \
test/osd/TestOpStat.h \
Expand Down
163 changes: 163 additions & 0 deletions src/test/osdc/MemWriteback.cc
@@ -0,0 +1,163 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#include <errno.h>
#include <time.h>

#include <thread>
#include "common/debug.h"
#include "common/Cond.h"
#include "common/Finisher.h"
#include "common/Mutex.h"
#include "include/assert.h"
#include "common/ceph_time.h"

#include "MemWriteback.h"

#define dout_subsys ceph_subsys_objectcacher
#undef dout_prefix
#define dout_prefix *_dout << "MemWriteback(" << this << ") "

class C_DelayRead : public Context {
MemWriteback *wb;
CephContext *m_cct;
Context *m_con;
ceph::timespan m_delay;
Mutex *m_lock;
object_t m_oid;
uint64_t m_off;
uint64_t m_len;
bufferlist *m_bl;

public:
C_DelayRead(MemWriteback *mwb, CephContext *cct, Context *c, Mutex *lock,
const object_t& oid, uint64_t off, uint64_t len, bufferlist *pbl,
uint64_t delay_ns=0)
: wb(mwb), m_cct(cct), m_con(c),
m_delay(delay_ns * std::chrono::nanoseconds(1)),
m_lock(lock), m_oid(oid), m_off(off), m_len(len), m_bl(pbl) {}
void finish(int r) {
std::this_thread::sleep_for(m_delay);
m_lock->Lock();
r = wb->read_object_data(m_oid, m_off, m_len, m_bl);
if (m_con)
m_con->complete(r);
m_lock->Unlock();
}
};

class C_DelayWrite : public Context {
MemWriteback *wb;
CephContext *m_cct;
Context *m_con;
ceph::timespan m_delay;
Mutex *m_lock;
object_t m_oid;
uint64_t m_off;
uint64_t m_len;
const bufferlist& m_bl;

public:
C_DelayWrite(MemWriteback *mwb, CephContext *cct, Context *c, Mutex *lock,
const object_t& oid, uint64_t off, uint64_t len,
const bufferlist& bl, uint64_t delay_ns=0)
: wb(mwb), m_cct(cct), m_con(c),
m_delay(delay_ns * std::chrono::nanoseconds(1)),
m_lock(lock), m_oid(oid), m_off(off), m_len(len), m_bl(bl) {}
void finish(int r) {
std::this_thread::sleep_for(m_delay);
m_lock->Lock();
wb->write_object_data(m_oid, m_off, m_len, m_bl);
if (m_con)
m_con->complete(r);
m_lock->Unlock();
}
};

MemWriteback::MemWriteback(CephContext *cct, Mutex *lock, uint64_t delay_ns)
: m_cct(cct), m_lock(lock), m_delay_ns(delay_ns)
{
m_finisher = new Finisher(cct);
m_finisher->start();
}

MemWriteback::~MemWriteback()
{
m_finisher->stop();
delete m_finisher;
}

void MemWriteback::read(const object_t& oid, uint64_t object_no,
const object_locator_t& oloc,
uint64_t off, uint64_t len, snapid_t snapid,
bufferlist *pbl, uint64_t trunc_size,
__u32 trunc_seq, int op_flags, Context *onfinish)
{
assert(snapid == CEPH_NOSNAP);
C_DelayRead *wrapper = new C_DelayRead(this, m_cct, onfinish, m_lock, oid,
off, len, pbl, m_delay_ns);
m_finisher->queue(wrapper, len);
}

ceph_tid_t MemWriteback::write(const object_t& oid,
const object_locator_t& oloc,
uint64_t off, uint64_t len,
const SnapContext& snapc,
const bufferlist &bl, ceph::real_time mtime,
uint64_t trunc_size, __u32 trunc_seq,
ceph_tid_t journal_tid, Context *oncommit)
{
assert(snapc.seq == 0);
C_DelayWrite *wrapper = new C_DelayWrite(this, m_cct, oncommit, m_lock, oid,
off, len, bl, m_delay_ns);
m_finisher->queue(wrapper, 0);
return m_tid.inc();
}

void MemWriteback::write_object_data(const object_t& oid, uint64_t off, uint64_t len,
const bufferlist& data_bl)
{
dout(1) << "writing " << oid << " " << off << "~" << len << dendl;
assert(len == data_bl.length());
bufferlist& obj_bl = object_data[oid];
bufferlist new_obj_bl;
// ensure size, or set it if new object
if (off + len > obj_bl.length()) {
obj_bl.append_zero(off + len - obj_bl.length());
}

// beginning
new_obj_bl.substr_of(obj_bl, 0, off);
// overwritten bit
new_obj_bl.append(data_bl);
// tail bit
bufferlist tmp;
tmp.substr_of(obj_bl, off+len, obj_bl.length()-(off+len));
new_obj_bl.append(tmp);
obj_bl.swap(new_obj_bl);
dout(1) << oid << " final size " << obj_bl.length() << dendl;
}

int MemWriteback::read_object_data(const object_t& oid, uint64_t off, uint64_t len,
bufferlist *data_bl)
{
dout(1) << "reading " << oid << " " << off << "~" << len << dendl;
auto obj_i = object_data.find(oid);
if (obj_i == object_data.end()) {
dout(1) << oid << "DNE!" << dendl;
return -ENOENT;
}

const bufferlist& obj_bl = obj_i->second;
dout(1) << "reading " << oid << " from total size " << obj_bl.length() << dendl;

uint64_t read_len = MIN(len, obj_bl.length()-off);
data_bl->substr_of(obj_bl, off, read_len);
return 0;
}

bool MemWriteback::may_copy_on_write(const object_t&, uint64_t, uint64_t,
snapid_t)
{
return false;
}
49 changes: 49 additions & 0 deletions src/test/osdc/MemWriteback.h
@@ -0,0 +1,49 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#ifndef CEPH_TEST_OSDC_MEMWRITEBACK_H
#define CEPH_TEST_OSDC_MEMWRITEBACK_H

#include "include/atomic.h"
#include "include/Context.h"
#include "include/types.h"
#include "osd/osd_types.h"
#include "osdc/WritebackHandler.h"

class Finisher;
class Mutex;

class MemWriteback : public WritebackHandler {
public:
MemWriteback(CephContext *cct, Mutex *lock, uint64_t delay_ns);
virtual ~MemWriteback();

virtual void read(const object_t& oid, uint64_t object_no,
const object_locator_t& oloc, uint64_t off, uint64_t len,
snapid_t snapid, bufferlist *pbl, uint64_t trunc_size,
__u32 trunc_seq, int op_flags, Context *onfinish);

virtual ceph_tid_t write(const object_t& oid, const object_locator_t& oloc,
uint64_t off, uint64_t len,
const SnapContext& snapc, const bufferlist &bl,
ceph::real_time mtime, uint64_t trunc_size,
__u32 trunc_seq, ceph_tid_t journal_tid,
Context *oncommit);

using WritebackHandler::write;

virtual bool may_copy_on_write(const object_t&, uint64_t, uint64_t,
snapid_t);
void write_object_data(const object_t& oid, uint64_t off, uint64_t len,
const bufferlist& data_bl);
int read_object_data(const object_t& oid, uint64_t off, uint64_t len,
bufferlist *data_bl);
private:
std::map<object_t, bufferlist> object_data;
CephContext *m_cct;
Mutex *m_lock;
uint64_t m_delay_ns;
atomic_t m_tid;
Finisher *m_finisher;
};

#endif

0 comments on commit d2a7358

Please sign in to comment.