sapling/eden/fs/fuse/FuseChannel.h
Wez Furlong 467c417ccb re-organize the fuse Channel and Session code
Summary:
The higher level goal is to make it easier to deal
with the graceful restart scenario.

This diff removes the SessionDeleter class and effectively renames
the Channel class to FuseChannel.  The FuseChannel represents
the channel to the kernel; it can be constructed from a fuse
device descriptor that has been obtained either from the privhelper
at mount time, or from the graceful restart procedure.  Importantly
for graceful restart, it is possible to move the fuse device
descriptor out of the FuseChannel so that it can be transferred
to a new eden process.

The graceful restart procedure requires a bit more control over
the lifecycle of the fuse event loop so this diff also takes over
managing the thread pool for the worker threads.  The threads
are owned by the MountPoint class which continues to be responsible
for starting and stopping the fuse session and notifying EdenServer
when it has finished.  A nice side effect of this change is that
we can remove a couple of inelegant aspects of the integration;
the stack size env var stuff and the redundant extra thread
to wait for the loop to finish.

I opted to expose the dispatcher ops struct via an `extern` to
simplify the code in the MountPoint class and avoid adding special
interfaces for passing the ops around; they're constant anyway
so this doesn't feel especially egregious.

Reviewed By: bolinfest

Differential Revision: D5751521

fbshipit-source-id: 5ba4fff48f3efb31a809adfc7787555711f649c9
2017-09-08 19:25:34 -07:00

107 lines
3.1 KiB
C++

/*
* Copyright (c) 2016-present, 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/File.h>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>
#include "eden/fs/fuse/fuse_headers.h"
#include "eden/fs/utils/PathFuncs.h"
namespace facebook {
namespace eden {
namespace fusell {
class Dispatcher;
class FuseChannel {
public:
~FuseChannel();
/**
* Construct the fuse channel and session structures that are
* required by libfuse to communicate with the kernel using
* a pre-existing fuseDevice descriptor. The descriptor may
* have been obtained via privilegedFuseMount() or may have
* been passed to us as part of a graceful restart procedure.
*/
FuseChannel(
folly::File&& fuseDevice,
bool debug,
Dispatcher* const dispatcher);
// Forbidden copy constructor and assignment operator
FuseChannel(FuseChannel const&) = delete;
FuseChannel& operator=(FuseChannel const&) = delete;
/**
* Dispatches fuse requests until the session is torn down.
* This function blocks until the fuse session is stopped.
* The intent is that this is called from each of the
* fuse worker threads provided by the MountPoint. */
void processSession();
/**
* Requests that the worker threads terminate their processing loop.
*/
void requestSessionExit();
/**
* When performing a graceful restart, extract the fuse device
* descriptor from the channel, preventing it from being closed
* when we destroy this channel instance.
* Note that this method does not prevent the worker threads
* from continuing to use the fuse session.
*/
folly::File stealFuseDevice();
/**
* Notify to invalidate cache for an inode
*
* @param ino the inode number
* @param off the offset in the inode where to start invalidating
* or negative to invalidate attributes only
* @param len the amount of cache to invalidate or 0 for all
*/
void invalidateInode(fuse_ino_t ino, off_t off, off_t len);
/**
* Notify to invalidate parent attributes and the dentry matching
* parent/name
*
* @param parent inode number
* @param name file name
*/
void invalidateEntry(fuse_ino_t parent, PathComponentPiece name);
private:
/*
* fuse_chan_ops functions.
*
* These are very similar to the ones defined in libfuse.
* Unfortunately libfuse does not provide a public API for creating a channel
* from a mounted /dev/fuse file descriptor, so we have to provide our own
* implementations.
*/
static int recv(struct fuse_chan** chp, char* buf, size_t size);
static int send(struct fuse_chan* ch, const struct iovec iov[], size_t count);
static void destroy(struct fuse_chan* ch);
fuse_chan* ch_{nullptr};
fuse_args args_{0, nullptr, 0};
struct fuse_session* session_{nullptr};
Dispatcher* const dispatcher_{nullptr};
folly::File fuseDevice_;
};
}
}
}