2021-10-01 07:38:10 +00:00
|
|
|
use std::future::Future;
|
|
|
|
use std::pin::Pin;
|
|
|
|
|
2020-04-17 12:11:25 +00:00
|
|
|
use anyhow::{bail, Error};
|
2019-08-28 14:11:01 +00:00
|
|
|
use futures::*;
|
2021-09-21 05:58:47 +00:00
|
|
|
use http::request::Parts;
|
|
|
|
use http::Response;
|
2021-10-05 09:01:05 +00:00
|
|
|
use hyper::{Body, Method, StatusCode};
|
|
|
|
use http::HeaderMap;
|
2019-08-28 14:11:01 +00:00
|
|
|
|
2021-10-08 09:19:37 +00:00
|
|
|
use proxmox_lang::try_block;
|
|
|
|
use proxmox_router::{RpcEnvironmentType, UserInformation};
|
2021-11-23 16:57:00 +00:00
|
|
|
use proxmox_sys::fs::CreateOptions;
|
2019-08-28 14:11:01 +00:00
|
|
|
|
2021-10-05 09:01:05 +00:00
|
|
|
use proxmox_rest_server::{daemon, AuthError, ApiConfig, RestServer, RestEnvironment, ServerAdapter};
|
2021-09-21 05:58:41 +00:00
|
|
|
|
2021-10-05 09:01:05 +00:00
|
|
|
use proxmox_backup::server::auth::check_pbs_auth;
|
2019-01-29 15:55:49 +00:00
|
|
|
use proxmox_backup::auth_helpers::*;
|
2019-02-16 11:19:13 +00:00
|
|
|
use proxmox_backup::config;
|
2018-10-31 09:42:14 +00:00
|
|
|
|
2020-01-20 11:52:22 +00:00
|
|
|
fn main() {
|
Set MMAP_THRESHOLD to a fixed value (128K)
glibc's malloc has a misguided heuristic to detect transient allocations that
will just result in allocation sizes below 32 MiB never using mmap.
That it turn means that those relatively big allocations are on the heap where
cleanup and returning memory to the OS is harder to do and easier to be blocked
by long living, small allocations at the top (end) of the heap.
Observing the malloc size distribution in a file-level backup run:
@size:
[0] 14 | |
[1] 25214 |@@@@@ |
[2, 4) 9090 |@ |
[4, 8) 12987 |@@ |
[8, 16) 93453 |@@@@@@@@@@@@@@@@@@@@ |
[16, 32) 30255 |@@@@@@ |
[32, 64) 237445 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64, 128) 32692 |@@@@@@@ |
[128, 256) 22296 |@@@@ |
[256, 512) 16177 |@@@ |
[512, 1K) 5139 |@ |
[1K, 2K) 3352 | |
[2K, 4K) 214 | |
[4K, 8K) 1568 | |
[8K, 16K) 95 | |
[16K, 32K) 3457 | |
[32K, 64K) 3175 | |
[64K, 128K) 161 | |
[128K, 256K) 453 | |
[256K, 512K) 93 | |
[512K, 1M) 74 | |
[1M, 2M) 774 | |
[2M, 4M) 319 | |
[4M, 8M) 700 | |
[8M, 16M) 93 | |
[16M, 32M) 18 | |
We see that all allocations will be on the heap, and that while most
allocations are small, the relatively few big ones will still make up most of
the RSS and if blocked from being released back to the OS result in much higher
peak and average usage for the program than actually required.
Avoiding the "dynamic" mmap-threshold increasement algorithm and fixing it at
the original default of 128 KiB reduces RSS size by factor 10-20 when running
backups. As with memory mappings other mappings or the heap can never block
freeing the memory fully back to the OS.
But, the drawback of using mmap is more wasted space for unaligned or small
allocation sizes, and the fact that the kernel allegedly zeros out the data
before giving it to user space. The former doesn't really matter for us when
using it only for allocations bigger than 128 KiB, and the latter is a
trade-off, using 10 to 20 times less memory brings its own performance
improvement possibilities for the whole system after all ;-)
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
[ Thomas: added to comment & commit message + extra-empty-line fixes ]
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2022-01-26 06:10:59 +00:00
|
|
|
pbs_tools::setup_libc_malloc_opts();
|
|
|
|
|
2020-06-15 08:38:30 +00:00
|
|
|
proxmox_backup::tools::setup_safe_path_env();
|
|
|
|
|
2021-11-19 16:36:06 +00:00
|
|
|
if let Err(err) = proxmox_async::runtime::main(run()) {
|
2019-02-11 14:11:42 +00:00
|
|
|
eprintln!("Error: {}", err);
|
|
|
|
std::process::exit(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-05 09:01:05 +00:00
|
|
|
struct ProxmoxBackupApiAdapter;
|
2021-09-21 05:58:47 +00:00
|
|
|
|
2021-10-05 09:01:05 +00:00
|
|
|
impl ServerAdapter for ProxmoxBackupApiAdapter {
|
2021-09-21 05:58:47 +00:00
|
|
|
|
2021-10-05 09:01:05 +00:00
|
|
|
fn get_index(
|
|
|
|
&self,
|
|
|
|
_env: RestEnvironment,
|
|
|
|
_parts: Parts,
|
|
|
|
) -> Pin<Box<dyn Future<Output = Response<Body>> + Send>> {
|
|
|
|
Box::pin(async move {
|
|
|
|
|
|
|
|
let index = "<center><h1>Proxmox Backup API Server</h1></center>";
|
|
|
|
|
|
|
|
Response::builder()
|
|
|
|
.status(StatusCode::OK)
|
|
|
|
.header(hyper::header::CONTENT_TYPE, "text/html")
|
|
|
|
.body(index.into())
|
|
|
|
.unwrap()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_auth<'a>(
|
|
|
|
&'a self,
|
|
|
|
headers: &'a HeaderMap,
|
|
|
|
method: &'a Method,
|
|
|
|
) -> Pin<Box<dyn Future<Output = Result<(String, Box<dyn UserInformation + Sync + Send>), AuthError>> + Send + 'a>> {
|
|
|
|
Box::pin(async move {
|
|
|
|
check_pbs_auth(headers, method).await
|
|
|
|
})
|
|
|
|
}
|
2021-09-21 05:58:47 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 14:11:01 +00:00
|
|
|
async fn run() -> Result<(), Error> {
|
2019-01-26 09:56:11 +00:00
|
|
|
if let Err(err) = syslog::init(
|
|
|
|
syslog::Facility::LOG_DAEMON,
|
|
|
|
log::LevelFilter::Info,
|
|
|
|
Some("proxmox-backup-api")) {
|
2019-02-11 14:11:42 +00:00
|
|
|
bail!("unable to inititialize syslog - {}", err);
|
2019-02-16 11:19:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
config::create_configdir()?;
|
2019-01-26 09:56:11 +00:00
|
|
|
|
2019-12-27 12:44:21 +00:00
|
|
|
config::update_self_signed_cert(false)?;
|
|
|
|
|
2021-09-01 10:21:51 +00:00
|
|
|
proxmox_backup::server::create_run_dir()?;
|
2021-11-12 07:08:23 +00:00
|
|
|
proxmox_backup::server::create_state_dir()?;
|
2022-04-12 05:25:58 +00:00
|
|
|
proxmox_backup::server::create_active_operations_dir()?;
|
2020-10-28 06:33:05 +00:00
|
|
|
proxmox_backup::server::jobstate::create_jobstate_dir()?;
|
2020-12-09 09:16:01 +00:00
|
|
|
proxmox_backup::tape::create_tape_status_dir()?;
|
2021-02-19 16:49:50 +00:00
|
|
|
proxmox_backup::tape::create_drive_state_dir()?;
|
|
|
|
proxmox_backup::tape::create_changer_state_dir()?;
|
2021-07-12 15:23:38 +00:00
|
|
|
proxmox_backup::tape::create_drive_lock_dir()?;
|
2020-05-23 08:43:08 +00:00
|
|
|
|
2019-01-29 12:15:33 +00:00
|
|
|
if let Err(err) = generate_auth_key() {
|
2019-02-11 14:11:42 +00:00
|
|
|
bail!("unable to generate auth key - {}", err);
|
2019-01-29 11:59:07 +00:00
|
|
|
}
|
2019-01-29 16:21:58 +00:00
|
|
|
let _ = private_auth_key(); // load with lazy_static
|
2019-01-29 11:59:07 +00:00
|
|
|
|
2019-01-29 12:15:33 +00:00
|
|
|
if let Err(err) = generate_csrf_key() {
|
2019-02-11 14:11:42 +00:00
|
|
|
bail!("unable to generate csrf key - {}", err);
|
2019-01-29 12:15:33 +00:00
|
|
|
}
|
2019-01-29 16:21:58 +00:00
|
|
|
let _ = csrf_secret(); // load with lazy_static
|
2019-01-29 12:15:33 +00:00
|
|
|
|
2021-09-21 05:58:40 +00:00
|
|
|
let mut config = ApiConfig::new(
|
2021-07-06 09:56:35 +00:00
|
|
|
pbs_buildcfg::JS_DIR,
|
2021-03-31 10:21:51 +00:00
|
|
|
&proxmox_backup::api2::ROUTER,
|
|
|
|
RpcEnvironmentType::PRIVILEGED,
|
2021-10-05 09:01:05 +00:00
|
|
|
ProxmoxBackupApiAdapter,
|
2021-03-31 10:21:51 +00:00
|
|
|
)?;
|
2020-05-23 08:43:08 +00:00
|
|
|
|
2021-09-21 05:58:40 +00:00
|
|
|
let backup_user = pbs_config::backup_user()?;
|
2021-09-30 10:31:38 +00:00
|
|
|
let mut commando_sock = proxmox_rest_server::CommandSocket::new(proxmox_rest_server::our_ctrl_sock(), backup_user.gid);
|
2020-11-02 18:13:36 +00:00
|
|
|
|
2021-09-21 05:58:40 +00:00
|
|
|
let dir_opts = CreateOptions::new().owner(backup_user.uid).group(backup_user.gid);
|
|
|
|
let file_opts = CreateOptions::new().owner(backup_user.uid).group(backup_user.gid);
|
|
|
|
|
2021-09-30 09:59:21 +00:00
|
|
|
config.enable_access_log(
|
2021-09-21 05:58:40 +00:00
|
|
|
pbs_buildcfg::API_ACCESS_LOG_FN,
|
2021-09-21 05:58:50 +00:00
|
|
|
Some(dir_opts.clone()),
|
|
|
|
Some(file_opts.clone()),
|
|
|
|
&mut commando_sock,
|
|
|
|
)?;
|
|
|
|
|
|
|
|
config.enable_auth_log(
|
|
|
|
pbs_buildcfg::API_AUTH_LOG_FN,
|
2021-09-22 06:44:48 +00:00
|
|
|
Some(dir_opts.clone()),
|
|
|
|
Some(file_opts.clone()),
|
2021-09-21 05:58:40 +00:00
|
|
|
&mut commando_sock,
|
|
|
|
)?;
|
2020-10-16 09:06:46 +00:00
|
|
|
|
2021-09-21 05:58:50 +00:00
|
|
|
|
2018-11-15 07:18:48 +00:00
|
|
|
let rest_server = RestServer::new(config);
|
2021-09-23 08:09:19 +00:00
|
|
|
proxmox_rest_server::init_worker_tasks(pbs_buildcfg::PROXMOX_BACKUP_LOG_DIR_M!().into(), file_opts.clone())?;
|
2018-10-31 09:42:14 +00:00
|
|
|
|
2019-03-18 11:27:00 +00:00
|
|
|
// http server future:
|
2019-03-18 13:13:44 +00:00
|
|
|
let server = daemon::create_daemon(
|
|
|
|
([127,0,0,1], 82).into(),
|
2021-09-29 09:21:32 +00:00
|
|
|
move |listener| {
|
2021-09-29 07:04:17 +00:00
|
|
|
let incoming = hyper::server::conn::AddrIncoming::from_listener(listener)?;
|
|
|
|
|
2021-09-29 09:21:32 +00:00
|
|
|
Ok(async {
|
|
|
|
daemon::systemd_notify(daemon::SystemdNotify::Ready)?;
|
|
|
|
|
|
|
|
hyper::Server::builder(incoming)
|
2019-09-02 13:16:21 +00:00
|
|
|
.serve(rest_server)
|
2021-09-21 05:58:40 +00:00
|
|
|
.with_graceful_shutdown(proxmox_rest_server::shutdown_future())
|
2019-09-02 13:16:21 +00:00
|
|
|
.map_err(Error::from)
|
2021-09-29 09:21:32 +00:00
|
|
|
.await
|
|
|
|
})
|
2019-03-18 11:27:00 +00:00
|
|
|
},
|
2019-09-02 13:16:21 +00:00
|
|
|
);
|
2019-03-18 11:27:00 +00:00
|
|
|
|
2021-09-23 08:09:19 +00:00
|
|
|
proxmox_rest_server::write_pid(pbs_buildcfg::PROXMOX_BACKUP_API_PID_FN)?;
|
2019-04-25 08:38:26 +00:00
|
|
|
|
2019-08-28 14:11:01 +00:00
|
|
|
let init_result: Result<(), Error> = try_block!({
|
2021-09-23 08:09:19 +00:00
|
|
|
proxmox_rest_server::register_task_control_commands(&mut commando_sock)?;
|
2020-11-02 18:13:36 +00:00
|
|
|
commando_sock.spawn()?;
|
2021-09-30 06:03:34 +00:00
|
|
|
proxmox_rest_server::catch_shutdown_signal()?;
|
|
|
|
proxmox_rest_server::catch_reload_signal()?;
|
2019-08-28 14:11:01 +00:00
|
|
|
Ok(())
|
|
|
|
});
|
2019-04-08 12:00:23 +00:00
|
|
|
|
2019-08-28 14:11:01 +00:00
|
|
|
if let Err(err) = init_result {
|
|
|
|
bail!("unable to start daemon - {}", err);
|
|
|
|
}
|
2019-04-09 10:15:06 +00:00
|
|
|
|
2019-09-02 13:16:21 +00:00
|
|
|
server.await?;
|
2019-12-27 11:50:27 +00:00
|
|
|
log::info!("server shutting down, waiting for active workers to complete");
|
2021-09-21 05:58:40 +00:00
|
|
|
proxmox_rest_server::last_worker_future().await?;
|
2019-04-08 12:00:23 +00:00
|
|
|
|
2019-08-28 14:11:01 +00:00
|
|
|
log::info!("done - exit server");
|
2020-05-23 08:43:08 +00:00
|
|
|
|
2019-02-11 14:11:42 +00:00
|
|
|
Ok(())
|
2018-10-30 09:04:30 +00:00
|
|
|
}
|