mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-12 15:26:52 +00:00
Make fsync an option for meta and data
This commit is contained in:
+22
-13
@@ -80,6 +80,7 @@ pub struct BlockManager {
|
||||
/// Directory in which block are stored
|
||||
pub data_dir: PathBuf,
|
||||
|
||||
data_fsync: bool,
|
||||
compression_level: Option<i32>,
|
||||
|
||||
mutation_lock: [Mutex<BlockManagerLocked>; 256],
|
||||
@@ -114,6 +115,7 @@ impl BlockManager {
|
||||
pub fn new(
|
||||
db: &db::Db,
|
||||
data_dir: PathBuf,
|
||||
data_fsync: bool,
|
||||
compression_level: Option<i32>,
|
||||
replication: TableShardedReplication,
|
||||
system: Arc<System>,
|
||||
@@ -141,6 +143,7 @@ impl BlockManager {
|
||||
let block_manager = Arc::new(Self {
|
||||
replication,
|
||||
data_dir,
|
||||
data_fsync,
|
||||
compression_level,
|
||||
mutation_lock: [(); 256].map(|_| Mutex::new(BlockManagerLocked())),
|
||||
rc,
|
||||
@@ -713,7 +716,11 @@ impl BlockManagerLocked {
|
||||
|
||||
let mut f = fs::File::create(&path_tmp).await?;
|
||||
f.write_all(data).await?;
|
||||
f.sync_all().await?;
|
||||
|
||||
if mgr.data_fsync {
|
||||
f.sync_all().await?;
|
||||
}
|
||||
|
||||
drop(f);
|
||||
|
||||
fs::rename(path_tmp, path).await?;
|
||||
@@ -724,18 +731,20 @@ impl BlockManagerLocked {
|
||||
fs::remove_file(to_delete).await?;
|
||||
}
|
||||
|
||||
// We want to ensure that when this function returns, data is properly persisted
|
||||
// to disk. The first step is the sync_all above that does an fsync on the data file.
|
||||
// Now, we do an fsync on the containing directory, to ensure that the rename
|
||||
// is persisted properly. See:
|
||||
// http://thedjbway.b0llix.net/qmail/syncdir.html
|
||||
let dir = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.mode(0)
|
||||
.open(directory)
|
||||
.await?;
|
||||
dir.sync_all().await?;
|
||||
drop(dir);
|
||||
if mgr.data_fsync {
|
||||
// We want to ensure that when this function returns, data is properly persisted
|
||||
// to disk. The first step is the sync_all above that does an fsync on the data file.
|
||||
// Now, we do an fsync on the containing directory, to ensure that the rename
|
||||
// is persisted properly. See:
|
||||
// http://thedjbway.b0llix.net/qmail/syncdir.html
|
||||
let dir = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.mode(0)
|
||||
.open(directory)
|
||||
.await?;
|
||||
dir.sync_all().await?;
|
||||
drop(dir);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+14
-1
@@ -91,6 +91,11 @@ impl Garage {
|
||||
// ---- Sled DB ----
|
||||
#[cfg(feature = "sled")]
|
||||
"sled" => {
|
||||
if config.metadata_fsync {
|
||||
return Err(Error::Message(format!(
|
||||
"`metadata_fsync = true` is not supported with the Sled database engine"
|
||||
)));
|
||||
}
|
||||
db_path.push("db");
|
||||
info!("Opening Sled database at: {}", db_path.display());
|
||||
let db = db::sled_adapter::sled::Config::default()
|
||||
@@ -111,7 +116,11 @@ impl Garage {
|
||||
let db = db::sqlite_adapter::rusqlite::Connection::open(db_path)
|
||||
.and_then(|db| {
|
||||
db.pragma_update(None, "journal_mode", &"WAL")?;
|
||||
db.pragma_update(None, "synchronous", &"NORMAL")?;
|
||||
if config.metadata_fsync {
|
||||
db.pragma_update(None, "synchronous", &"NORMAL")?;
|
||||
} else {
|
||||
db.pragma_update(None, "synchronous", &"OFF")?;
|
||||
}
|
||||
Ok(db)
|
||||
})
|
||||
.ok_or_message("Unable to open sqlite DB")?;
|
||||
@@ -139,6 +148,9 @@ impl Garage {
|
||||
env_builder.map_size(map_size);
|
||||
unsafe {
|
||||
env_builder.flag(heed::flags::Flags::MdbNoMetaSync);
|
||||
if !config.metadata_fsync {
|
||||
env_builder.flag(heed::flags::Flags::MdbNoSync);
|
||||
}
|
||||
}
|
||||
let db = match env_builder.open(&db_path) {
|
||||
Err(heed::Error::Io(e)) if e.kind() == std::io::ErrorKind::OutOfMemory => {
|
||||
@@ -208,6 +220,7 @@ impl Garage {
|
||||
let block_manager = BlockManager::new(
|
||||
&db,
|
||||
config.data_dir.clone(),
|
||||
config.data_fsync,
|
||||
config.compression_level,
|
||||
data_rep_param,
|
||||
system.clone(),
|
||||
|
||||
@@ -15,6 +15,13 @@ pub struct Config {
|
||||
/// Path where to store data. Can be slower, but need higher volume
|
||||
pub data_dir: PathBuf,
|
||||
|
||||
/// Whether to fsync after all metadata transactions (disabled by default)
|
||||
#[serde(default)]
|
||||
pub metadata_fsync: bool,
|
||||
/// Whether to fsync after all data block writes (disabled by default)
|
||||
#[serde(default)]
|
||||
pub data_fsync: bool,
|
||||
|
||||
/// Size of data blocks to save to disk
|
||||
#[serde(default = "default_block_size")]
|
||||
pub block_size: usize,
|
||||
|
||||
Reference in New Issue
Block a user