eden: remove PassThru file handle usage

Summary:
`creat(2)` and `open(2)` could decide to create a PassThru file handle.

This diff removes that usage.  There is a TODO here around handling `O_EXCL` properly.
I'm punting this to a follow-up diff.

Reviewed By: bolinfest

Differential Revision: D3301387

fbshipit-source-id: d35104c536396e7fd064d786f3d5592ecfcbfecf
This commit is contained in:
Wez Furlong 2016-05-17 17:22:22 -07:00 committed by Facebook Github Bot 3
parent 25dd9997d9
commit 88c1b44aab
3 changed files with 46 additions and 52 deletions

View File

@ -169,7 +169,9 @@ void FileData::materialize(int open_flags, RelativePathPiece path) {
if (!file_) {
try {
// Test whether an overlay file exists by trying to open it.
file_ = overlay_->openFile(path, O_RDWR, 0600);
// O_NOFOLLOW because it never makes sense for the kernel to ask
// a fuse server to open a file that is a symlink to something else.
file_ = overlay_->openFile(path, O_RDWR | O_NOFOLLOW, 0600);
// since we have a pre-existing overlay file, we don't need the blob.
need_blob = false;
} catch (const std::system_error& err) {

View File

@ -13,7 +13,6 @@
#include "TreeEntryFileHandle.h"
#include "eden/fs/overlay/Overlay.h"
#include "eden/fs/store/LocalStore.h"
#include "eden/fuse/passthru/PassThruInodes.h"
using folly::Future;
using folly::StringPiece;
@ -110,39 +109,19 @@ AbsolutePath TreeEntryFileInode::getLocalPath() const {
folly::Future<fusell::FileHandle*> TreeEntryFileInode::open(
const struct fuse_file_info& fi) {
if (!entry_) {
auto localPath = getLocalPath();
auto fd = ::open(localPath.c_str(), fi.flags);
checkUnixError(fd);
return new fusell::PassThruFileHandle(fd, ino_);
}
auto data = getOrLoadData();
SCOPE_EXIT {
data.reset();
fileHandleDidClose();
};
data->materialize(
fi.flags,
fusell::InodeNameManager::get()->resolvePathToNode(getNodeId()));
switch (entry_->getFileType()) {
case FileType::REGULAR_FILE: {
auto data = getOrLoadData();
SCOPE_EXIT {
data.reset();
fileHandleDidClose();
};
data->materialize(
fi.flags,
fusell::InodeNameManager::get()->resolvePathToNode(getNodeId()));
return new TreeEntryFileHandle(
std::static_pointer_cast<TreeEntryFileInode>(shared_from_this()),
data,
fi.flags);
}
case FileType::SYMLINK:
// man 2 open says: ELOOP ... or O_NOFOLLOW was specified but pathname
// was a symbolic link.
// We shouldn't really be able to get here in any case.
folly::throwSystemErrorExplicit(ELOOP);
default:
// We really really should never be able to get here.
folly::throwSystemErrorExplicit(
EIO, "impossible filetype ", entry_->getFileType());
}
return new TreeEntryFileHandle(
std::static_pointer_cast<TreeEntryFileInode>(shared_from_this()),
data,
fi.flags);
}
Future<vector<string>> TreeEntryFileInode::listxattr() {

View File

@ -12,7 +12,6 @@
#include "TreeInodeDirHandle.h"
#include "eden/fs/overlay/Overlay.h"
#include "eden/fs/store/LocalStore.h"
#include "eden/fuse/passthru/PassThruInodes.h"
#include "eden/utils/PathFuncs.h"
namespace facebook {
@ -137,31 +136,45 @@ TreeInode::create(PathComponentPiece name, mode_t mode, int flags) {
// Ask the overlay manager to create it.
auto file = overlay_->openFile(targetname, O_CREAT | flags, mode);
// Discard the file handle and allow the FileData class to open it again.
// We'll need to figure out something nicer than this in a follow-on diff
// to make sure that O_EXCL|O_CREAT is working correctly.
file.close();
// Generate an inode number for this new entry.
auto node = fusell::InodeNameManager::get()->getNodeByName(ino_, name);
auto handle = std::make_unique<fusell::PassThruFileHandle>(
file.release(), node->getNodeId());
// build a corresponding TreeEntryFileInode
auto inode = std::make_shared<TreeEntryFileInode>(
node->getNodeId(),
std::static_pointer_cast<TreeInode>(shared_from_this()),
nullptr);
// Populate metadata.
auto handle_ptr =
handle.get(); // need to get this before move handle into the lambda.
return handle_ptr->getattr().then(
[ =, handle = std::move(handle) ](fusell::Dispatcher::Attr attr) mutable {
fusell::DirInode::CreateResult result;
fuse_file_info fi;
memset(&fi, 0, sizeof(fi));
result.inode = std::make_shared<TreeEntryFileInode>(
node->getNodeId(),
std::static_pointer_cast<TreeInode>(shared_from_this()),
nullptr);
// The kernel wants an open operation to return the inode,
// the file handle and some attribute information.
// Let's open a file handle now.
return inode->open(fi).then([=](fusell::FileHandle* handle_ptr) {
// Capture the handle into a unique_ptr so that we can ensure caleanup.
// This will be removed when we remove the naked pointers in a followup.
std::unique_ptr<fusell::FileHandle> handle(handle_ptr);
result.file = std::move(handle);
result.attr = attr;
result.node = node;
// Now that we have the file handle, let's look up the attributes.
return handle_ptr->getattr().then([ =, handle = std::move(handle) ](
fusell::Dispatcher::Attr attr) mutable {
fusell::DirInode::CreateResult result;
return result;
});
// Return all of the results back to the kernel.
result.inode = inode;
result.file = std::move(handle);
result.attr = attr;
result.node = node;
return result;
});
});
}
std::shared_ptr<LocalStore> TreeInode::getStore() const {