]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/FuseStore: only flush if dirty 10723/head
authorSage Weil <sage@redhat.com>
Mon, 27 Jun 2016 20:09:22 +0000 (13:09 -0700)
committerSage Weil <sage@redhat.com>
Wed, 7 Sep 2016 22:14:16 +0000 (18:14 -0400)
No need to rewrite the object unless it was changed.

This partially fixes truncate.

Signed-off-by: Sage Weil <sage@redhat.com>
qa/workunits/objectstore/test_fuse.sh
src/os/FuseStore.cc
src/os/FuseStore.h

index cbceb144dfbae56f91dad264753c994a60d3bb03..e58a0cf0bb4cef5b9d23ce96dbe6c989d776e453 100755 (executable)
@@ -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
index 0c11154a88288215a9d962375572c4b50065b977..fd9dc9a2165ccbfbee8d1e5fd46c21547639f4f7 100644 (file)
@@ -33,12 +33,35 @@ struct fs_info {
   char *mountpoint;
 };
 
+int FuseStore::open_file(string p, struct fuse_file_info *fi,
+                        std::function<int(bufferlist *bl)> f)
+{
+  if (open_files.count(p)) {
+    OpenFile *o = open_files[p];
+    fi->fh = reinterpret_cast<uint64_t>(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<uint64_t>(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<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> 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<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> 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<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> 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<string> k;
-      k.insert(key);
-      map<string,bufferlist> v;
-      int r = fs->store->omap_get_values(cid, oid, k, &v);
+      int r = fs->open_file(
+       path, fi,
+       [&](bufferlist *pbl) {
+         set<string> k;
+         k.insert(key);
+         map<string,bufferlist> 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<uint64_t>(pbl);
+    FuseStore::OpenFile *o = new FuseStore::OpenFile;
+    o->bl.claim(*pbl);
+    fi->fh = reinterpret_cast<uint64_t>(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<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> 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<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> 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<uint64_t>(pbl);
+    FuseStore::OpenFile *o = new FuseStore::OpenFile;
+    o->bl.claim(*pbl);
+    o->dirty = true;
+    fi->fh = reinterpret_cast<uint64_t>(o);
   }
   return 0;
 }
 
 static int os_release(const char *path, struct fuse_file_info *fi)
 {
-  bufferlist *pbl = reinterpret_cast<bufferlist*>(fi->fh);
-  delete pbl;
+  dout(10) << __func__ << " " << path << dendl;
+  fuse_context *fc = fuse_get_context();
+  FuseStore *fs = static_cast<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> l(fs->lock);
+  FuseStore::OpenFile *o = reinterpret_cast<FuseStore::OpenFile*>(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<bufferlist*>(fi->fh);
-  if (!pbl)
+  dout(10) << __func__ << " " << path << " offset " << offset
+          << " size " << size << dendl;
+  fuse_context *fc = fuse_get_context();
+  FuseStore *fs = static_cast<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> l(fs->lock);
+  FuseStore::OpenFile *o = reinterpret_cast<FuseStore::OpenFile*>(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<bufferlist*>(fi->fh);
-  if (!pbl)
+  dout(10) << __func__ << " " << path << " offset " << offset
+          << " size " << size << dendl;
+  fuse_context *fc = fuse_get_context();
+  FuseStore *fs = static_cast<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> l(fs->lock);
+  FuseStore::OpenFile *o = reinterpret_cast<FuseStore::OpenFile*>(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<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> l(fs->lock);
 
-  bufferlist *pbl = reinterpret_cast<bufferlist*>(fi->fh);
-  if (!pbl)
+  FuseStore::OpenFile *o = reinterpret_cast<FuseStore::OpenFile*>(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<string,bufferlist> 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<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> 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<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> 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<FuseStore*>(fc->private_data);
+  std::lock_guard<std::mutex> l(fs->lock);
 
   struct store_statfs_t s;
   int r = fs->store->statfs(&s);
index 2dc2f2964738d4f95e0a695f38e684bd6597a642..bb9e59f5f45915c93f338f1139a5e98eff9ec646 100644 (file)
@@ -5,17 +5,31 @@
 #define CEPH_OS_FUSESTORE_H
 
 #include <string>
-#include "common/Thread.h"
+#include <map>
+#include <mutex>
 
-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<std::string,OpenFile*> open_files;
+
+  int open_file(std::string p, struct fuse_file_info *fi,
+               std::function<int(bufferlist *bl)> 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();