fusebox: Add DirEntry stream response error handling
A FUSE readdir op will create DirEntryResponse to collect responses
(DirEntry list chunks, streamed from the server) and append them to
DirEntryResponse DirEntry list.
Any received chunk can have a non-zero error. Add an "Append" error
API to DirEntryResponse. Like other Append API, Respond() to Kernel
Fuse DirEntryRequest(s) [1].
[1] One error is sufficient in practice to end the FUSE readdir op.
The Kernel sends a FUSE releasedir op to close the dir on receiving
a readdir op error.
BUG=chromium:1244007
TEST=cros_workon_make --board=${BOARD} fusebox --test
Change-Id: If80bb95cb9a7c268157a440d03e3b9fba3baa1eb
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3230449
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Commit-Queue: Noel Gordon <noel@chromium.org>
Tested-by: Noel Gordon <noel@chromium.org>
diff --git a/fusebox/fuse_request.cc b/fusebox/fuse_request.cc
index 8c9c259..59f0934 100644
--- a/fusebox/fuse_request.cc
+++ b/fusebox/fuse_request.cc
@@ -144,12 +144,20 @@
Respond();
}
+void DirEntryResponse::Append(int error) {
+ error_ = error;
+ Respond();
+}
+
void DirEntryResponse::Respond() {
const auto process_next_request = [&]() {
DCHECK(!request_.empty());
- if (request_[0]->IsInterrupted()) {
- request_.erase(request_.begin());
+ if (request_[0]->IsInterrupted())
+ return true;
+
+ if (error_) {
+ request_[0]->ReplyError(error_);
return true;
}
@@ -161,14 +169,12 @@
if (request_[0]->AddEntry(entry_[offset++], next))
continue; // add next entry
request_[0]->ReplyDone();
- request_.erase(request_.begin());
return true;
}
CHECK_GE(offset, entry_.size());
if (end_) {
request_[0]->ReplyDone();
- request_.erase(request_.begin());
return true;
}
@@ -178,6 +184,7 @@
while (!request_.empty() && !entry_.empty()) {
if (!process_next_request())
break;
+ request_.erase(request_.begin());
}
}
diff --git a/fusebox/fuse_request.h b/fusebox/fuse_request.h
index 638e051..4721b26 100644
--- a/fusebox/fuse_request.h
+++ b/fusebox/fuse_request.h
@@ -139,6 +139,9 @@
// Append |request| to the DirEntryRequest list.
void Append(std::unique_ptr<DirEntryRequest> request);
+ // Error the DirEntry list with errno |error|.
+ void Append(int error);
+
private:
// Called on Append() to respond to DirEntry requests.
void Respond();
@@ -153,6 +156,9 @@
// List of DirEntry from the file system: readdir(2).
std::vector<struct DirEntry> entry_;
+ // Error state of the DirEntry list.
+ int error_ = 0;
+
// True when the DirEntry list is complete.
bool end_ = false;
};