|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <string>
|
|
#include <rados/librados.h>
|
|
|
|
using namespace std;
|
|
|
|
/**
|
|
* This small program demonstrates the memory corruption of rados_read if a timeout happens
|
|
*/
|
|
|
|
const char *pool = "data";
|
|
const char *id = "admin";
|
|
const char *confFile = "/etc/ceph/ceph.conf";
|
|
int main(int argc, char **argv)
|
|
{
|
|
// First write the object we will use for demonstrating the memory corruption.
|
|
// You can also use any existing object for this problem to be reproduced.
|
|
const char* oid = "foo";
|
|
string content = "some random string with no special requirement";
|
|
|
|
rados_t cluster;
|
|
rados_ioctx_t ioctx;
|
|
rados_create(&cluster, id);
|
|
rados_conf_read_file(cluster, confFile);
|
|
rados_connect(cluster);
|
|
rados_ioctx_create(cluster, pool, &ioctx);
|
|
|
|
int err = rados_write(ioctx, oid, content.c_str(), content.length(), 0);
|
|
printf("result of writing %s: %d\n", oid, err);
|
|
|
|
rados_ioctx_destroy(ioctx);
|
|
rados_shutdown(cluster);
|
|
|
|
// create a new rados object here, since we have to set the timeout parameter before connect
|
|
rados_create(&cluster, id);
|
|
rados_conf_read_file(cluster, confFile);
|
|
rados_conf_set(cluster, "rados_osd_op_timeout", "0.00001"); // use any small value that will result in a timeout
|
|
rados_connect(cluster);
|
|
rados_ioctx_create(cluster, pool, &ioctx);
|
|
|
|
// then we show that the buffer is changed after rados_read returned with a timeout
|
|
for(int i=0; i<1000; i++) {
|
|
char *buf = new char[content.length()];
|
|
err = rados_read(ioctx, oid, buf, content.length(), 0);
|
|
printf("result of reading %s: %d\n", oid, err);
|
|
if(err == -110) {
|
|
int startIndex = 0;
|
|
// find the index until which librados already read the object before the timeout occurred
|
|
for(int b=0; b<32; b++) {
|
|
if(buf[b] == 0) {
|
|
startIndex = b;
|
|
printf("buffer filled with %d bytes\n", startIndex);
|
|
printf("value of byte at index %d: %d\n", startIndex, buf[startIndex]);
|
|
break;
|
|
}
|
|
}
|
|
// wait some time to give librados a change to do something
|
|
usleep(1000);
|
|
|
|
// then check if the buffer was changed after the call
|
|
if(buf[startIndex] != 0) {
|
|
printf("byte at index %d was changed after the call to: %d\n", startIndex, buf[startIndex]);
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
printf("no timeout on reading %s. Is rados_osd_op_timeout configured correctly?\n", oid);
|
|
}
|
|
}
|
|
|
|
// now try to crash it
|
|
for(int i=0; i<5000; i++) {
|
|
char *buf = new char[content.length()];
|
|
err = rados_read(ioctx, oid, buf, content.length(), 0);
|
|
delete[] buf;
|
|
printf(".");
|
|
fflush(stdout);
|
|
usleep(2);
|
|
}
|
|
|
|
rados_ioctx_destroy(ioctx);
|
|
rados_shutdown(cluster);
|
|
return 0;
|
|
}
|