fuse: Set `max_pages` in `InitOut`
This field acts as a global upper bound on the size of any request so
read and write requests are truncated to fit this size even if
`max_readahead` and `max_write` are set to larger values. Initialize
this field to the number of pages needed to fit the largest supported
requset size.
BUG=none
TEST=arc.PlayStore.vm
Change-Id: Ia82d3e5709971c642312c45b26c288a953dedb18
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3299973
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Chirantan Ekbote <chirantan@chromium.org>
diff --git a/fuse/src/server.rs b/fuse/src/server.rs
index 77ad89b..4a6362e 100644
--- a/fuse/src/server.rs
+++ b/fuse/src/server.rs
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+use std::cmp::{max, min};
use std::convert::TryInto;
use std::ffi::CStr;
use std::io;
@@ -954,6 +955,7 @@
| FsOptions::DO_READDIRPLUS
| FsOptions::READDIRPLUS_AUTO
| FsOptions::ATOMIC_O_TRUNC
+ | FsOptions::MAX_PAGES
| FsOptions::MAP_ALIGNMENT;
let capable = FsOptions::from_bits_truncate(flags);
@@ -973,6 +975,11 @@
enabled.remove(FsOptions::ATOMIC_O_TRUNC);
}
+ let max_write = self.fs.max_buffer_size();
+ let max_pages = min(
+ max(max_readahead, max_write) / pagesize() as u32,
+ u16::MAX as u32,
+ ) as u16;
let out = InitOut {
major: KERNEL_VERSION,
minor: KERNEL_MINOR_VERSION,
@@ -980,8 +987,9 @@
flags: enabled.bits(),
max_background: ::std::u16::MAX,
congestion_threshold: (::std::u16::MAX / 4) * 3,
- max_write: self.fs.max_buffer_size(),
+ max_write,
time_gran: 1, // nanoseconds
+ max_pages,
map_alignment: pagesize().trailing_zeros() as u16,
..Default::default()
};
diff --git a/fuse/src/sys.rs b/fuse/src/sys.rs
index 0c3af6a..07e1b6a 100644
--- a/fuse/src/sys.rs
+++ b/fuse/src/sys.rs
@@ -363,6 +363,13 @@
/// mapping requests are pagesize-aligned. This field automatically set by the server and
/// this feature is enabled by default.
const MAP_ALIGNMENT = MAP_ALIGNMENT;
+
+
+ /// Indicates that the `max_pages` field of the `InitOut` struct is valid.
+ ///
+ /// This field is used by the kernel driver to determine the maximum number of pages that
+ /// may be used for any read or write requests.
+ const MAX_PAGES = MAX_PAGES;
}
}