sapling/eden/fuse/MountPoint.h
Adam Simpkins 781936eba5 fix uninitialized inode numbers and other data in stat() responses
Summary:
This fixes inode number handling problems in TreeInode and TreeEntryFileInode.
Previosly these classes each had an ino_ member variable, despite deriving from
InodeBase which has its own (private) ino_ member.

TreeEntryFileInode never actually initialized its own local ino_ variable.
This was causing problems for many applications which use inode numbers to
cache file data.  TreeEntryFileInode returned garbage data in the inode field,
resulting in incorrect cache collisions.

This fixes the inode handling, and also fixes the stat data returned by
FileData.  It now sets the uid, gid, and inode fields correctly.  It 0s out
several other fields rather than leaving them uninitialized.

Reviewed By: bolinfest

Differential Revision: D3455126

fbshipit-source-id: 631276b01676733f96035bc153219ef84406dcc9
2016-06-20 13:40:02 -07:00

128 lines
3.2 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 <condition_variable>
#include <memory>
#include <mutex>
#include "eden/utils/PathFuncs.h"
struct stat;
namespace facebook {
namespace eden {
namespace fusell {
class DirInode;
class InodeDispatcher;
class InodeNameManager;
class Channel;
class MountPoint {
public:
explicit MountPoint(
AbsolutePathPiece path,
std::shared_ptr<DirInode> root = {});
virtual ~MountPoint();
void setRootInode(std::shared_ptr<DirInode> inode);
const AbsolutePath& getPath() const {
return path_;
}
InodeDispatcher* getDispatcher() const {
return dispatcher_.get();
}
InodeNameManager* getNameMgr() const {
return nameManager_.get();
}
/**
* Spawn a new thread to mount the filesystem and run the fuse channel.
*
* This is similar to run(), except that it returns as soon as the filesystem
* has been successfully mounted.
*
* If an onStop() argument is supplied, this will be called from the FUSE
* channel thread after the mount point is stopped, just before the thread
* terminates. (This happens once the mount point is unmounted.)
*
* If start() throws an exception, onStop() will not be called.
*/
void start(bool debug);
void start(bool debug, const std::function<void()>& onStop);
/**
* Mount the file system, and run the fuse channel.
*
* This function will not return until the filesystem is unmounted.
*/
void run(bool debug);
uid_t getUid() const {
return uid_;
}
gid_t getGid() const {
return gid_;
}
/** Returns the channel associated with this mount point.
* No smart pointer because the lifetime is managed solely
* by the MountPoint instance.
* This method may return nullptr during initialization or
* finalization of a mount point.
*/
Channel* getChannel() {
return channel_.get();
}
/**
* Indicate that the mount point has been successfully started.
*
* This function should only be invoked by InodeDispatcher.
*/
void mountStarted();
/**
* Return a stat structure that has been minimally initialized with
* data for this mount point.
*
* The caller must still initialize all file-specific data (inode number,
* file mode, size, timestamps, link count, etc).
*/
struct stat initStatData() const;
private:
enum class Status { UNINIT, STARTING, RUNNING, ERROR };
// Forbidden copy constructor and assignment operator
MountPoint(MountPoint const&) = delete;
MountPoint& operator=(MountPoint const&) = delete;
AbsolutePath const path_; // the path where this MountPoint is mounted
uid_t uid_;
gid_t gid_;
std::unique_ptr<InodeDispatcher> const dispatcher_;
std::unique_ptr<InodeNameManager> const nameManager_;
std::unique_ptr<Channel> channel_;
std::mutex mutex_;
std::condition_variable statusCV_;
Status status_{Status::UNINIT};
std::exception_ptr startError_;
};
}
}
} // facebook::eden::fusell