Merge pull request #27704 from tchaikov/wip-denc-dump

denc: allow DencDumper to dump OOB buffer

Reviewed-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
Reviewed-by: Sage Weil <sage@redhat.com>
This commit is contained in:
Kefu Chai 2019-04-24 19:49:54 +08:00 committed by GitHub
commit b4040f09dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 32 deletions

View File

@ -968,7 +968,7 @@ public:
int validate_weightf(float weight) {
uint64_t iweight = weight * 0x10000;
if (iweight > std::numeric_limits<int>::max()) {
if (iweight > static_cast<uint64_t>(std::numeric_limits<int>::max())) {
return -EOVERFLOW;
}
return 0;

View File

@ -77,6 +77,8 @@ template<uint8_t S>
struct sha_digest_t;
using sha1_digest_t = sha_digest_t<20>;
template<typename T> class DencDumper;
namespace ceph {
template <class T>
@ -808,6 +810,7 @@ inline namespace v14_2_0 {
}
friend class list;
template<typename Type> friend class ::DencDumper;
public:
~contiguous_appender() {

View File

@ -41,6 +41,7 @@
#include "include/ceph_assert.h" // boost clobbers this
#include "include/intarith.h"
#include "include/int_types.h"
#include "include/scope_guard.h"
#include "buffer.h"
#include "byteorder.h"
@ -77,37 +78,75 @@ inline constexpr bool denc_supported = denc_traits<T>::supported;
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# define ENCODE_STR(x) #x
# define ENCODE_STRINGIFY(x) ENCODE_STR(x)
# define DENC_DUMP_PRE(Type) \
char *__denc_dump_pre = p.get_pos();
// this hackery with bits below is just to get a semi-reasonable
// distribution across time. it is somewhat exponential but not
// quite.
# define DENC_DUMP_POST(Type) \
do { \
static int i = 0; \
i++; \
int bits = 0; \
for (unsigned t = i; t; bits++) \
t &= t - 1; \
if (bits > 2) \
break; \
char fn[PATH_MAX]; \
::snprintf(fn, sizeof(fn), \
ENCODE_STRINGIFY(ENCODE_DUMP_PATH) "/%s__%d.%x", #Type, \
getpid(), i++); \
int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT|O_CLOEXEC, 0644); \
if (fd >= 0) { \
size_t len = p.get_pos() - __denc_dump_pre; \
int r = ::write(fd, __denc_dump_pre, len); \
(void)r; \
::close(fd); \
} \
} while (0)
template<typename T>
class DencDumper {
public:
DencDumper(const char* name,
ceph::bufferlist::contiguous_appender& appender)
: name{name},
appender{appender},
bl_offset{appender.bl.length()},
space_offset{space_size()},
start{appender.get_pos()}
{}
~DencDumper() {
if (do_sample()) {
dump();
}
}
private:
static bool do_sample() {
// this hackery with bits below is just to get a semi-reasonable
// distribution across time. it is somewhat exponential but not
// quite.
i++;
int bits = 0;
for (unsigned t = i; t; bits++)
t &= t - 1;
return bits <= 2;
}
size_t space_size() {
return appender.get_logical_offset() - appender.get_out_of_band_offset();
}
void dump() {
char fn[PATH_MAX];
::snprintf(fn, sizeof(fn),
ENCODE_STRINGIFY(ENCODE_DUMP_PATH) "/%s__%d.%x", name,
getpid(), i++);
int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT|O_CLOEXEC, 0644);
if (fd < 0) {
return;
}
auto close_fd = make_scope_guard([fd] { ::close(fd); });
if (auto bl_delta = appender.bl.length() - bl_offset; bl_delta > 0) {
ceph::bufferlist dump_bl;
appender.bl.copy(bl_offset + space_offset, bl_delta - space_offset, dump_bl);
const size_t space_len = space_size();
dump_bl.append(appender.get_pos() - space_len, space_len);
dump_bl.write_fd(fd);
} else {
size_t len = appender.get_pos() - start;
[[maybe_unused]] int r = ::write(fd, start, len);
}
}
const char* name;
ceph::bufferlist::contiguous_appender& appender;
const size_t bl_offset;
const size_t space_offset;
const char* start;
static int i;
};
template<typename T> int DencDumper<T>::i = 0;
# define DENC_DUMP_PRE(Type) \
DencDumper<Type> _denc_dumper{#Type, p};
#else
# define DENC_DUMP_PRE(Type)
# define DENC_DUMP_POST(Type)
#endif
@ -1700,7 +1739,6 @@ inline std::enable_if_t<traits::supported && !traits::featured> decode_nohead(
void encode(::ceph::buffer::list::contiguous_appender& p) const { \
DENC_DUMP_PRE(Type); \
_denc_friend(*this, p); \
DENC_DUMP_POST(Type); \
} \
void decode(::ceph::buffer::ptr::const_iterator& p) { \
_denc_friend(*this, p); \
@ -1718,7 +1756,6 @@ inline std::enable_if_t<traits::supported && !traits::featured> decode_nohead(
void encode(::ceph::buffer::list::contiguous_appender& p, uint64_t f) const { \
DENC_DUMP_PRE(Type); \
_denc_friend(*this, p, f); \
DENC_DUMP_POST(Type); \
} \
void decode(::ceph::buffer::ptr::const_iterator& p, uint64_t f=0) { \
_denc_friend(*this, p, f); \

View File

@ -863,7 +863,8 @@ CtPtr ProtocolV1::handle_message_data(char *buffer, int r) {
bufferptr bp = data_blp.get_current_ptr();
unsigned read_len = std::min(bp.length(), msg_left);
ceph_assert(read_len < std::numeric_limits<int>::max());
ceph_assert(read_len <
static_cast<unsigned>(std::numeric_limits<int>::max()));
data_blp.advance(read_len);
data.append(bp, 0, read_len);
msg_left -= read_len;

View File

@ -61,7 +61,6 @@ struct bluefs_fnode_t {
void encode(bufferlist::contiguous_appender& p) const {
DENC_DUMP_PRE(bluefs_fnode_t);
_denc_friend(*this, p);
DENC_DUMP_POST(bluefs_fnode_t);
}
void decode(buffer::ptr::const_iterator& p) {
_denc_friend(*this, p);