mirror of
https://github.com/ceph/ceph
synced 2025-01-31 07:22:56 +00:00
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 <sage@redhat.com>
This commit is contained in:
parent
b6870a618b
commit
265730aa5a
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user