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 <mbenjamin@redhat.com>
This commit is contained in:
Matt Benjamin 2015-11-12 11:55:37 -05:00
parent 5f4ef7edff
commit fbfafb3eee
2 changed files with 82 additions and 70 deletions

View File

@ -35,13 +35,6 @@ const string RGWFileHandle::root_name = "/";
atomic<uint32_t> 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;
}

View File

@ -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);