Line data Source code
1 : use std::path::Path;
2 :
3 : use anyhow::{Context, anyhow};
4 : use tracing::{instrument, warn};
5 :
6 : pub const RESIZE_SWAP_BIN: &str = "/neonvm/bin/resize-swap";
7 :
8 : #[instrument]
9 : pub fn resize_swap(size_bytes: u64) -> anyhow::Result<()> {
10 : // run `/neonvm/bin/resize-swap --once {size_bytes}`
11 : //
12 : // Passing '--once' causes resize-swap to delete itself after successful completion, which
13 : // means that if compute_ctl restarts later, we won't end up calling 'swapoff' while
14 : // postgres is running.
15 : //
16 : // NOTE: resize-swap is not very clever. If present, --once MUST be the first arg.
17 : let child_result = std::process::Command::new("/usr/bin/sudo")
18 : .arg(RESIZE_SWAP_BIN)
19 : .arg("--once")
20 : .arg(size_bytes.to_string())
21 : .spawn();
22 :
23 : child_result
24 : .context("spawn() failed")
25 0 : .and_then(|mut child| child.wait().context("wait() failed"))
26 0 : .and_then(|status| match status.success() {
27 0 : true => Ok(()),
28 : false => {
29 : // The command failed. Maybe it was because the resize-swap file doesn't exist?
30 : // The --once flag causes it to delete itself on success so we don't disable swap
31 : // while postgres is running; maybe this is fine.
32 0 : match Path::new(RESIZE_SWAP_BIN).try_exists() {
33 0 : Err(_) | Ok(true) => Err(anyhow!("process exited with {status}")),
34 : // The path doesn't exist; we're actually ok
35 : Ok(false) => {
36 0 : warn!("ignoring \"not found\" error from resize-swap to avoid swapoff while compute is running");
37 0 : Ok(())
38 : },
39 : }
40 : }
41 0 : })
42 : // wrap any prior error with the overall context that we couldn't run the command
43 0 : .with_context(|| {
44 0 : format!("could not run `/usr/bin/sudo {RESIZE_SWAP_BIN} --once {size_bytes}`")
45 0 : })
46 : }
|