Skip to content

Commit

Permalink
Merge pull request #39324 from rzarzynski/wip-librados-nul-objname-na…
Browse files Browse the repository at this point in the history
…utilus

nautilus: librados, tests: allow to list objects with the NUL character in names

Reviewed-by: J. Eric Ivancich <ivancich@redhat.com>
  • Loading branch information
yuriw committed Mar 1, 2021
2 parents b0dbec5 + b71bb4d commit ead1cd5
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 12 deletions.
28 changes: 27 additions & 1 deletion src/include/rados/librados.h
Expand Up @@ -220,7 +220,7 @@ typedef void *rados_ioctx_t;
*
* An iterator for listing the objects in a pool.
* Used with rados_nobjects_list_open(),
* rados_nobjects_list_next(), and
* rados_nobjects_list_next(), rados_nobjects_list_next2(), and
* rados_nobjects_list_close().
*/
typedef void *rados_list_ctx_t;
Expand Down Expand Up @@ -1135,6 +1135,32 @@ CEPH_RADOS_API int rados_nobjects_list_next(rados_list_ctx_t ctx,
const char **key,
const char **nspace);

/**
* Get the next object name, locator and their sizes in the pool
*
* The sizes allow to list objects with \0 (the NUL character)
* in .e.g *entry. Is is unusual see such object names but a bug
* in a client has risen the need to handle them as well.
* *entry and *key are valid until next call to rados_nobjects_list_*
*
* @param ctx iterator marking where you are in the listing
* @param entry where to store the name of the entry
* @param key where to store the object locator (set to NULL to ignore)
* @param nspace where to store the object namespace (set to NULL to ignore)
* @param entry_size where to store the size of name of the entry
* @param key_size where to store the size of object locator (set to NULL to ignore)
* @param nspace_size where to store the size of object namespace (set to NULL to ignore)
* @returns 0 on success, negative error code on failure
* @returns -ENOENT when there are no more objects to list
*/
CEPH_RADOS_API int rados_nobjects_list_next2(rados_list_ctx_t ctx,
const char **entry,
const char **key,
const char **nspace,
size_t *entry_size,
size_t *key_size,
size_t *nspace_size);

/**
* Close the object listing handle.
*
Expand Down
33 changes: 29 additions & 4 deletions src/librados/librados_c.cc
Expand Up @@ -2104,6 +2104,22 @@ LIBRADOS_C_API_BASE_DEFAULT(rados_nobjects_list_get_pg_hash_position);
extern "C" int _rados_nobjects_list_next(rados_list_ctx_t listctx, const char **entry, const char **key, const char **nspace)
{
tracepoint(librados, rados_nobjects_list_next_enter, listctx);
uint32_t retval = rados_nobjects_list_next2(listctx, entry, key, nspace, NULL, NULL, NULL);
tracepoint(librados, rados_nobjects_list_next_exit, 0, *entry, key, nspace);
return retval;
}
LIBRADOS_C_API_BASE_DEFAULT(rados_nobjects_list_next);

extern "C" int _rados_nobjects_list_next2(
rados_list_ctx_t listctx,
const char **entry,
const char **key,
const char **nspace,
size_t *entry_size,
size_t *key_size,
size_t *nspace_size)
{
tracepoint(librados, rados_nobjects_list_next2_enter, listctx);
librados::ObjListCtx *lh = (librados::ObjListCtx *)listctx;
Objecter::NListContext *h = lh->nlc;

Expand All @@ -2115,11 +2131,11 @@ extern "C" int _rados_nobjects_list_next(rados_list_ctx_t listctx, const char **
if (h->list.empty()) {
int ret = lh->ctx->nlist(lh->nlc, RADOS_LIST_MAX_ENTRIES);
if (ret < 0) {
tracepoint(librados, rados_nobjects_list_next_exit, ret, NULL, NULL, NULL);
tracepoint(librados, rados_nobjects_list_next2_exit, ret, NULL, NULL, NULL, NULL, NULL, NULL);
return ret;
}
if (h->list.empty()) {
tracepoint(librados, rados_nobjects_list_next_exit, -ENOENT, NULL, NULL, NULL);
tracepoint(librados, rados_nobjects_list_next2_exit, -ENOENT, NULL, NULL, NULL, NULL, NULL, NULL);
return -ENOENT;
}
}
Expand All @@ -2134,10 +2150,19 @@ extern "C" int _rados_nobjects_list_next(rados_list_ctx_t listctx, const char **
}
if (nspace)
*nspace = h->list.front().nspace.c_str();
tracepoint(librados, rados_nobjects_list_next_exit, 0, *entry, key, nspace);

if (entry_size)
*entry_size = h->list.front().oid.size();
if (key_size)
*key_size = h->list.front().locator.size();
if (nspace_size)
*nspace_size = h->list.front().nspace.size();

tracepoint(librados, rados_nobjects_list_next2_exit, 0, entry, key, nspace,
entry_size, key_size, nspace_size);
return 0;
}
LIBRADOS_C_API_BASE_DEFAULT(rados_nobjects_list_next);
LIBRADOS_C_API_BASE_DEFAULT(rados_nobjects_list_next2);


/*
Expand Down
12 changes: 7 additions & 5 deletions src/librados/librados_cxx.cc
Expand Up @@ -755,22 +755,24 @@ void librados::NObjectIteratorImpl::set_filter(const bufferlist &bl)
void librados::NObjectIteratorImpl::get_next()
{
const char *entry, *key, *nspace;
size_t entry_size, key_size, nspace_size;
if (ctx->nlc->at_end())
return;
int ret = rados_nobjects_list_next(ctx.get(), &entry, &key, &nspace);
int ret = rados_nobjects_list_next2(ctx.get(), &entry, &key, &nspace,
&entry_size, &key_size, &nspace_size);
if (ret == -ENOENT) {
return;
}
else if (ret) {
throw std::system_error(-ret, std::system_category(),
"rados_nobjects_list_next");
"rados_nobjects_list_next2");
}

if (cur_obj.impl == NULL)
cur_obj.impl = new ListObjectImpl();
cur_obj.impl->nspace = nspace;
cur_obj.impl->oid = entry;
cur_obj.impl->locator = key ? key : string();
cur_obj.impl->nspace = string{nspace, nspace_size};
cur_obj.impl->oid = string{entry, entry_size};
cur_obj.impl->locator = key ? string(key, key_size) : string();
}

uint32_t librados::NObjectIteratorImpl::get_pg_hash_position() const
Expand Down
17 changes: 17 additions & 0 deletions src/test/librados/list.cc
Expand Up @@ -38,6 +38,23 @@ TEST_F(LibRadosList, ListObjects) {
rados_nobjects_list_close(ctx);
}

TEST_F(LibRadosList, ListObjectsZeroInName) {
char buf[128];
memset(buf, 0xcc, sizeof(buf));
ASSERT_EQ(0, rados_write(ioctx, "foo\0bar", buf, sizeof(buf), 0));
rados_list_ctx_t ctx;
ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
const char *entry;
size_t entry_size;
bool foundit = false;
while (rados_nobjects_list_next2(ctx, &entry, NULL, NULL,
&entry_size, NULL, NULL) != -ENOENT) {
foundit = true;
ASSERT_EQ(std::string(entry, entry_size), "foo\0bar");
}
ASSERT_TRUE(foundit);
rados_nobjects_list_close(ctx);
}

static void check_list(
std::set<std::string>& myset,
Expand Down
4 changes: 2 additions & 2 deletions src/tools/scratchtool.c
Expand Up @@ -291,8 +291,8 @@ static int testrados(void)
r = rados_nobjects_list_open(io_ctx, &h);
printf("rados_nobjects_list_open = %d, h = %p\n", r, h);
const char *poolname;
while (rados_nobjects_list_next(h, &poolname, NULL, NULL) == 0)
printf("rados_nobjects_list_next got object '%s'\n", poolname);
while (rados_nobjects_list_next2(h, &poolname, NULL, NULL, NULL, NULL, NULL) == 0)
printf("rados_nobjects_list_next2 got object '%s'\n", poolname);
rados_nobjects_list_close(h);

/* stat */
Expand Down
26 changes: 26 additions & 0 deletions src/tracing/librados.tp
Expand Up @@ -1846,6 +1846,32 @@ TRACEPOINT_EVENT(librados, rados_nobjects_list_next_exit,
)
)

TRACEPOINT_EVENT(librados, rados_nobjects_list_next2_enter,
TP_ARGS(
rados_list_ctx_t, listctx),
TP_FIELDS(
ctf_integer_hex(rados_list_ctx_t, listctx, listctx)
)
)

TRACEPOINT_EVENT(librados, rados_nobjects_list_next2_exit,
TP_ARGS(
int, retval,
const char* const*, entry,
const char* const*, key,
const char* const*, nspace,
const size_t*, entry_size,
const size_t*, key_size,
const size_t*, nspace_size),
TP_FIELDS(
ctf_integer(int, retval, retval)
ceph_ctf_sequencep(char, entry, entry, size_t, entry_size)
ceph_ctf_sequencep(char, key, key, size_t, key_size)
ceph_ctf_sequencep(char, nspace, nspace, size_t, nspace_size)
)
)


TRACEPOINT_EVENT(librados, rados_objects_list_open_enter,
TP_ARGS(
rados_ioctx_t, ioctx),
Expand Down

0 comments on commit ead1cd5

Please sign in to comment.