From 265730aa5a139752ee1e284470a5301edcb8438a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 27 Jun 2016 13:09:22 -0700 Subject: [PATCH] os/FuseStore: only flush if dirty No need to rewrite the object unless it was changed. This partially fixes truncate. Signed-off-by: Sage Weil --- qa/workunits/objectstore/test_fuse.sh | 4 + src/os/FuseStore.cc | 178 +++++++++++++++++++------- src/os/FuseStore.h | 22 +++- 3 files changed, 157 insertions(+), 47 deletions(-) diff --git a/qa/workunits/objectstore/test_fuse.sh b/qa/workunits/objectstore/test_fuse.sh index cbceb144dfb..e58a0cf0bb4 100755 --- a/qa/workunits/objectstore/test_fuse.sh +++ b/qa/workunits/objectstore/test_fuse.sh @@ -81,9 +81,13 @@ test ! -s $MNT/meta/all/#-1:7b3f43c4:::osd_superblock:0#/data echo asdfasdfasdf > $MNT/meta/all/#-1:7b3f43c4:::osd_superblock:0#/data test -s $MNT/meta/all/#-1:7b3f43c4:::osd_superblock:0#/data grep -q asdfasdfasdf $MNT/meta/all/#-1:7b3f43c4:::osd_superblock:0#/data +truncate --size 4 $MNT/meta/all/#-1:7b3f43c4:::osd_superblock:0#/data +stat --format=%s $MNT/meta/all/#-1:7b3f43c4:::osd_superblock:0#/data | grep -q ^4$ +expect_false grep -q asdfasdfasdf $MNT/meta/all/#-1:7b3f43c4:::osd_superblock:0#/data rm $MNT/meta/all/#-1:7b3f43c4:::osd_superblock:0#/data test ! -s $MNT/meta/all/#-1:7b3f43c4:::osd_superblock:0#/data + # create pg collection mkdir --mode 0003 $MNT/0.0_head cat $MNT/0.0_head/bitwise_hash_bits diff --git a/src/os/FuseStore.cc b/src/os/FuseStore.cc index 0c11154a882..fd9dc9a2165 100644 --- a/src/os/FuseStore.cc +++ b/src/os/FuseStore.cc @@ -33,12 +33,35 @@ struct fs_info { char *mountpoint; }; +int FuseStore::open_file(string p, struct fuse_file_info *fi, + std::function f) +{ + if (open_files.count(p)) { + OpenFile *o = open_files[p]; + fi->fh = reinterpret_cast(o); + ++o->ref; + return 0; + } + bufferlist bl; + int r = f(&bl); + if (r < 0) { + return r; + } + OpenFile *o = new OpenFile; + o->path = p; + o->bl.claim(bl); + open_files[p] = o; + fi->fh = reinterpret_cast(o); + ++o->ref; + return 0; +} + FuseStore::FuseStore(ObjectStore *s, string p) : store(s), mount_point(p), fuse_thread(this) { - info = new fs_info; + info = new fs_info(); } FuseStore::~FuseStore() @@ -205,6 +228,7 @@ static int parse_fn(const char *path, coll_t *cid, ghobject_t *oid, string *key, static int os_getattr(const char *path, struct stat *stbuf) { + dout(10) << __func__ << " " << path << dendl; coll_t cid; ghobject_t oid; string key; @@ -215,6 +239,7 @@ static int os_getattr(const char *path, struct stat *stbuf) fuse_context *fc = fuse_get_context(); FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); stbuf->st_size = 0; stbuf->st_uid = 0; @@ -354,6 +379,7 @@ static int os_readdir(const char *path, off_t offset, struct fuse_file_info *fi) { + dout(10) << __func__ << " " << path << " offset " << offset << dendl; coll_t cid; ghobject_t oid; string key; @@ -364,6 +390,7 @@ static int os_readdir(const char *path, fuse_context *fc = fuse_get_context(); FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); // we can't shift 32 bits or else off_t will go negative const int hash_shift = 31; @@ -513,6 +540,7 @@ static int os_readdir(const char *path, static int os_open(const char *path, struct fuse_file_info *fi) { + dout(10) << __func__ << " " << path << dendl; coll_t cid; ghobject_t oid; string key; @@ -523,6 +551,7 @@ static int os_open(const char *path, struct fuse_file_info *fi) fuse_context *fc = fuse_get_context(); FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); bufferlist *pbl = 0; switch (t) { @@ -595,10 +624,12 @@ static int os_open(const char *path, struct fuse_file_info *fi) case FN_OBJECT_DATA: { - pbl = new bufferlist; - int r = fs->store->read(cid, oid, 0, 0, *pbl); + int r = fs->open_file( + path, fi, + [&](bufferlist *pbl) { + return fs->store->read(cid, oid, 0, 0, *pbl); + }); if (r < 0) { - delete pbl; return r; } } @@ -606,48 +637,64 @@ static int os_open(const char *path, struct fuse_file_info *fi) case FN_OBJECT_ATTR_VAL: { - bufferptr bp; - int r = fs->store->getattr(cid, oid, key.c_str(), bp); + int r = fs->open_file( + path, fi, + [&](bufferlist *pbl) { + bufferptr bp; + int r = fs->store->getattr(cid, oid, key.c_str(), bp); + if (r < 0) + return r; + pbl->append(bp); + return 0; + }); if (r < 0) return r; - pbl = new bufferlist; - pbl->append(bp); } break; case FN_OBJECT_OMAP_VAL: { - set k; - k.insert(key); - map v; - int r = fs->store->omap_get_values(cid, oid, k, &v); + int r = fs->open_file( + path, fi, + [&](bufferlist *pbl) { + set k; + k.insert(key); + map v; + int r = fs->store->omap_get_values(cid, oid, k, &v); + if (r < 0) + return r; + *pbl = v[key]; + return 0; + }); if (r < 0) - return r; - pbl = new bufferlist; - *pbl = v[key]; + return r; } break; case FN_OBJECT_OMAP_HEADER: { - bufferlist bl; - int r = fs->store->omap_get_header(cid, oid, &bl); + int r = fs->open_file( + path, fi, + [&](bufferlist *pbl) { + return fs->store->omap_get_header(cid, oid, pbl); + }); if (r < 0) return r; - pbl = new bufferlist; - pbl->claim(bl); } break; } if (pbl) { - fi->fh = reinterpret_cast(pbl); + FuseStore::OpenFile *o = new FuseStore::OpenFile; + o->bl.claim(*pbl); + fi->fh = reinterpret_cast(o); } return 0; } static int os_mkdir(const char *path, mode_t mode) { + dout(10) << __func__ << " " << path << dendl; coll_t cid; ghobject_t oid; string key; @@ -658,6 +705,7 @@ static int os_mkdir(const char *path, mode_t mode) fuse_context *fc = fuse_get_context(); FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); ObjectStore::Transaction t; switch (f) { @@ -706,11 +754,13 @@ static int os_mkdir(const char *path, mode_t mode) static int os_chmod(const char *path, mode_t mode) { + dout(10) << __func__ << " " << path << dendl; return 0; } static int os_create(const char *path, mode_t mode, struct fuse_file_info *fi) { + dout(10) << __func__ << " " << path << dendl; coll_t cid; ghobject_t oid; string key; @@ -721,6 +771,7 @@ static int os_create(const char *path, mode_t mode, struct fuse_file_info *fi) fuse_context *fc = fuse_get_context(); FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); ObjectStore::Transaction t; bufferlist *pbl = 0; @@ -773,30 +824,46 @@ static int os_create(const char *path, mode_t mode, struct fuse_file_info *fi) } if (pbl) { - fi->fh = reinterpret_cast(pbl); + FuseStore::OpenFile *o = new FuseStore::OpenFile; + o->bl.claim(*pbl); + o->dirty = true; + fi->fh = reinterpret_cast(o); } return 0; } static int os_release(const char *path, struct fuse_file_info *fi) { - bufferlist *pbl = reinterpret_cast(fi->fh); - delete pbl; + dout(10) << __func__ << " " << path << dendl; + fuse_context *fc = fuse_get_context(); + FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); + FuseStore::OpenFile *o = reinterpret_cast(fi->fh); + if (--o->ref == 0) { + dout(10) << __func__ << " closing last " << o->path << dendl; + fs->open_files.erase(o->path); + delete o; + } return 0; } static int os_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { - bufferlist *pbl = reinterpret_cast(fi->fh); - if (!pbl) + dout(10) << __func__ << " " << path << " offset " << offset + << " size " << size << dendl; + fuse_context *fc = fuse_get_context(); + FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); + FuseStore::OpenFile *o = reinterpret_cast(fi->fh); + if (!o) return 0; - if (offset >= pbl->length()) + if (offset >= o->bl.length()) return 0; - if (offset + size > pbl->length()) - size = pbl->length() - offset; + if (offset + size > o->bl.length()) + size = o->bl.length() - offset; bufferlist r; - r.substr_of(*pbl, offset, size); + r.substr_of(o->bl, offset, size); memcpy(buf, r.c_str(), r.length()); return r.length(); } @@ -804,32 +871,39 @@ static int os_read(const char *path, char *buf, size_t size, off_t offset, static int os_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { - bufferlist *pbl = reinterpret_cast(fi->fh); - if (!pbl) + dout(10) << __func__ << " " << path << " offset " << offset + << " size " << size << dendl; + fuse_context *fc = fuse_get_context(); + FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); + FuseStore::OpenFile *o = reinterpret_cast(fi->fh); + if (!o) return 0; bufferlist final; if (offset) { - if (offset > pbl->length()) { - final.substr_of(*pbl, 0, offset); + if (offset > o->bl.length()) { + final.substr_of(o->bl, 0, offset); } else { - final.claim_append(*pbl); + final.claim_append(o->bl); size_t zlen = offset - final.length(); final.append_zero(zlen); } } final.append(buf, size); - if (offset + size < pbl->length()) { + if (offset + size < o->bl.length()) { bufferlist rest; - rest.substr_of(*pbl, offset + size, pbl->length() - offset - size); + rest.substr_of(o->bl, offset + size, o->bl.length() - offset - size); final.claim_append(rest); } - *pbl = final; + o->bl = final; + o->dirty = true; return size; } int os_flush(const char *path, struct fuse_file_info *fi) { + dout(10) << __func__ << " " << path << dendl; coll_t cid; ghobject_t oid; string key; @@ -840,32 +914,35 @@ int os_flush(const char *path, struct fuse_file_info *fi) fuse_context *fc = fuse_get_context(); FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); - bufferlist *pbl = reinterpret_cast(fi->fh); - if (!pbl) + FuseStore::OpenFile *o = reinterpret_cast(fi->fh); + if (!o) + return 0; + if (!o->dirty) return 0; ObjectStore::Transaction t; switch (f) { case FN_OBJECT_DATA: - t.write(cid, oid, 0, pbl->length(), *pbl); + t.write(cid, oid, 0, o->bl.length(), o->bl); break; case FN_OBJECT_ATTR_VAL: - t.setattr(cid, oid, key.c_str(), *pbl); + t.setattr(cid, oid, key.c_str(), o->bl); break; case FN_OBJECT_OMAP_VAL: { map aset; - aset[key] = *pbl; + aset[key] = o->bl; t.omap_setkeys(cid, oid, aset); break; } case FN_OBJECT_OMAP_HEADER: - t.omap_setheader(cid, oid, *pbl); + t.omap_setheader(cid, oid, o->bl); break; default: @@ -884,6 +961,7 @@ int os_flush(const char *path, struct fuse_file_info *fi) static int os_unlink(const char *path) { + dout(10) << __func__ << " " << path << dendl; coll_t cid; ghobject_t oid; string key; @@ -894,6 +972,7 @@ static int os_unlink(const char *path) fuse_context *fc = fuse_get_context(); FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); ObjectStore::Transaction t; @@ -947,6 +1026,7 @@ static int os_unlink(const char *path) static int os_truncate(const char *path, off_t size) { + dout(10) << __func__ << " " << path << " size " << size << dendl; coll_t cid; ghobject_t oid; string key; @@ -967,6 +1047,16 @@ static int os_truncate(const char *path, off_t size) fuse_context *fc = fuse_get_context(); FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); + + if (fs->open_files.count(path)) { + FuseStore::OpenFile *o = fs->open_files[path]; + if (o->bl.length() > size) { + bufferlist t; + t.substr_of(o->bl, 0, size); + o->bl.swap(t); + } + } ObjectStore::Transaction t; t.truncate(cid, oid, size); @@ -981,8 +1071,10 @@ static int os_truncate(const char *path, off_t size) static int os_statfs(const char *path, struct statvfs *stbuf) { + dout(10) << __func__ << " " << path << dendl; fuse_context *fc = fuse_get_context(); FuseStore *fs = static_cast(fc->private_data); + std::lock_guard l(fs->lock); struct store_statfs_t s; int r = fs->store->statfs(&s); diff --git a/src/os/FuseStore.h b/src/os/FuseStore.h index 2dc2f296473..bb9e59f5f45 100644 --- a/src/os/FuseStore.h +++ b/src/os/FuseStore.h @@ -5,17 +5,31 @@ #define CEPH_OS_FUSESTORE_H #include -#include "common/Thread.h" +#include +#include -using std::string; +#include "common/Thread.h" +#include "include/buffer.h" class ObjectStore; class FuseStore { public: ObjectStore *store; - string mount_point; + std::string mount_point; struct fs_info *info; + std::mutex lock; + + struct OpenFile { + std::string path; + bufferlist bl; + bool dirty = false; + int ref = 0; + }; + std::map open_files; + + int open_file(std::string p, struct fuse_file_info *fi, + std::function f); class FuseThread : public Thread { FuseStore *fs; @@ -27,7 +41,7 @@ public: } } fuse_thread; - FuseStore(ObjectStore *s, string p); + FuseStore(ObjectStore *s, std::string p); ~FuseStore(); int main();