librgw: conditionally send '.' and '..' (rgw_readdir)

Ganesha traditionally does not expect them, but they may be needed
when bypassing the MDCACHE (2.4).

Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
This commit is contained in:
Matt Benjamin 2016-01-08 12:40:48 -05:00
parent 5e75c1834a
commit b7730c0a6b
6 changed files with 37 additions and 13 deletions

View File

@ -152,9 +152,13 @@ int rgw_unlink(struct rgw_fs *rgw_fs,
*/
typedef bool (*rgw_readdir_cb)(const char *name, void *arg, uint64_t offset);
#define RGW_READDIR_FLAG_NONE 0x0000
#define RGW_READDIR_FLAG_DOTDOT 0x0001 /* send dot names */
int rgw_readdir(struct rgw_fs *rgw_fs,
struct rgw_file_handle *parent_fh, uint64_t *offset,
rgw_readdir_cb rcb, void *cb_arg, bool *eof);
rgw_readdir_cb rcb, void *cb_arg, bool *eof,
uint32_t flags);
/* XXX (get|set)attr mask bits */
#define RGW_SETATTR_MODE 1

View File

@ -210,7 +210,7 @@ namespace rgw {
} /* RGWFileHandle::reclaim */
int RGWFileHandle::readdir(rgw_readdir_cb rcb, void *cb_arg, uint64_t *offset,
bool *eof)
bool *eof, uint32_t flags)
{
using event = RGWLibFS::event;
int rc = 0;
@ -220,6 +220,12 @@ namespace rgw {
(void) clock_gettime(CLOCK_MONOTONIC_COARSE, &now); /* !LOCKED */
if (flags & RGW_READDIR_FLAG_DOTDOT) {
/* send '.' and '..' with their NFS-defined offsets */
rcb(".", cb_arg, 1);
rcb("..", cb_arg, 2);
}
if (is_root()) {
RGWListBucketsRequest req(cct, fs->get_user(), this, rcb, cb_arg,
offset);
@ -957,14 +963,15 @@ int rgw_close(struct rgw_fs *rgw_fs,
int rgw_readdir(struct rgw_fs *rgw_fs,
struct rgw_file_handle *parent_fh, uint64_t *offset,
rgw_readdir_cb rcb, void *cb_arg, bool *eof)
rgw_readdir_cb rcb, void *cb_arg, bool *eof,
uint32_t flags)
{
RGWFileHandle* parent = get_rgwfh(parent_fh);
if (! parent) {
/* bad parent */
return -EINVAL;
}
int rc = parent->readdir(rcb, cb_arg, offset, eof);
int rc = parent->readdir(rcb, cb_arg, offset, eof, flags);
return -rc;
}

View File

@ -417,7 +417,8 @@ namespace rgw {
return EPERM;
}
int readdir(rgw_readdir_cb rcb, void *cb_arg, uint64_t *offset, bool *eof);
int readdir(rgw_readdir_cb rcb, void *cb_arg, uint64_t *offset, bool *eof,
uint32_t flags);
int write(uint64_t off, size_t len, size_t *nbytes, void *buffer);
int write_finish();
int close();

View File

@ -97,7 +97,8 @@ TEST(LibRGW, LIST_BUCKETS) {
bool eof = false;
uint64_t offset = 0;
int ret = rgw_readdir(fs, fs->root_fh, &offset, r1_cb, &fids1, &eof);
int ret = rgw_readdir(fs, fs->root_fh, &offset, r1_cb, &fids1, &eof,
RGW_READDIR_FLAG_NONE);
for (auto& fid : fids1) {
std::cout << "fname: " << get<0>(fid) << " fid: " << get<1>(fid)
<< std::endl;
@ -170,7 +171,8 @@ TEST(LibRGW, LIST_OBJECTS) {
bool eof = false;
uint64_t offset = 0;
int ret = rgw_readdir(fs, bucket_fh, &offset, r2_cb, &obj_vector, &eof);
int ret = rgw_readdir(fs, bucket_fh, &offset, r2_cb, &obj_vector, &eof,
RGW_READDIR_FLAG_NONE);
for (auto& obj : obj_vector) {
std::cout << "fname: " << get<0>(obj) << " fid: " << get<1>(obj)
<< std::endl;

View File

@ -208,7 +208,7 @@ TEST(LibRGW, LIST_OBJECTS) {
bool eof = false;
uint64_t offset = 0;
int ret = rgw_readdir(fs, bucket_fh, &offset, r2_cb, &fids,
&eof);
&eof, RGW_READDIR_FLAG_NONE);
for (auto& fid : fids) {
std::cout << "fname: " << get<0>(fid) << " fid: " << get<1>(fid)
<< std::endl;

View File

@ -167,8 +167,12 @@ extern "C" {
<< " dir=" << rgw_fh->full_object_name()
<< " called back name=" << name
<< dendl;
obj_stack.push(
obj_rec{name, nullptr, parent_fh, nullptr});
string name_str{name};
if (! ((name_str == ".") ||
(name_str == ".."))) {
obj_stack.push(
obj_rec{std::move(name_str), nullptr, parent_fh, nullptr});
}
return true; /* XXX */
}
}
@ -222,7 +226,8 @@ TEST(LibRGW, ENUMERATE1) {
<< " object_name: " << elt.rgw_fh->object_name()
<< " full_name: " << elt.rgw_fh->full_object_name()
<< dendl;
rc = rgw_readdir(fs, elt.fh, &offset, r1_cb, elt.fh, &eof);
rc = rgw_readdir(fs, elt.fh, &offset, r1_cb, elt.fh, &eof,
RGW_READDIR_FLAG_DOTDOT);
elt.state.readdir = true;
ASSERT_EQ(rc, 0);
// ASSERT_TRUE(eof); // XXXX working incorrectly w/single readdir
@ -324,7 +329,11 @@ extern "C" {
<< " iv count=" << dvec.count
<< " called back name=" << name
<< dendl;
dvec.obj_names.push_back(dirent_t{name, offset});
string name_str{name};
if (! ((name_str == ".") ||
(name_str == ".."))) {
dvec.obj_names.push_back(dirent_t{std::move(name_str), offset});
}
return true; /* XXX */
}
}
@ -347,7 +356,8 @@ TEST(LibRGW, MARKER1_READDIR)
do {
ASSERT_TRUE(dvec.count <= max_iterations);
int ret = rgw_readdir(fs, marker_fh, &offset, r2_cb, &dvec, &eof);
int ret = rgw_readdir(fs, marker_fh, &offset, r2_cb, &dvec, &eof,
RGW_READDIR_FLAG_DOTDOT);
ASSERT_EQ(ret, 0);
ASSERT_EQ(offset, get<1>(dvec.obj_names.back())); // cookie check
++dvec.count;