From b7730c0a6b83df7cd65f8b73d006c666771ff0e3 Mon Sep 17 00:00:00 2001 From: Matt Benjamin Date: Fri, 8 Jan 2016 12:40:48 -0500 Subject: [PATCH] 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 --- src/include/rados/rgw_file.h | 6 +++++- src/rgw/rgw_file.cc | 13 ++++++++++--- src/rgw/rgw_file.h | 3 ++- src/test/librgw_file.cc | 6 ++++-- src/test/librgw_file_gp.cc | 2 +- src/test/librgw_file_nfsns.cc | 20 +++++++++++++++----- 6 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/include/rados/rgw_file.h b/src/include/rados/rgw_file.h index 040426ef7a0..98e005825a0 100644 --- a/src/include/rados/rgw_file.h +++ b/src/include/rados/rgw_file.h @@ -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 diff --git a/src/rgw/rgw_file.cc b/src/rgw/rgw_file.cc index 63b5c86badf..e56a094b4b0 100644 --- a/src/rgw/rgw_file.cc +++ b/src/rgw/rgw_file.cc @@ -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; } diff --git a/src/rgw/rgw_file.h b/src/rgw/rgw_file.h index a6ca509744b..7009bd559b0 100644 --- a/src/rgw/rgw_file.h +++ b/src/rgw/rgw_file.h @@ -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(); diff --git a/src/test/librgw_file.cc b/src/test/librgw_file.cc index 0af400cc208..949e2eaa923 100644 --- a/src/test/librgw_file.cc +++ b/src/test/librgw_file.cc @@ -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; diff --git a/src/test/librgw_file_gp.cc b/src/test/librgw_file_gp.cc index ed988e92f42..eab64a8aa81 100644 --- a/src/test/librgw_file_gp.cc +++ b/src/test/librgw_file_gp.cc @@ -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; diff --git a/src/test/librgw_file_nfsns.cc b/src/test/librgw_file_nfsns.cc index 4aada698ac2..e91e452af29 100644 --- a/src/test/librgw_file_nfsns.cc +++ b/src/test/librgw_file_nfsns.cc @@ -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;