Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5dd7bc78 authored by Daichi Hirono's avatar Daichi Hirono Committed by android-build-merger
Browse files

Merge "Retry write operation when getting ENOBUFS." into oc-dev

am: e6b7328b

Change-Id: Ica177880f5de4d981a9c3e873ef05591b1455c3b
parents 24375323 e6b7328b
Loading
Loading
Loading
Loading
+30 −21
Original line number Original line Diff line number Diff line
@@ -34,6 +34,8 @@ namespace android {
namespace fuse {
namespace fuse {
namespace {
namespace {


constexpr useconds_t kRetrySleepForWriting = 1000;  // 1 ms

template <typename T>
template <typename T>
bool CheckHeaderLength(const FuseMessage<T>* self, const char* name, size_t max_size) {
bool CheckHeaderLength(const FuseMessage<T>* self, const char* name, size_t max_size) {
    const auto& header = static_cast<const T*>(self)->header;
    const auto& header = static_cast<const T*>(self)->header;
@@ -91,6 +93,7 @@ ResultOrAgain WriteInternal(const FuseMessage<T>* self, int fd, int sockflag, co
    const char* const buf = reinterpret_cast<const char*>(self);
    const char* const buf = reinterpret_cast<const char*>(self);
    const auto& header = static_cast<const T*>(self)->header;
    const auto& header = static_cast<const T*>(self)->header;


    while (true) {
        int result;
        int result;
        if (sockflag) {
        if (sockflag) {
            CHECK(data == nullptr);
            CHECK(data == nullptr);
@@ -102,19 +105,25 @@ ResultOrAgain WriteInternal(const FuseMessage<T>* self, int fd, int sockflag, co
        } else {
        } else {
            result = TEMP_FAILURE_RETRY(write(fd, buf, header.len));
            result = TEMP_FAILURE_RETRY(write(fd, buf, header.len));
        }
        }

        if (result == -1) {
        if (result == -1) {
        if (errno == EAGAIN) {
            switch (errno) {
                case ENOBUFS:
                    // When returning ENOBUFS, epoll still reports the FD is writable. Just usleep
                    // and retry again.
                    usleep(kRetrySleepForWriting);
                    continue;
                case EAGAIN:
                    return ResultOrAgain::kAgain;
                    return ResultOrAgain::kAgain;
        }
                default:
                    PLOG(ERROR) << "Failed to write a FUSE message";
                    PLOG(ERROR) << "Failed to write a FUSE message";
                    return ResultOrAgain::kFailure;
                    return ResultOrAgain::kFailure;
            }
            }

        }
        CHECK(static_cast<uint32_t>(result) == header.len);
        CHECK(static_cast<uint32_t>(result) == header.len);
        return ResultOrAgain::kSuccess;
        return ResultOrAgain::kSuccess;
    }
    }
}
}
}


static_assert(std::is_standard_layout<FuseBuffer>::value,
static_assert(std::is_standard_layout<FuseBuffer>::value,
              "FuseBuffer must be standard layout union.");
              "FuseBuffer must be standard layout union.");
@@ -161,7 +170,7 @@ bool FuseMessage<T>::Write(int fd) const {
template <typename T>
template <typename T>
bool FuseMessage<T>::WriteWithBody(int fd, size_t max_size, const void* data) const {
bool FuseMessage<T>::WriteWithBody(int fd, size_t max_size, const void* data) const {
    CHECK(data != nullptr);
    CHECK(data != nullptr);
    return WriteInternal<T>(this, fd, 0, data, max_size) == ResultOrAgain::kSuccess;
    return WriteInternal(this, fd, 0, data, max_size) == ResultOrAgain::kSuccess;
}
}


template <typename T>
template <typename T>