From fbfafb3eeea1b86bca4cbf84c4e3df84e35f29e0 Mon Sep 17 00:00:00 2001 From: Matt Benjamin Date: Thu, 12 Nov 2015 11:55:37 -0500 Subject: [PATCH] librgw: ok, make RGW vnodes cache Unix attrs Ganesa ULP needs to see a sane progression of attrs in the CREATE path. With this change shell actions like $ echo "hi" > /nfs41/mybucket/mom work as expected. Signed-off-by: Matt Benjamin --- src/rgw/rgw_file.cc | 99 ++++++++++++++++----------------------------- src/rgw/rgw_file.h | 53 +++++++++++++++++++++--- 2 files changed, 82 insertions(+), 70 deletions(-) diff --git a/src/rgw/rgw_file.cc b/src/rgw/rgw_file.cc index c2baf04af889e..537f9c06a97ed 100644 --- a/src/rgw/rgw_file.cc +++ b/src/rgw/rgw_file.cc @@ -35,13 +35,6 @@ const string RGWFileHandle::root_name = "/"; atomic RGWLibFS::fs_inst; - -#define RGW_RWXMODE (S_IRWXU | S_IRWXG | S_IRWXO) - -#define RGW_RWMODE (RGW_RWXMODE & \ - ~(S_IXUSR | S_IXGRP | S_IXOTH)) - - /* librgw */ extern "C" { @@ -144,22 +137,14 @@ int rgw_create(struct rgw_fs *rgw_fs, if (get<1>(fhr) & RGWFileHandle::FLAG_CREATE) { /* fill in stat data */ time_t now = time(0); - memset(st, 0, sizeof(struct stat)); - st->st_dev = fs->get_inst(); - st->st_ino = rgw_fh->get_fh()->fh_hk.object; // XXX - st->st_mode = RGW_RWMODE|S_IFREG; - st->st_nlink = 1; - st->st_uid = 0; // XXX - st->st_gid = 0; // XXX - st->st_size = 0; - st->st_blksize = 4096; - st->st_blocks = 0; - st->st_atim.tv_sec = now; - st->st_mtim.tv_sec = now; - st->st_ctim.tv_sec = now; + rgw_fh->get_stat()->st_atim.tv_sec = now; + rgw_fh->get_stat()->st_mtim.tv_sec = now; + rgw_fh->get_stat()->st_ctim.tv_sec = now; rgw_fh->open_for_create(); } + *st = *(rgw_fh->get_stat()); + struct rgw_file_handle *rfh = rgw_fh->get_fh(); *fh = rfh; @@ -377,39 +362,17 @@ int rgw_getattr(struct rgw_fs *rgw_fs, RGWFileHandle* rgw_fh = get_rgwfh(fh); - if (rgw_fh->is_root()) { - /* XXX do something */ - memset(st, 0, sizeof(struct stat)); - st->st_dev = fs->get_inst(); - st->st_ino = rgw_fh->get_fh()->fh_hk.object; // XXX - st->st_mode = RGW_RWXMODE|S_IFDIR; - st->st_nlink = 3; - st->st_uid = 0; // XXX - st->st_gid = 0; // XXX -#if 0 - /* XXX cluster create time? do we know that? */ - st->st_atim.tv_sec = req.mtime(); - st->st_mtim.tv_sec = req.mtime(); - st->st_ctim.tv_sec = req.ctime(); -#endif - } else if (rgw_fh->is_bucket()) { - /* bucket */ - /* fill in stat data */ - memset(st, 0, sizeof(struct stat)); - st->st_dev = fs->get_inst(); - st->st_ino = rgw_fh->get_fh()->fh_hk.object; // XXX - st->st_mode = RGW_RWXMODE|S_IFDIR; - st->st_nlink = 3; - st->st_uid = 0; // XXX - st->st_gid = 0; // XXX -#if 0 - /* XXX we can at least get creation_time */ - st->st_atim.tv_sec = req.mtime(); - st->st_mtim.tv_sec = req.mtime(); - st->st_ctim.tv_sec = req.ctime(); -#endif + if (rgw_fh->is_root() || + rgw_fh->is_bucket()) { + /* XXX nothing */ } else { /* object */ + + /* an object being created isn't expected to exist (if it does, + * we'll detect the conflict later */ + if (rgw_fh->creating()) + goto done; + const std::string bname = rgw_fh->bucket_name(); const std::string oname = rgw_fh->object_name(); @@ -419,25 +382,22 @@ int rgw_getattr(struct rgw_fs *rgw_fs, int rc = librgw.get_fe()->execute_req(&req); if ((rc != 0) || - (req.get_ret() != 0)) + (req.get_ret() != 0)) { + /* XXX EINVAL is likely illegal protocol return--if the object + * should but doesn't exist, it should probably be ENOENT */ return -EINVAL; + } /* fill in stat data */ - memset(st, 0, sizeof(struct stat)); - st->st_dev = fs->get_inst(); - st->st_ino = rgw_fh->get_fh()->fh_hk.object; // XXX - st->st_mode = RGW_RWMODE|S_IFREG; - st->st_nlink = 1; - st->st_uid = 0; // XXX - st->st_gid = 0; // XXX - st->st_size = req.size(); - st->st_blksize = 4096; - st->st_blocks = (st->st_size) / 512; - st->st_atim.tv_sec = req.mtime(); - st->st_mtim.tv_sec = req.mtime(); - st->st_ctim.tv_sec = req.ctime(); + rgw_fh->get_stat()->st_size = req.size(); + rgw_fh->get_stat()->st_blocks = (st->st_size) / 512; + rgw_fh->get_stat()->st_atim.tv_sec = req.mtime(); + rgw_fh->get_stat()->st_mtim.tv_sec = req.mtime(); + rgw_fh->get_stat()->st_ctim.tv_sec = req.ctime(); } +done: + *st = *(rgw_fh->get_stat()); return 0; } @@ -520,6 +480,8 @@ int rgw_readdir(struct rgw_fs *rgw_fs, RGWListBucketRequest req(cct, fs->get_user(), uri, rcb, cb_arg, offset); rc = librgw.get_fe()->execute_req(&req); + /* XXX update link count (incorrectly) */ + parent->get_stat()->st_nlink = 3 + *offset; } /* XXXX request MUST set this */ @@ -593,6 +555,11 @@ int rgw_write(struct rgw_fs *rgw_fs, int rc = librgw.get_fe()->execute_req(&req); + /* XXX move into request */ + ssize_t min_size = offset+length; + if (min_size > rgw_fh->get_stat()->st_size) + rgw_fh->get_stat()->st_size = min_size; + *bytes_written = (rc == 0) ? req.bytes_written : 0; return rc; @@ -701,6 +668,8 @@ int rgw_readv(struct rgw_fs *rgw_fs, int rc = librgw.get_fe()->execute_req(&req); + /* XXX update size (in request) */ + return rc; } diff --git a/src/rgw/rgw_file.h b/src/rgw/rgw_file.h index a11f4d6f88d35..de8a7135127ec 100644 --- a/src/rgw/rgw_file.h +++ b/src/rgw/rgw_file.h @@ -22,6 +22,13 @@ */ #include "include/assert.h" + +#define RGW_RWXMODE (S_IRWXU | S_IRWXG | S_IRWXO) + +#define RGW_RWMODE (RGW_RWXMODE & \ + ~(S_IXUSR | S_IXGRP | S_IXOTH)) + + namespace rgw { namespace bi = boost::intrusive; @@ -104,6 +111,7 @@ namespace rgw { RGWFHRef parent; /* const */ std::string name; /* XXX file or bucket name */ /* const */ fh_key fhk; + struct stat st; uint32_t flags; public: @@ -117,11 +125,21 @@ namespace rgw { friend class RGWLibFS; private: - RGWFileHandle(RGWLibFS* _fs) + RGWFileHandle(RGWLibFS* _fs, uint32_t fs_inst) : refcnt(1), fs(_fs), parent(nullptr), flags(FLAG_ROOT) { /* root */ fh.fh_type = RGW_FS_TYPE_DIRECTORY; + + /* partial Unix attrs */ + memset(&st, 0, sizeof(struct stat)); + st.st_dev = fs_inst; + st.st_mode = RGW_RWXMODE|S_IFDIR; + st.st_nlink = 3; + + st.st_uid = 0; // XXX + st.st_gid = 0; // XXX + /* pointer to self */ fh.fh_private = this; } @@ -131,13 +149,15 @@ namespace rgw { fh.fh_hk.bucket = XXH64(fsid.c_str(), fsid.length(), fh_key::seed); fh.fh_hk.object = XXH64(object_name.c_str(), object_name.length(), fh_key::seed); + /* fixup Unix attrs */ + st.st_ino = fh.fh_hk.object; fhk = fh.fh_hk; name = object_name; } public: - RGWFileHandle(RGWLibFS* fs, RGWFileHandle* _parent, const fh_key& _fhk, - const char *_name) + RGWFileHandle(RGWLibFS* fs, uint32_t fs_inst, RGWFileHandle* _parent, + const fh_key& _fhk, const char *_name) : parent(_parent), name(_name), fhk(_fhk), flags(FLAG_NONE) { fh.fh_type = parent->is_root() @@ -147,6 +167,27 @@ namespace rgw { fh_key fhk(parent->name, name); fh.fh_hk = fhk.fh_hk; /* XXX redundant in fh_hk */ + /* partial Unix attrs */ + memset(&st, 0, sizeof(struct stat)); + st.st_dev = fs_inst; + st.st_ino = fh.fh_hk.object; // XXX + + st.st_uid = 0; // XXX + st.st_gid = 0; // XXX + + switch (fh.fh_type) { + case RGW_FS_TYPE_DIRECTORY: + st.st_mode = RGW_RWXMODE|S_IFDIR; + st.st_nlink = 3; + break; + case RGW_FS_TYPE_FILE: + st.st_mode = RGW_RWMODE|S_IFREG; + st.st_nlink = 1; + st.st_blksize = 4096; + default: + break; + } + /* pointer to self */ fh.fh_private = this; } @@ -157,6 +198,8 @@ namespace rgw { struct rgw_file_handle* get_fh() { return &fh; } + struct stat *get_stat() { return &st; } + const std::string& bucket_name() const { if (is_root()) return root_name; @@ -280,7 +323,7 @@ namespace rgw { public: RGWLibFS(CephContext* _cct, const char *_uid, const char *_user_id, const char* _key) - : cct(_cct), root_fh(this), uid(_uid), key(_user_id, _key) { + : cct(_cct), root_fh(this, get_inst()), uid(_uid), key(_user_id, _key) { /* no bucket may be named rgw_fs_inst-(.*) */ fsid = RGWFileHandle::root_name + "rgw_fs_inst-" + @@ -323,7 +366,7 @@ namespace rgw { RGWFileHandle::FHCache::FLAG_LOCK); /* LATCHED */ if (! fh) { - fh = new RGWFileHandle(this, parent, fhk, name); + fh = new RGWFileHandle(this, get_inst(), parent, fhk, name); intrusive_ptr_add_ref(fh); /* sentinel ref */ fh_cache.insert_latched(fh, lat, RGWFileHandle::FHCache::FLAG_NONE); -- 2.39.5