mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 08:18:15 +03:00
f23c60212d
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
140 lines
3.4 KiB
C++
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
|