/* * 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 #include #include #include #include #include #include "eden/fs/fuse/EdenStats.h" #include "eden/fs/fuse/FileHandleMap.h" #include "eden/fs/fuse/fuse_headers.h" #include "eden/fs/utils/PathFuncs.h" namespace facebook { namespace eden { namespace fusell { #define FUSELL_NOT_IMPL() \ do { \ LOG_FIRST_N(ERROR, 1) << __PRETTY_FUNCTION__ << " not implemented"; \ folly::throwSystemErrorExplicit(ENOSYS, __PRETTY_FUNCTION__); \ } while (0) class Dispatcher; class RequestData; class FileHandle; class DirHandle; class MountPoint; /** Low level fuse operations are exposed here so that we can * tie them into the fuse channel in the MountPoint class. */ extern const fuse_lowlevel_ops dispatcher_ops; class Dispatcher { fuse_conn_info connInfo_; ThreadLocalEdenStats* stats_{nullptr}; FileHandleMap fileHandles_; std::atomic numOutstandingRequests_{0}; public: virtual ~Dispatcher(); explicit Dispatcher(ThreadLocalEdenStats* stats); static void disp_init(void* userdata, struct fuse_conn_info* conn); ThreadLocalEdenStats* getStats() const; /** * Called by RequestData to advise of requests that are in-flight * and pending completion. */ inline void incNumOutstandingRequests() { numOutstandingRequests_++; } inline void decNumOutstandingRequests() { numOutstandingRequests_--; } /** * Returns true if there are no outstanding fuse requests. * This is intended to be used only after the associated fuse * channel has stopped servicing new requests during graceful * shutdown; once that has happened, and hasOutstandingRequests() * returns false we know that it is safe to proceed with the * graceful shutdown. */ inline bool hasOutstandingRequests() const { return numOutstandingRequests_ == 0; } const fuse_conn_info& getConnInfo() const; FileHandleMap& getFileHandles(); // delegates to FileHandleMap::getGenericFileHandle std::shared_ptr getGenericFileHandle(uint64_t fh); // delegates to FileHandleMap::getFileHandle std::shared_ptr getFileHandle(uint64_t fh); // delegates to FileHandleMap::getDirHandle std::shared_ptr getDirHandle(uint64_t dh); /** * Called during filesystem mounting. It informs the filesystem * of kernel capabilities and provides an opportunity to poke some * flags and limits in the conn_info to report capabilities back * to the kernel */ virtual void initConnection(fuse_conn_info& conn); /** * Called when fuse is tearing down the session */ virtual void destroy(); /** * Lookup a directory entry by name and get its attributes */ virtual folly::Future lookup( fuse_ino_t parent, PathComponentPiece name); /** * Forget about an inode * * The nlookup parameter indicates the number of lookups * previously performed on this inode. * * If the filesystem implements inode lifetimes, it is recommended * that inodes acquire a single reference on each lookup, and lose * nlookup references on each forget. * * The filesystem may ignore forget calls, if the inodes don't * need to have a limited lifetime. * * On unmount it is not guaranteed, that all referenced inodes * will receive a forget message. * * @param ino the inode number * @param nlookup the number of lookups to forget */ virtual folly::Future forget(fuse_ino_t ino, unsigned long nlookup); /** * The stat information and the cache TTL for the kernel * * The timeout value is measured in seconds and indicates how long * the kernel side of the FUSE will cache the values in the * struct stat before calling getattr() again to refresh it. */ struct Attr { struct stat st; double timeout; explicit Attr( const struct stat& st, double timeout = std::numeric_limits::max()); }; /** * Get file attributes * * @param ino the inode number */ virtual folly::Future getattr(fuse_ino_t ino); /** * Set file attributes * * In the 'attr' argument only members indicated by the 'to_set' * bitmask contain valid values. Other members contain undefined * values. * * @param ino the inode number * @param attr the attributes * @param to_set bit mask of attributes which should be set * * Changed in version 2.5: * file information filled in for ftruncate */ virtual folly::Future setattr(fuse_ino_t ino, const struct stat& attr, int to_set); /** * Read symbolic link * * @param ino the inode number */ virtual folly::Future readlink(fuse_ino_t ino); /** * Create file node * * Create a regular file, character device, block device, fifo or * socket node. * * @param parent inode number of the parent directory * @param name to create * @param mode file type and mode with which to create the new file * @param rdev the device number (only valid if created file is a device) */ virtual folly::Future mknod(fuse_ino_t parent, PathComponentPiece name, mode_t mode, dev_t rdev); /** * Create a directory * * @param parent inode number of the parent directory * @param name to create * @param mode with which to create the new file */ virtual folly::Future mkdir(fuse_ino_t parent, PathComponentPiece name, mode_t mode); /** * Remove a file * * @param parent inode number of the parent directory * @param name to remove */ virtual folly::Future unlink( fuse_ino_t parent, PathComponentPiece name); /** * Remove a directory * * @param parent inode number of the parent directory * @param name to remove */ virtual folly::Future rmdir( fuse_ino_t parent, PathComponentPiece name); /** * Create a symbolic link * * @param parent inode number of the parent directory * @param name to create * @param link the contents of the symbolic link */ virtual folly::Future symlink(fuse_ino_t parent, PathComponentPiece name, folly::StringPiece link); /** * Rename a file * * @param parent inode number of the old parent directory * @param name old name * @param newparent inode number of the new parent directory * @param newname new name */ virtual folly::Future rename( fuse_ino_t parent, PathComponentPiece name, fuse_ino_t newparent, PathComponentPiece newname); /** * Create a hard link * * @param ino the old inode number * @param newparent inode number of the new parent directory * @param newname new name to create */ virtual folly::Future link(fuse_ino_t ino, fuse_ino_t newparent, PathComponentPiece newname); /** * Open a file * * Open flags (with the exception of O_CREAT, O_EXCL, O_NOCTTY and * O_TRUNC) are available in fi->flags. * * Filesystem may store an arbitrary file handle (pointer, index, * etc) in fi->fh, and use this in other all other file operations * (read, write, flush, release, fsync). * * There are also some flags (direct_io, keep_cache) which the * filesystem may set in fi, to change the way the file is opened. * See fuse_file_info structure in for more details. * * @param ino the inode number * @param fi file information */ virtual folly::Future> open( fuse_ino_t ino, const struct fuse_file_info& fi); /** * Open a directory * * Filesystem may store an arbitrary file handle (pointer, index, * etc) in fi->fh, and use this in other all other directory * stream operations (readdir, releasedir, fsyncdir). * * Filesystem may also implement stateless directory I/O and not * store anything in fi->fh, though that makes it impossible to * implement standard conforming directory stream operations in * case the contents of the directory can change between opendir * and releasedir. * * @param ino the inode number * @param fi file information */ virtual folly::Future> opendir( fuse_ino_t ino, const struct fuse_file_info& fi); /** * Get file system statistics * * @param ino the inode number, zero means "undefined" */ virtual folly::Future statfs(fuse_ino_t ino); /** * Set an extended attribute */ virtual folly::Future setxattr(fuse_ino_t ino, folly::StringPiece name, folly::StringPiece value, int flags); /** * Get an extended attribute */ virtual folly::Future getxattr( fuse_ino_t ino, folly::StringPiece name); static const int kENOATTR; /** * List extended attribute names */ virtual folly::Future> listxattr(fuse_ino_t ino); /** * Remove an extended attribute * * @param ino the inode number * @param name of the extended attribute */ virtual folly::Future removexattr(fuse_ino_t ino, folly::StringPiece name); /** * Check file access permissions * * This will be called for the access() system call. If the * 'default_permissions' mount option is given, this method is not * called. * * This method is not called under Linux kernel versions 2.4.x * * Introduced in version 2.5 * * @param ino the inode number * @param mask requested access mode */ virtual folly::Future access(fuse_ino_t ino, int mask); struct Create { fuse_entry_param entry; std::shared_ptr fh; }; /** * Create and open a file * * If the file does not exist, first create it with the specified * mode, and then open it. * * Open flags (with the exception of O_NOCTTY) are available in * fi->flags. * * If this method is not implemented or under Linux kernel * versions earlier than 2.6.15, the mknod() and open() methods * will be called instead. * * Introduced in version 2.5 * * @param parent inode number of the parent directory * @param name to create * @param mode file type and mode with which to create the new file */ virtual folly::Future create(fuse_ino_t parent, PathComponentPiece name, mode_t mode, int flags); /** * Map block index within file to block index within device * * Note: This makes sense only for block device backed filesystems * mounted with the 'blkdev' option * * Introduced in version 2.6 * * @param ino the inode number * @param blocksize unit of block index * @param idx block index within file */ virtual folly::Future bmap(fuse_ino_t ino, size_t blocksize, uint64_t idx); }; } } }