Skip to content

Commit

Permalink
rgw_file: introduce rgw_lookup type hints
Browse files Browse the repository at this point in the history
The new type hints optimize object type deduction, when the
rgw_lookup is called from an rgw_readdir callback.

Fixes: http://tracker.ceph.com/issues/19623

Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
  • Loading branch information
mattbenjamin committed Apr 13, 2017
1 parent e8f1f4a commit 2e66c7a
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 15 deletions.
13 changes: 10 additions & 3 deletions src/include/rados/rgw_file.h
Expand Up @@ -27,7 +27,7 @@ extern "C" {

#define LIBRGW_FILE_VER_MAJOR 1
#define LIBRGW_FILE_VER_MINOR 1
#define LIBRGW_FILE_VER_EXTRA 2
#define LIBRGW_FILE_VER_EXTRA 3

#define LIBRGW_FILE_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra)
#define LIBRGW_FILE_VERSION_CODE LIBRGW_FILE_VERSION(LIBRGW_FILE_VER_MAJOR, LIBRGW_FILE_VER_MINOR, LIBRGW_FILE_VER_EXTRA)
Expand All @@ -36,7 +36,8 @@ extern "C" {
* object types
*/
enum rgw_fh_type {
RGW_FS_TYPE_FILE = 0,
RGW_FS_TYPE_NIL = 0,
RGW_FS_TYPE_FILE,
RGW_FS_TYPE_DIRECTORY,
};

Expand Down Expand Up @@ -92,6 +93,11 @@ void rgwfile_version(int *major, int *minor, int *extra);
#define RGW_LOOKUP_FLAG_NONE 0x0000
#define RGW_LOOKUP_FLAG_CREATE 0x0001
#define RGW_LOOKUP_FLAG_RCB 0x0002 /* readdir callback hint */
#define RGW_LOOKUP_FLAG_DIR 0x0004
#define RGW_LOOKUP_FLAG_FILE 0x0008

#define RGW_LOOKUP_TYPE_FLAGS \
(RGW_LOOKUP_FLAG_DIR|RGW_LOOKUP_FLAG_FILE)

int rgw_lookup(struct rgw_fs *rgw_fs,
struct rgw_file_handle *parent_fh, const char *path,
Expand Down Expand Up @@ -200,7 +206,8 @@ int rgw_unlink(struct rgw_fs *rgw_fs,
/*
read directory content
*/
typedef bool (*rgw_readdir_cb)(const char *name, void *arg, uint64_t offset);
typedef bool (*rgw_readdir_cb)(const char *name, void *arg, uint64_t offset,
uint32_t flags);

#define RGW_READDIR_FLAG_NONE 0x0000
#define RGW_READDIR_FLAG_DOTDOT 0x0001 /* send dot names */
Expand Down
21 changes: 17 additions & 4 deletions src/rgw/rgw_file.cc
Expand Up @@ -94,6 +94,7 @@ namespace rgw {

LookupFHResult RGWLibFS::stat_leaf(RGWFileHandle* parent,
const char *path,
enum rgw_fh_type type,
uint32_t flags)
{
/* find either-of <object_name>, <object_name/>, only one of
Expand All @@ -118,6 +119,10 @@ namespace rgw {
switch (ix) {
case 0:
{
/* type hint */
if (type == RGW_FS_TYPE_DIRECTORY)
continue;

RGWStatObjRequest req(cct, get_user(),
parent->bucket_name(), obj_path,
RGWStatObjRequest::FLAG_NONE);
Expand All @@ -143,6 +148,10 @@ namespace rgw {
case 1:
{
/* try dir form */
/* type hint */
if (type == RGW_FS_TYPE_FILE)
continue;

obj_path += "/";
RGWStatObjRequest req(cct, get_user(),
parent->bucket_name(), obj_path,
Expand Down Expand Up @@ -174,7 +183,8 @@ namespace rgw {
if ((rc == 0) &&
(req.get_ret() == 0)) {
if (req.matched) {
// we need rgw object's key name equal to file name, if not return NULL
/* we need rgw object's key name equal to file name, if
* not return NULL */
if ((flags & RGWFileHandle::FLAG_EXACT_MATCH) &&
!req.exact_matched) {
lsubdout(get_context(), rgw, 15)
Expand Down Expand Up @@ -912,8 +922,8 @@ namespace rgw {
if ((*offset == 0) &&
(flags & RGW_READDIR_FLAG_DOTDOT)) {
/* send '.' and '..' with their NFS-defined offsets */
rcb(".", cb_arg, 1);
rcb("..", cb_arg, 2);
rcb(".", cb_arg, 1, RGW_LOOKUP_FLAG_DIR);
rcb("..", cb_arg, 2, RGW_LOOKUP_FLAG_DIR);
}

if (is_root()) {
Expand Down Expand Up @@ -1484,10 +1494,13 @@ int rgw_lookup(struct rgw_fs *rgw_fs,
}
} else {
/* lookup in a readdir callback */
enum rgw_fh_type fh_type = fh_type_of(flags);

uint32_t sl_flags = (flags & RGW_LOOKUP_FLAG_RCB)
? RGWFileHandle::FLAG_NONE
: RGWFileHandle::FLAG_EXACT_MATCH;
fhr = fs->stat_leaf(parent, path, sl_flags);

fhr = fs->stat_leaf(parent, path, fh_type, sl_flags);
if (! get<0>(fhr)) {
if (! (flags & RGW_LOOKUP_FLAG_CREATE))
return -ENOENT;
Expand Down
26 changes: 23 additions & 3 deletions src/rgw/rgw_file.h
Expand Up @@ -685,6 +685,22 @@ namespace rgw {
return static_cast<RGWFileHandle*>(fh->fh_private);
}

static inline enum rgw_fh_type fh_type_of(uint32_t flags) {
enum rgw_fh_type fh_type;
switch(flags & RGW_LOOKUP_TYPE_FLAGS)
{
case RGW_LOOKUP_FLAG_DIR:
fh_type = RGW_FS_TYPE_DIRECTORY;
break;
case RGW_LOOKUP_FLAG_FILE:
fh_type = RGW_FS_TYPE_FILE;
break;
default:
fh_type = RGW_FS_TYPE_NIL;
};
return fh_type;
}

typedef std::tuple<RGWFileHandle*, uint32_t> LookupFHResult;
typedef std::tuple<RGWFileHandle*, int> MkObjResult;

Expand Down Expand Up @@ -1014,7 +1030,8 @@ namespace rgw {
const char *path, uint32_t flags);

LookupFHResult stat_leaf(RGWFileHandle* parent, const char *path,
uint32_t flags);
enum rgw_fh_type type = RGW_FS_TYPE_NIL,
uint32_t flags = RGWFileHandle::FLAG_NONE);

int read(RGWFileHandle* rgw_fh, uint64_t offset, size_t length,
size_t* bytes_read, void* buffer, uint32_t flags);
Expand Down Expand Up @@ -1199,7 +1216,7 @@ class RGWListBucketsRequest : public RGWLibRequest,
/* update traversal cache */
rgw_fh->add_marker(off, rgw_obj_key{marker.data(), ""},
RGW_FS_TYPE_DIRECTORY);
rcb(name.data(), cb_arg, off);
rcb(name.data(), cb_arg, off, RGW_LOOKUP_FLAG_DIR);
return 0;
}

Expand Down Expand Up @@ -1286,7 +1303,10 @@ class RGWListBucketsRequest : public RGWLibRequest,
*offset = off;
/* update traversal cache */
rgw_fh->add_marker(off, marker, type);
rcb(name.data(), cb_arg, off); // XXX has to be legit C-style string
rcb(name.data(), cb_arg, off,
(type == RGW_FS_TYPE_DIRECTORY) ?
RGW_LOOKUP_FLAG_DIR :
RGW_LOOKUP_FLAG_FILE);
return 0;
}

Expand Down
6 changes: 4 additions & 2 deletions src/test/librgw_file.cc
Expand Up @@ -73,7 +73,8 @@ TEST(LibRGW, GETATTR_ROOT) {
}

extern "C" {
static bool r1_cb(const char* name, void *arg, uint64_t offset) {
static bool r1_cb(const char* name, void *arg, uint64_t offset,
uint32_t flags) {
// don't need arg--it would point to fids1
fids1.push_back(fid_type(name, offset, nullptr /* handle */));
return true; /* XXX ? */
Expand Down Expand Up @@ -135,7 +136,8 @@ TEST(LibRGW, GETATTR_BUCKETS) {
}

extern "C" {
static bool r2_cb(const char* name, void *arg, uint64_t offset) {
static bool r2_cb(const char* name, void *arg, uint64_t offset,
uint32_t flags) {
std::vector<fid_type>& obj_vector = *(static_cast<std::vector<fid_type>*>(arg));
obj_vector.push_back(fid_type(name, offset, nullptr));
return true; /* XXX ? */
Expand Down
3 changes: 2 additions & 1 deletion src/test/librgw_file_gp.cc
Expand Up @@ -192,7 +192,8 @@ TEST(LibRGW, LOOKUP_BUCKET) {
}

extern "C" {
static bool r2_cb(const char* name, void *arg, uint64_t offset) {
static bool r2_cb(const char* name, void *arg, uint64_t offset,
uint32_t flags) {
// don't need arg--it would point to fids
fids.push_back(fid_type(name, offset, nullptr));
return true; /* XXX ? */
Expand Down
8 changes: 6 additions & 2 deletions src/test/librgw_file_nfsns.cc
Expand Up @@ -853,14 +853,16 @@ TEST(LibRGW, RELEASE_DIRS1) {
}

extern "C" {
static bool r1_cb(const char* name, void *arg, uint64_t offset) {
static bool r1_cb(const char* name, void *arg, uint64_t offset,
uint32_t flags) {
struct rgw_file_handle* parent_fh
= static_cast<struct rgw_file_handle*>(arg);
RGWFileHandle* rgw_fh = get_rgwfh(parent_fh);
lsubdout(cct, rgw, 10) << __func__
<< " bucket=" << rgw_fh->bucket_name()
<< " dir=" << rgw_fh->full_object_name()
<< " called back name=" << name
<< " flags=" << flags
<< dendl;
string name_str{name};
if (! ((name_str == ".") ||
Expand Down Expand Up @@ -1008,14 +1010,16 @@ TEST(LibRGW, MARKER1_SETUP_OBJECTS)
}

extern "C" {
static bool r2_cb(const char* name, void *arg, uint64_t offset) {
static bool r2_cb(const char* name, void *arg, uint64_t offset,
uint32_t flags) {
dirent_vec& dvec =
*(static_cast<dirent_vec*>(arg));
lsubdout(cct, rgw, 10) << __func__
<< " bucket=" << bucket_name
<< " dir=" << marker_dir
<< " iv count=" << dvec.count
<< " called back name=" << name
<< " flags=" << flags
<< dendl;
string name_str{name};
if (! ((name_str == ".") ||
Expand Down

0 comments on commit 2e66c7a

Please sign in to comment.