Simplify FileNode Cache. Remove the need for PlaceHolder.

- Store std::shared_ptr's directly, no need for PlaceHolder wrapper
 - Use std::forward_list to store shared_ptr's, the shared_ptr
   is guaranteed to be unique hence a set is an unnecessary overhead
 - Refactor code to use FileNode * instead of PlaceHolder *
This commit is contained in:
Ian Lee 2016-04-27 19:14:03 +01:00
parent ba9b25a1d2
commit af64702dd0
7 changed files with 55 additions and 80 deletions

View File

@ -95,10 +95,9 @@ std::shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
if (it != openFiles.end()) { if (it != openFiles.end()) {
// all the items in the set point to the same node.. so just use the // all the items in the set point to the same node.. so just use the
// first // first
return (*it->second.begin())->node; return it->second.front();
} else {
return std::shared_ptr<FileNode>();
} }
return std::shared_ptr<FileNode>();
} }
void EncFS_Context::renameNode(const char *from, const char *to) { void EncFS_Context::renameNode(const char *from, const char *to) {
@ -106,36 +105,27 @@ void EncFS_Context::renameNode(const char *from, const char *to) {
FileMap::iterator it = openFiles.find(std::string(from)); FileMap::iterator it = openFiles.find(std::string(from));
if (it != openFiles.end()) { if (it != openFiles.end()) {
std::set<Placeholder *> val = it->second; auto val = it->second;
openFiles.erase(it); openFiles.erase(it);
openFiles[std::string(to)] = val; openFiles[std::string(to)] = val;
} }
} }
std::shared_ptr<FileNode> EncFS_Context::getNode(void *pl) {
Placeholder *ph = (Placeholder *)pl; FileNode *EncFS_Context::putNode(const char *path,
return ph->node; std::shared_ptr<FileNode> &&node) {
Lock lock(contextMutex);
auto &list = openFiles[std::string(path)];
list.push_front(std::move(node));
return list.front().get();
} }
void *EncFS_Context::putNode(const char *path, void EncFS_Context::eraseNode(const char *path, FileNode *pl) {
const std::shared_ptr<FileNode> &node) {
Lock lock(contextMutex); Lock lock(contextMutex);
Placeholder *pl = new Placeholder(node);
openFiles[std::string(path)].insert(pl);
return (void *)pl;
}
void EncFS_Context::eraseNode(const char *path, void *pl) {
Lock lock(contextMutex);
Placeholder *ph = (Placeholder *)pl;
FileMap::iterator it = openFiles.find(std::string(path)); FileMap::iterator it = openFiles.find(std::string(path));
rAssert(it != openFiles.end()); rAssert(it != openFiles.end());
int rmCount = it->second.erase(ph); it->second.pop_front();
rAssert(rmCount == 1);
// if no more references to this file, remove the record all together // if no more references to this file, remove the record all together
if (it->second.empty()) { if (it->second.empty()) {
@ -145,8 +135,6 @@ void EncFS_Context::eraseNode(const char *path, void *pl) {
openFiles.erase(it); openFiles.erase(it);
storedName.assign(storedName.length(), '\0'); storedName.assign(storedName.length(), '\0');
} }
delete ph;
} }
} // namespace encfs } // namespace encfs

View File

@ -21,10 +21,10 @@
#ifndef _Context_incl_ #ifndef _Context_incl_
#define _Context_incl_ #define _Context_incl_
#include <forward_list>
#include <memory> #include <memory>
#include <pthread.h> #include <pthread.h>
#include <set> #include <set>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -42,15 +42,14 @@ class EncFS_Context {
EncFS_Context(); EncFS_Context();
~EncFS_Context(); ~EncFS_Context();
std::shared_ptr<FileNode> getNode(void *ptr);
std::shared_ptr<FileNode> lookupNode(const char *path); std::shared_ptr<FileNode> lookupNode(const char *path);
int getAndResetUsageCounter(); int getAndResetUsageCounter();
int openFileCount() const; int openFileCount() const;
void *putNode(const char *path, const std::shared_ptr<FileNode> &node); FileNode *putNode(const char *path, std::shared_ptr<FileNode> &&node);
void eraseNode(const char *path, void *placeholder); void eraseNode(const char *path, FileNode *fnode);
void renameNode(const char *oldName, const char *newName); void renameNode(const char *oldName, const char *newName);
@ -81,13 +80,9 @@ class EncFS_Context {
* release() is called. std::shared_ptr then does our reference counting for * release() is called. std::shared_ptr then does our reference counting for
* us. * us.
*/ */
struct Placeholder {
std::shared_ptr<FileNode> node;
Placeholder(const std::shared_ptr<FileNode> &ptr) : node(ptr) {} typedef std::unordered_map<
}; std::string, std::forward_list<std::shared_ptr<FileNode>>> FileMap;
typedef std::unordered_map<std::string, std::set<Placeholder *> > FileMap;
mutable pthread_mutex_t contextMutex; mutable pthread_mutex_t contextMutex;
FileMap openFiles; FileMap openFiles;

View File

@ -633,7 +633,6 @@ std::shared_ptr<FileNode> DirNode::renameNode(const char *from, const char *to,
std::shared_ptr<FileNode> DirNode::findOrCreate(const char *plainName) { std::shared_ptr<FileNode> DirNode::findOrCreate(const char *plainName) {
std::shared_ptr<FileNode> node; std::shared_ptr<FileNode> node;
if (ctx) node = ctx->lookupNode(plainName); if (ctx) node = ctx->lookupNode(plainName);
if (!node) { if (!node) {
uint64_t iv = 0; uint64_t iv = 0;
string cipherName = naming->encodePath(plainName, &iv); string cipherName = naming->encodePath(plainName, &iv);
@ -647,14 +646,11 @@ std::shared_ptr<FileNode> DirNode::findOrCreate(const char *plainName) {
return node; return node;
} }
std::shared_ptr<FileNode> DirNode::lookupNode(const char *plainName,
const char *requestor) { shared_ptr<FileNode> DirNode::lookupNode(const char *plainName,
(void)requestor; const char * /* requestor */) {
Lock _lock(mutex); Lock _lock(mutex);
return findOrCreate(plainName);
std::shared_ptr<FileNode> node = findOrCreate(plainName);
return node;
} }
/* /*

View File

@ -866,9 +866,8 @@ static void selectBlockMAC(int *macBytes, int *macRandBytes, bool forceMac) {
"performance but it also means [almost] any modifications or errors\n" "performance but it also means [almost] any modifications or errors\n"
"within a block will be caught and will cause a read error.")); "within a block will be caught and will cause a read error."));
} else { } else {
cout << "\n\n" cout << "\n\n" << _("You specified --require-macs. "
<< _("You specified --require-macs. " "Enabling block authentication code headers...")
"Enabling block authentication code headers...")
<< "\n\n"; << "\n\n";
addMAC = true; addMAC = true;
} }

View File

@ -122,24 +122,25 @@ static int withFileNode(const char *opName, const char *path,
if (!FSRoot) return res; if (!FSRoot) return res;
try { try {
std::shared_ptr<FileNode> fnode;
if (fi != NULL) auto do_op = [&FSRoot, opName, &op](FileNode *fnode) {
fnode = GET_FN(ctx, fi); rAssert(fnode != nullptr);
VLOG(1) << "op: " << opName << " : " << fnode->cipherName();
// check that we're not recursing into the mount point itself
if (FSRoot->touchesMountpoint(fnode->cipherName())) {
VLOG(1) << "op: " << opName << " error: Tried to touch mountpoint: '"
<< fnode->cipherName() << "'";
return -EIO;
}
return op(fnode);
};
if (fi != nullptr)
res = do_op(reinterpret_cast<FileNode *>(fi->fh));
else else
fnode = FSRoot->lookupNode(path, opName); res = do_op(FSRoot->lookupNode(path, opName).get());
rAssert(fnode.get() != NULL);
VLOG(1) << "op: " << opName << " : " << fnode->cipherName();
// check that we're not recursing into the mount point itself
if (FSRoot->touchesMountpoint(fnode->cipherName())) {
VLOG(1) << "op: " << opName << " error: Tried to touch mountpoint: '"
<< fnode->cipherName() << "'";
return res; // still -EIO
}
res = op(fnode.get());
if (res < 0) { if (res < 0) {
RLOG(DEBUG) << "op: " << opName << " error: " << strerror(-res); RLOG(DEBUG) << "op: " << opName << " error: " << strerror(-res);
} }
@ -522,7 +523,8 @@ int encfs_open(const char *path, struct fuse_file_info *file) {
<< file->flags; << file->flags;
if (res >= 0) { if (res >= 0) {
file->fh = (uintptr_t)ctx->putNode(path, fnode); file->fh =
reinterpret_cast<uintptr_t>(ctx->putNode(path, std::move(fnode)));
res = ESUCCESS; res = ESUCCESS;
} }
} }
@ -571,7 +573,7 @@ int encfs_release(const char *path, struct fuse_file_info *finfo) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
try { try {
ctx->eraseNode(path, (void *)(uintptr_t)finfo->fh); ctx->eraseNode(path, reinterpret_cast<FileNode *>(finfo->fh));
return ESUCCESS; return ESUCCESS;
} catch (encfs::Error &err) { } catch (encfs::Error &err) {
RLOG(ERROR) << "error caught in release: " << err.what(); RLOG(ERROR) << "error caught in release: " << err.what();

View File

@ -182,31 +182,27 @@ static int showInfo(int argc, char **argv) {
return EXIT_FAILURE; return EXIT_FAILURE;
case Config_V3: case Config_V3:
// xgroup(diag) // xgroup(diag)
cout << "\n" cout << "\n" << autosprintf(_("Version 3 configuration; "
<< autosprintf(_("Version 3 configuration; " "created by %s\n"),
"created by %s\n"), config->creator.c_str());
config->creator.c_str());
break; break;
case Config_V4: case Config_V4:
// xgroup(diag) // xgroup(diag)
cout << "\n" cout << "\n" << autosprintf(_("Version 4 configuration; "
<< autosprintf(_("Version 4 configuration; " "created by %s\n"),
"created by %s\n"), config->creator.c_str());
config->creator.c_str());
break; break;
case Config_V5: case Config_V5:
// xgroup(diag) // xgroup(diag)
cout << "\n" cout << "\n" << autosprintf(_("Version 5 configuration; "
<< autosprintf(_("Version 5 configuration; " "created by %s (revision %i)\n"),
"created by %s (revision %i)\n"), config->creator.c_str(), config->subVersion);
config->creator.c_str(), config->subVersion);
break; break;
case Config_V6: case Config_V6:
// xgroup(diag) // xgroup(diag)
cout << "\n" cout << "\n" << autosprintf(_("Version 6 configuration; "
<< autosprintf(_("Version 6 configuration; " "created by %s (revision %i)\n"),
"created by %s (revision %i)\n"), config->creator.c_str(), config->subVersion);
config->creator.c_str(), config->subVersion);
break; break;
} }

View File

@ -155,8 +155,7 @@ static void usage(const char *name) {
" encfs ~/.crypt ~/crypt\n" " encfs ~/.crypt ~/crypt\n"
"\n") "\n")
// xgroup(usage) // xgroup(usage)
<< _("For more information, see the man page encfs(1)") << "\n" << _("For more information, see the man page encfs(1)") << "\n" << endl;
<< endl;
} }
static void FuseUsage() { static void FuseUsage() {