sapling/eden/fuse/InodeDispatcher.h
Wez Furlong 174d0b9b0a eden: assign our own file handle numbers and track all file handles
Summary:
Previously we would simply report the raw pointer address to the kernel and
rely on it to return that same number to us as the file handle, and make sure
that it told us to shut down the handle when it was closed.

This meant that we had no real idea about which files were still open.

For our future live upgrade plans we need to be able to know this so that we
can transfer the appropriate information to our replacement process.

To facilitate this this diff implements a FileHandleMap class that will assign
file handle numbers and keep track of the instances.  The number assignment
strategy is the same as it used to be in the common case: we take the address
of the newly created instance and use that 64-bit number as the file handle
number.  However, in the future when we transfer the mapping to a new process,
we may experience a collision when subsequently opening a file handle.  To deal
with that, we have a bounded number of attempts to assign a random file handle
number.

We don't yet offer a means to iterate the map, but it would be trivial to
expose such an accessor when we're ready to use it.

Since we now keep track of these things via shared_ptr this changes the
appropriate portions of the fuse interface from unique_ptr to shared_ptr.

Reviewed By: simpkins

Differential Revision: D3602364

fbshipit-source-id: dd996339c2838225a2caeee9da16ef99a06c1e2b
2016-07-26 10:00:11 -07:00

137 lines
4.4 KiB
C++

/*
* Copyright (c) 2016, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#pragma once
#include <folly/FBString.h>
#include <folly/SharedMutex.h>
#include <mutex>
#include <shared_mutex>
#include <unordered_map>
#include "Dispatcher.h"
#include "InodeNameManager.h"
namespace facebook {
namespace eden {
namespace fusell {
class DirInode;
class FileInode;
class InodeBase;
class MountPoint;
/**
* A dispatcher that dispatches to Inode instances
*/
class InodeDispatcher : public Dispatcher {
std::shared_ptr<DirInode> root_;
std::unordered_map<fuse_ino_t, std::shared_ptr<InodeBase>> inodes_;
mutable folly::SharedMutex lock_;
// The MountPoint that owns this InodeDispatcher.
MountPoint* const mountPoint_;
public:
/*
* Create an InodeDispatcher, without a root node yet.
* setRootInode() must be called before using this dispatcher.
*/
explicit InodeDispatcher(MountPoint* mountPoint);
/*
* Create an InodeDispatcher using the specified root inode object.
*/
explicit InodeDispatcher(
MountPoint* mountPoint,
std::shared_ptr<DirInode> rootInode);
std::shared_ptr<InodeBase> getInode(fuse_ino_t, bool mustExist = true) const;
std::shared_ptr<InodeBase> lookupInode(fuse_ino_t) const;
std::shared_ptr<DirInode> getDirInode(fuse_ino_t,
bool mustExist = true) const;
std::shared_ptr<FileInode> getFileInode(fuse_ino_t,
bool mustExist = true) const;
/*
* Set the root inode.
*
* This method should be used to set the root inode on a default-constructed
* InodeDispatcher. It may only be called once, and it must be called before
* using the InodeDispatcher.
*/
void setRootInode(std::shared_ptr<DirInode> inode);
void recordInode(std::shared_ptr<InodeBase> inode);
void initConnection(fuse_conn_info& conn) override;
folly::Future<Attr> getattr(fuse_ino_t ino) override;
folly::Future<Attr> setattr(fuse_ino_t ino,
const struct stat& attr,
int to_set) override;
folly::Future<std::shared_ptr<DirHandle>> opendir(
fuse_ino_t ino,
const struct fuse_file_info& fi) override;
folly::Future<fuse_entry_param> lookup(
fuse_ino_t parent,
PathComponentPiece name) override;
/**
* Similar to lookup(), except this does not require an active FUSE request.
*/
folly::Future<std::shared_ptr<InodeBase>> lookupInodeBase(
fuse_ino_t parent,
PathComponentPiece name);
folly::Future<folly::Unit> forget(fuse_ino_t ino,
unsigned long nlookup) override;
folly::Future<std::shared_ptr<FileHandle>> open(
fuse_ino_t ino,
const struct fuse_file_info& fi) override;
folly::Future<std::string> readlink(fuse_ino_t ino) override;
folly::Future<fuse_entry_param> mknod(
fuse_ino_t parent,
PathComponentPiece name,
mode_t mode,
dev_t rdev) override;
folly::Future<fuse_entry_param>
mkdir(fuse_ino_t parent, PathComponentPiece name, mode_t mode) override;
folly::Future<folly::Unit> unlink(fuse_ino_t parent, PathComponentPiece name)
override;
folly::Future<folly::Unit> rmdir(fuse_ino_t parent, PathComponentPiece name)
override;
folly::Future<fuse_entry_param> symlink(
PathComponentPiece link,
fuse_ino_t parent,
PathComponentPiece name) override;
folly::Future<folly::Unit> rename(
fuse_ino_t parent,
PathComponentPiece name,
fuse_ino_t newparent,
PathComponentPiece newname) override;
folly::Future<fuse_entry_param> link(
fuse_ino_t ino,
fuse_ino_t newparent,
PathComponentPiece newname) override;
folly::Future<Dispatcher::Create> create(
fuse_ino_t parent,
PathComponentPiece name,
mode_t mode,
int flags) override;
folly::Future<std::string> getxattr(fuse_ino_t ino, folly::StringPiece name)
override;
folly::Future<std::vector<std::string>> listxattr(fuse_ino_t ino) override;
/** Compute a fuse_entry_param */
fuse_entry_param computeEntryParam(
const Dispatcher::Attr& attr,
std::shared_ptr<InodeNameManager::Node> node);
};
}
}
}