sapling/eden/fs/inodes/OverlayFile.cpp
Genevieve Helsel f23c60212d support closing the Overlay class even if it is still in use
Summary:
Throw errors if a read or write is called on the `Overlay` class after `close()` has been called. Adds IO reference counting to know when it is safe to release the overlay lock after calling `close()`

This takes care to catch errors that could be thrown around overlay IO and makes sure to correctly decrement the IO count in the case of errors.

Reviewed By: chadaustin

Differential Revision: D17957360

fbshipit-source-id: af5e3c3f98c77800914d03cd748fb2f1c59ae264
2019-11-11 10:56:15 -08:00

140 lines
3.4 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
#include "eden/fs/inodes/OverlayFile.h"
#include <folly/FileUtil.h>
#include "eden/fs/inodes/Overlay.h"
namespace facebook {
namespace eden {
OverlayFile::OverlayFile(folly::File file, std::weak_ptr<Overlay> overlay)
: file_{std::move(file)}, overlay_{overlay} {}
folly::Expected<struct stat, int> OverlayFile::fstat() const {
std::shared_ptr<Overlay> overlay = overlay_.lock();
if (!overlay) {
return folly::makeUnexpected(EIO);
}
IORequest req{overlay.get()};
struct stat st {};
if (::fstat(file_.fd(), &st)) {
return folly::makeUnexpected(errno);
}
return st;
}
folly::Expected<ssize_t, int>
OverlayFile::preadNoInt(void* buf, size_t n, off_t offset) const {
std::shared_ptr<Overlay> overlay = overlay_.lock();
if (!overlay) {
return folly::makeUnexpected(EIO);
}
IORequest req{overlay.get()};
auto ret = folly::preadNoInt(file_.fd(), buf, n, offset);
if (ret == -1) {
return folly::makeUnexpected(errno);
}
return ret;
}
folly::Expected<off_t, int> OverlayFile::lseek(off_t offset, int whence) const {
std::shared_ptr<Overlay> overlay = overlay_.lock();
if (!overlay) {
return folly::makeUnexpected(EIO);
}
IORequest req{overlay.get()};
auto ret = ::lseek(file_.fd(), offset, whence);
if (ret == -1) {
return folly::makeUnexpected(errno);
}
return ret;
}
folly::Expected<ssize_t, int>
OverlayFile::pwritev(const iovec* iov, int iovcnt, off_t offset) const {
std::shared_ptr<Overlay> overlay = overlay_.lock();
if (!overlay) {
return folly::makeUnexpected(EIO);
}
IORequest req{overlay.get()};
auto ret = folly::pwritevNoInt(file_.fd(), iov, iovcnt, offset);
if (ret == -1) {
return folly::makeUnexpected(errno);
}
return ret;
}
folly::Expected<int, int> OverlayFile::ftruncate(off_t length) const {
std::shared_ptr<Overlay> overlay = overlay_.lock();
if (!overlay) {
return folly::makeUnexpected(EIO);
}
IORequest req{overlay.get()};
auto ret = ::ftruncate(file_.fd(), length);
if (ret == -1) {
return folly::makeUnexpected(errno);
}
return folly::makeExpected<int>(ret);
}
folly::Expected<int, int> OverlayFile::fsync() const {
std::shared_ptr<Overlay> overlay = overlay_.lock();
if (!overlay) {
return folly::makeUnexpected(EIO);
}
IORequest req{overlay.get()};
auto ret = ::fsync(file_.fd());
if (ret == -1) {
return folly::makeUnexpected(errno);
}
return folly::makeExpected<int>(ret);
}
folly::Expected<int, int> OverlayFile::fdatasync() const {
#ifndef __APPLE__
std::shared_ptr<Overlay> overlay = overlay_.lock();
if (!overlay) {
return folly::makeUnexpected(EIO);
}
IORequest req{overlay.get()};
auto ret = ::fdatasync(file_.fd());
if (ret == -1) {
return folly::makeUnexpected(errno);
}
return folly::makeExpected<int>(ret);
#else
return fsync();
#endif
}
folly::Expected<std::string, int> OverlayFile::readFile() const {
std::shared_ptr<Overlay> overlay = overlay_.lock();
if (!overlay) {
return folly::makeUnexpected(EIO);
}
IORequest req{overlay.get()};
std::string out;
if (!folly::readFile(file_.fd(), out)) {
return folly::makeUnexpected(errno);
}
return folly::makeExpected<int>(std::move(out));
}
} // namespace eden
} // namespace facebook