* [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize
@ 2026-08-12 11:03 Shan Shaji
2026-08-12 11:03 ` [PATCH proxmox-backup v2 1/3] partially fix #6933: ui: storage: " Shan Shaji
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Shan Shaji @ 2026-08-12 11:03 UTC (permalink / raw)
To: pbs-devel
The option to specify the `recordsize` was previously available neither
in the UI nor in the CLI. Users had to configure it manually using the
ZFS CLI. This series adds an option for specifying the `recordsize`
through both the UI and `proxmox-backup-manager` when creating storage.
Since adding support for editing this property at the dataset level
would require more changes, I am sending the creation related
changes first. Support for editing the property will be send
as a separate series.
changes since v1: Thanks @Nicolas Frey
* Patch [3/3] - Add validation function identical to the one in Javscript to
verify if the passed recordsize is valid. If it's not valid, then the
backup manager exits without creating the pool. Earlier, even though
the recordsize format was wrong, the backup manager allowed executing
the zpool and zfs commands, which in turn created the pool with the
default(128k) recordsize, but the `zfs set` command failed with an error.
References:
- https://openzfs.github.io/openzfs-docs/Performance%20and%20Tuning/Workload%20Tuning.html#dataset-recordsize
proxmox-backup:
Shan Shaji (2):
partially fix #6933: ui: storage: add option to specify zfs recordsize
partially fix #6933: bin: add option to specify ZFS recordsize
src/api2/node/disks/zfs.rs | 14 +++++++++++--
src/bin/proxmox_backup_manager/disk.rs | 8 ++++++--
www/Utils.js | 28 ++++++++++++++++++++++++++
www/window/ZFSCreate.js | 8 ++++++++
4 files changed, 54 insertions(+), 4 deletions(-)
proxmox:
Shan Shaji (1):
pbs-api-types: zfs: define schema for recordsize
pbs-api-types/src/zfs.rs | 68 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
Summary over all repositories:
5 files changed, 122 insertions(+), 4 deletions(-)
--
Generated by murpp 0.10.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH proxmox-backup v2 1/3] partially fix #6933: ui: storage: add option to specify zfs recordsize
2026-08-12 11:03 [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize Shan Shaji
@ 2026-08-12 11:03 ` Shan Shaji
2026-08-12 11:03 ` [PATCH proxmox-backup v2 2/3] partially fix #6933: bin: add option to specify ZFS recordsize Shan Shaji
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Shan Shaji @ 2026-08-12 11:03 UTC (permalink / raw)
To: pbs-devel
Earlier, to change the recordsize of an zfs storage dataset the users
had to use the `zfs` cli. Improved this by adding an option to specify
the recordsize while creating the storage. By default the recordsize is
set at 128KB.
Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
---
no changes since v1
src/api2/node/disks/zfs.rs | 14 ++++++++++++--
www/Utils.js | 28 ++++++++++++++++++++++++++++
www/window/ZFSCreate.js | 8 ++++++++
3 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/src/api2/node/disks/zfs.rs b/src/api2/node/disks/zfs.rs
index 7a62e3f70..43d0ce259 100644
--- a/src/api2/node/disks/zfs.rs
+++ b/src/api2/node/disks/zfs.rs
@@ -7,8 +7,8 @@ use proxmox_schema::api;
use pbs_api_types::{
DATASTORE_SCHEMA, DISK_ARRAY_SCHEMA, DISK_LIST_SCHEMA, DataStoreConfig, NODE_SCHEMA,
- PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, UPID_SCHEMA, ZFS_ASHIFT_SCHEMA, ZPOOL_NAME_SCHEMA,
- ZfsCompressionType, ZfsRaidLevel, ZpoolListItem,
+ PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, UPID_SCHEMA, ZFS_ASHIFT_SCHEMA, ZFS_RECORD_SIZE_SCHEMA,
+ ZPOOL_NAME_SCHEMA, ZfsCompressionType, ZfsRaidLevel, ZpoolListItem,
};
use crate::tools::disks::{
@@ -138,6 +138,10 @@ pub fn zpool_details(name: String) -> Result<Value, Error> {
type: bool,
optional: true,
},
+ recordsize: {
+ schema: ZFS_RECORD_SIZE_SCHEMA,
+ optional: true,
+ }
},
},
returns: {
@@ -155,6 +159,7 @@ pub fn create_zpool(
compression: Option<String>,
ashift: Option<usize>,
add_datastore: Option<bool>,
+ recordsize: Option<String>,
rpcenv: &mut dyn RpcEnvironment,
) -> Result<String, Error> {
let to_stdout = rpcenv.env_type() == RpcEnvironmentType::CLI;
@@ -292,6 +297,11 @@ pub fn create_zpool(
if let Some(compression) = compression {
command.arg(format!("compression={compression}"));
}
+
+ if let Some(recordsize) = recordsize {
+ command.arg(format!("recordsize={recordsize}"));
+ }
+
command.args(["relatime=on", &name]);
info!("# {command:?}");
match proxmox_sys::command::run_command(command, None) {
diff --git a/www/Utils.js b/www/Utils.js
index d6bfd459e..1c96bd0b3 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -395,6 +395,34 @@ Ext.define('PBS.Utils', {
return cls;
},
+ validateZfsRecordSize: function (value) {
+ if (!value) {
+ return true;
+ }
+
+ let match = value.match(/^([1-9][0-9]*)([km])?$/i);
+ if (!match) {
+ return gettext(
+ 'Invalid format. Use numbers with optional k or m suffix (e.g., 16k).',
+ );
+ }
+
+ let bytes = parseInt(match[1], 10);
+ let suffix = match[2]?.toLowerCase();
+
+ if (suffix === 'k') {
+ bytes *= 1024;
+ } else if (suffix === 'm') {
+ bytes *= 1024 * 1024;
+ }
+
+ if (bytes < 512 || (bytes & (bytes - 1)) !== 0 || bytes > 16 * 1024 * 1024) {
+ return gettext('Value must be a power of 2 between 512 and 16m');
+ }
+
+ return true;
+ },
+
constructor: function () {
var me = this;
diff --git a/www/window/ZFSCreate.js b/www/window/ZFSCreate.js
index 9a32bd5f3..7dcffc1b8 100644
--- a/www/window/ZFSCreate.js
+++ b/www/window/ZFSCreate.js
@@ -72,6 +72,14 @@ Ext.define('PBS.window.CreateZFS', {
value: '12',
name: 'ashift',
},
+ {
+ xtype: 'proxmoxtextfield',
+ name: 'recordsize',
+ fieldLabel: gettext('Record Size'),
+ allowBlank: true,
+ validator: PBS.Utils.validateZfsRecordSize,
+ emptyText: '128k'
+ },
],
columnB: [
{
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH proxmox-backup v2 2/3] partially fix #6933: bin: add option to specify ZFS recordsize
2026-08-12 11:03 [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize Shan Shaji
2026-08-12 11:03 ` [PATCH proxmox-backup v2 1/3] partially fix #6933: ui: storage: " Shan Shaji
@ 2026-08-12 11:03 ` Shan Shaji
2026-08-12 11:03 ` [PATCH proxmox v2 3/3] pbs-api-types: zfs: define schema for recordsize Shan Shaji
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Shan Shaji @ 2026-08-12 11:03 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
---
** No changes since v1 **
src/bin/proxmox_backup_manager/disk.rs | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/bin/proxmox_backup_manager/disk.rs b/src/bin/proxmox_backup_manager/disk.rs
index 258c5dfbd..91f738783 100644
--- a/src/bin/proxmox_backup_manager/disk.rs
+++ b/src/bin/proxmox_backup_manager/disk.rs
@@ -6,8 +6,7 @@ use proxmox_schema::api;
use std::io::IsTerminal;
use pbs_api_types::{
- BLOCKDEVICE_DISK_AND_PARTITION_NAME_SCHEMA, BLOCKDEVICE_NAME_SCHEMA, DATASTORE_SCHEMA,
- DISK_LIST_SCHEMA, ZFS_ASHIFT_SCHEMA, ZfsCompressionType, ZfsRaidLevel,
+ BLOCKDEVICE_DISK_AND_PARTITION_NAME_SCHEMA, BLOCKDEVICE_NAME_SCHEMA, DATASTORE_SCHEMA, DISK_LIST_SCHEMA, ZFS_ASHIFT_SCHEMA, ZFS_RECORD_SIZE_SCHEMA, ZfsCompressionType, ZfsRaidLevel
};
use proxmox_backup::tools::disks::{
FileSystemType, SmartAttribute, complete_disk_name, complete_partition_name,
@@ -204,6 +203,11 @@ async fn wipe_disk(mut param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<
type: bool,
optional: true,
},
+ recordsize: {
+ schema: ZFS_RECORD_SIZE_SCHEMA,
+ optional: true,
+ }
+
},
},
)]
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH proxmox v2 3/3] pbs-api-types: zfs: define schema for recordsize
2026-08-12 11:03 [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize Shan Shaji
2026-08-12 11:03 ` [PATCH proxmox-backup v2 1/3] partially fix #6933: ui: storage: " Shan Shaji
2026-08-12 11:03 ` [PATCH proxmox-backup v2 2/3] partially fix #6933: bin: add option to specify ZFS recordsize Shan Shaji
@ 2026-08-12 11:03 ` Shan Shaji
2026-08-12 13:41 ` Nicolas Frey
2026-08-12 13:41 ` [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize Nicolas Frey
2026-08-12 14:42 ` superseded: " Shan Shaji
4 siblings, 1 reply; 8+ messages in thread
From: Shan Shaji @ 2026-08-12 11:03 UTC (permalink / raw)
To: pbs-devel
add schema and verifcation function for recordsize to check against
allowed zfs constraints. Without the verification function the dataset
will be created using the default 128k recordsize.
Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
---
changes since v1: Please see the cover letter.
pbs-api-types/src/zfs.rs | 68 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/pbs-api-types/src/zfs.rs b/pbs-api-types/src/zfs.rs
index 2cfbd403..dea84b2e 100644
--- a/pbs-api-types/src/zfs.rs
+++ b/pbs-api-types/src/zfs.rs
@@ -1,3 +1,4 @@
+use anyhow::{Error, bail};
use serde::{Deserialize, Serialize};
#[cfg(feature = "enum-fallback")]
@@ -6,6 +7,7 @@ use proxmox_schema::*;
const_regex! {
pub ZPOOL_NAME_REGEX = r"^[a-zA-Z][a-z0-9A-Z\-_.:]+$";
+ ZFS_RECORD_SIZE_REGEX = r"^(?i)([1-9][0-9]*)([km])?$";
}
pub const ZFS_ASHIFT_SCHEMA: Schema = IntegerSchema::new("Pool sector size exponent.")
@@ -18,6 +20,39 @@ pub const ZPOOL_NAME_SCHEMA: Schema = StringSchema::new("ZFS Pool Name")
.format(&ApiStringFormat::Pattern(&ZPOOL_NAME_REGEX))
.schema();
+fn verify_zfs_recordsize(value: &str) -> Result<(), Error> {
+ if let Some(caps) = ZFS_RECORD_SIZE_REGEX.captures(value) {
+ let range_error = "Value must be a power of 2 between 512 and 16m";
+
+ let Ok(number) = caps[1].parse::<u32>() else {
+ bail!(range_error);
+ };
+
+ let multiplier = match caps.get(2).map(|v| v.as_str()) {
+ Some(suffix) if suffix.eq_ignore_ascii_case("k") => 1024,
+ Some(suffix) if suffix.eq_ignore_ascii_case("m") => 1024 * 1024,
+ _ => 1,
+ };
+
+ let bytes = number
+ .checked_mul(multiplier)
+ .filter(|&b| b.is_power_of_two() && (512..=16 * 1024 * 1024).contains(&b));
+
+ if bytes.is_none() {
+ bail!(range_error);
+ }
+
+ Ok(())
+ } else {
+ bail!("Invalid format. Use numbers with optional k or m suffix (e.g., 16k).")
+ }
+}
+
+pub const ZFS_RECORD_SIZE_SCHEMA: Schema =
+ StringSchema::new("ZFS Recordsize. Use numbers with optional k or m suffix (e.g., 128k).")
+ .format(&ApiStringFormat::VerifyFn(verify_zfs_recordsize))
+ .schema();
+
#[api(default: "On")]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
@@ -84,3 +119,36 @@ pub struct ZpoolListItem {
/// ZFS deduplication ratio
pub dedup: f64,
}
+
+#[cfg(test)]
+mod tests {
+
+ use super::verify_zfs_recordsize;
+
+ #[test]
+ fn test_zfs_record_size_verify_fn() {
+ let format_error = "Invalid format. Use numbers with optional k or m suffix (e.g., 16k).";
+ let range_error = "Value must be a power of 2 between 512 and 16m";
+
+ let valid_inputs = ["512", "1024", "16m", "16384k", "16777216"];
+ for input in valid_inputs {
+ assert!(verify_zfs_recordsize(input).is_ok());
+ }
+
+ let range_error_inputs = ["31m", "256", "31m", "32m", "4294967297"];
+ for input in range_error_inputs {
+ assert_eq!(
+ verify_zfs_recordsize(input).unwrap_err().to_string(),
+ range_error
+ );
+ }
+
+ let format_error_inputs = ["0", "k12", "16g", "1.5m", "-512", "0512"];
+ for input in format_error_inputs {
+ assert_eq!(
+ verify_zfs_recordsize(input).unwrap_err().to_string(),
+ format_error
+ );
+ }
+ }
+}
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize
2026-08-12 11:03 [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize Shan Shaji
` (2 preceding siblings ...)
2026-08-12 11:03 ` [PATCH proxmox v2 3/3] pbs-api-types: zfs: define schema for recordsize Shan Shaji
@ 2026-08-12 13:41 ` Nicolas Frey
2026-08-12 14:42 ` superseded: " Shan Shaji
4 siblings, 0 replies; 8+ messages in thread
From: Nicolas Frey @ 2026-08-12 13:41 UTC (permalink / raw)
To: Shan Shaji, pbs-devel
On Wed Aug 12, 2026 at 1:03 PM CEST, Shan Shaji wrote:
> The option to specify the `recordsize` was previously available neither
> in the UI nor in the CLI. Users had to configure it manually using the
> ZFS CLI. This series adds an option for specifying the `recordsize`
> through both the UI and `proxmox-backup-manager` when creating storage.
>
> Since adding support for editing this property at the dataset level
> would require more changes, I am sending the creation related
> changes first. Support for editing the property will be send
> as a separate series.
>
> changes since v1: Thanks @Nicolas Frey
>
> * Patch [3/3] - Add validation function identical to the one in Javscript to
> verify if the passed recordsize is valid. If it's not valid, then the
> backup manager exits without creating the pool. Earlier, even though
> the recordsize format was wrong, the backup manager allowed executing
> the zpool and zfs commands, which in turn created the pool with the
> default(128k) recordsize, but the `zfs set` command failed with an error.
thanks for sending a v2! one small style nit on patch [3/3]. consider this:
Reviewed-by: Nicolas Frey <n.frey@proxmox.com>
Tested-by: Nicolas Frey <n.frey@proxmox.com>
>
> References:
> - https://openzfs.github.io/openzfs-docs/Performance%20and%20Tuning/Workload%20Tuning.html#dataset-recordsize
>
> proxmox-backup:
>
> Shan Shaji (2):
> partially fix #6933: ui: storage: add option to specify zfs recordsize
> partially fix #6933: bin: add option to specify ZFS recordsize
>
> src/api2/node/disks/zfs.rs | 14 +++++++++++--
> src/bin/proxmox_backup_manager/disk.rs | 8 ++++++--
> www/Utils.js | 28 ++++++++++++++++++++++++++
> www/window/ZFSCreate.js | 8 ++++++++
> 4 files changed, 54 insertions(+), 4 deletions(-)
>
>
> proxmox:
>
> Shan Shaji (1):
> pbs-api-types: zfs: define schema for recordsize
>
> pbs-api-types/src/zfs.rs | 68 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 68 insertions(+)
>
>
> Summary over all repositories:
> 5 files changed, 122 insertions(+), 4 deletions(-)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH proxmox v2 3/3] pbs-api-types: zfs: define schema for recordsize
2026-08-12 11:03 ` [PATCH proxmox v2 3/3] pbs-api-types: zfs: define schema for recordsize Shan Shaji
@ 2026-08-12 13:41 ` Nicolas Frey
2026-08-12 13:55 ` Shan Shaji
0 siblings, 1 reply; 8+ messages in thread
From: Nicolas Frey @ 2026-08-12 13:41 UTC (permalink / raw)
To: Shan Shaji, pbs-devel
thanks for the v2 and adding a test! one small style nit inline
On Wed Aug 12, 2026 at 1:03 PM CEST, Shan Shaji wrote:
> add schema and verifcation function for recordsize to check against
> allowed zfs constraints. Without the verification function the dataset
> will be created using the default 128k recordsize.
>
> Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
> ---
>
> changes since v1: Please see the cover letter.
>
> pbs-api-types/src/zfs.rs | 68 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 68 insertions(+)
>
> diff --git a/pbs-api-types/src/zfs.rs b/pbs-api-types/src/zfs.rs
> index 2cfbd403..dea84b2e 100644
> --- a/pbs-api-types/src/zfs.rs
> +++ b/pbs-api-types/src/zfs.rs
> @@ -1,3 +1,4 @@
> +use anyhow::{Error, bail};
> use serde::{Deserialize, Serialize};
>
> #[cfg(feature = "enum-fallback")]
> @@ -6,6 +7,7 @@ use proxmox_schema::*;
>
> const_regex! {
> pub ZPOOL_NAME_REGEX = r"^[a-zA-Z][a-z0-9A-Z\-_.:]+$";
> + ZFS_RECORD_SIZE_REGEX = r"^(?i)([1-9][0-9]*)([km])?$";
> }
>
> pub const ZFS_ASHIFT_SCHEMA: Schema = IntegerSchema::new("Pool sector size exponent.")
> @@ -18,6 +20,39 @@ pub const ZPOOL_NAME_SCHEMA: Schema = StringSchema::new("ZFS Pool Name")
> .format(&ApiStringFormat::Pattern(&ZPOOL_NAME_REGEX))
> .schema();
>
> +fn verify_zfs_recordsize(value: &str) -> Result<(), Error> {
> + if let Some(caps) = ZFS_RECORD_SIZE_REGEX.captures(value) {
nit: you could instead use `let Some(x)` so the whole block does not need to be nested:
let Some(caps) = ZFS_RECORD_SIZE_REGEX.captures(value) else {
bail!("Invalid format. Use numbers with optional k or m suffix (e.g., 16k).");
};
.. rest of the code
though no need to send a v3 for it, as it's just a style nit
> + let range_error = "Value must be a power of 2 between 512 and 16m";
> +
> + let Ok(number) = caps[1].parse::<u32>() else {
> + bail!(range_error);
> + };
> +
> + let multiplier = match caps.get(2).map(|v| v.as_str()) {
> + Some(suffix) if suffix.eq_ignore_ascii_case("k") => 1024,
> + Some(suffix) if suffix.eq_ignore_ascii_case("m") => 1024 * 1024,
> + _ => 1,
> + };
> +
> + let bytes = number
> + .checked_mul(multiplier)
> + .filter(|&b| b.is_power_of_two() && (512..=16 * 1024 * 1024).contains(&b));
> +
> + if bytes.is_none() {
> + bail!(range_error);
> + }
> +
> + Ok(())
> + } else {
> + bail!("Invalid format. Use numbers with optional k or m suffix (e.g., 16k).")
> + }
> +}
> +
> +pub const ZFS_RECORD_SIZE_SCHEMA: Schema =
> + StringSchema::new("ZFS Recordsize. Use numbers with optional k or m suffix (e.g., 128k).")
> + .format(&ApiStringFormat::VerifyFn(verify_zfs_recordsize))
> + .schema();
> +
> #[api(default: "On")]
> #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
> #[serde(rename_all = "lowercase")]
> @@ -84,3 +119,36 @@ pub struct ZpoolListItem {
> /// ZFS deduplication ratio
> pub dedup: f64,
> }
> +
> +#[cfg(test)]
> +mod tests {
> +
> + use super::verify_zfs_recordsize;
> +
> + #[test]
> + fn test_zfs_record_size_verify_fn() {
> + let format_error = "Invalid format. Use numbers with optional k or m suffix (e.g., 16k).";
> + let range_error = "Value must be a power of 2 between 512 and 16m";
> +
> + let valid_inputs = ["512", "1024", "16m", "16384k", "16777216"];
> + for input in valid_inputs {
> + assert!(verify_zfs_recordsize(input).is_ok());
> + }
> +
> + let range_error_inputs = ["31m", "256", "31m", "32m", "4294967297"];
> + for input in range_error_inputs {
> + assert_eq!(
> + verify_zfs_recordsize(input).unwrap_err().to_string(),
> + range_error
> + );
> + }
> +
> + let format_error_inputs = ["0", "k12", "16g", "1.5m", "-512", "0512"];
> + for input in format_error_inputs {
> + assert_eq!(
> + verify_zfs_recordsize(input).unwrap_err().to_string(),
> + format_error
> + );
> + }
> + }
> +}
thanks for adding a test too!
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH proxmox v2 3/3] pbs-api-types: zfs: define schema for recordsize
2026-08-12 13:41 ` Nicolas Frey
@ 2026-08-12 13:55 ` Shan Shaji
0 siblings, 0 replies; 8+ messages in thread
From: Shan Shaji @ 2026-08-12 13:55 UTC (permalink / raw)
To: Nicolas Frey, pbs-devel
Hi,
Thanks for testing and verifying the code changes.
On Wed Aug 12, 2026 at 3:41 PM CEST, Nicolas Frey wrote:
> thanks for the v2 and adding a test! one small style nit inline
>
> On Wed Aug 12, 2026 at 1:03 PM CEST, Shan Shaji wrote:
>> add schema and verifcation function for recordsize to check against
>> allowed zfs constraints. Without the verification function the dataset
>> will be created using the default 128k recordsize.
>>
>> Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
>> ---
>>
>> changes since v1: Please see the cover letter.
>>
>> pbs-api-types/src/zfs.rs | 68 ++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 68 insertions(+)
>>
>> diff --git a/pbs-api-types/src/zfs.rs b/pbs-api-types/src/zfs.rs
>> index 2cfbd403..dea84b2e 100644
>> --- a/pbs-api-types/src/zfs.rs
>> +++ b/pbs-api-types/src/zfs.rs
>> @@ -1,3 +1,4 @@
>> +use anyhow::{Error, bail};
>> use serde::{Deserialize, Serialize};
>>
>> #[cfg(feature = "enum-fallback")]
>> @@ -6,6 +7,7 @@ use proxmox_schema::*;
>>
>> const_regex! {
>> pub ZPOOL_NAME_REGEX = r"^[a-zA-Z][a-z0-9A-Z\-_.:]+$";
>> + ZFS_RECORD_SIZE_REGEX = r"^(?i)([1-9][0-9]*)([km])?$";
>> }
>>
>> pub const ZFS_ASHIFT_SCHEMA: Schema = IntegerSchema::new("Pool sector size exponent.")
>> @@ -18,6 +20,39 @@ pub const ZPOOL_NAME_SCHEMA: Schema = StringSchema::new("ZFS Pool Name")
>> .format(&ApiStringFormat::Pattern(&ZPOOL_NAME_REGEX))
>> .schema();
>>
>> +fn verify_zfs_recordsize(value: &str) -> Result<(), Error> {
>> + if let Some(caps) = ZFS_RECORD_SIZE_REGEX.captures(value) {
>
> nit: you could instead use `let Some(x)` so the whole block does not need to be nested:
>
> let Some(caps) = ZFS_RECORD_SIZE_REGEX.captures(value) else {
> bail!("Invalid format. Use numbers with optional k or m suffix (e.g., 16k).");
> };
ahh, right! this is much more cleaner. I did used `let..else` inside the block
but didn't change it here.
> .. rest of the code
>
> though no need to send a v3 for it, as it's just a style nit
>> + let range_error = "Value must be a power of 2 between 512 and 16m";
>> +
>> + let Ok(number) = caps[1].parse::<u32>() else {
>> + bail!(range_error);
>> + };
^^^^ here
>> + let multiplier = match caps.get(2).map(|v| v.as_str()) {
>> + Some(suffix) if suffix.eq_ignore_ascii_case("k") => 1024,
>> + Some(suffix) if suffix.eq_ignore_ascii_case("m") => 1024 * 1024,
>> + _ => 1,
>> + };
>> +
>> + let bytes = number
>> + .checked_mul(multiplier)
>> + .filter(|&b| b.is_power_of_two() && (512..=16 * 1024 * 1024).contains(&b));
>> +
>> + if bytes.is_none() {
>> + bail!(range_error);
>> + }
>> +
>> + Ok(())
>> + } else {
>> + bail!("Invalid format. Use numbers with optional k or m suffix (e.g., 16k).")
>> + }
>> +}
>> +
>> +pub const ZFS_RECORD_SIZE_SCHEMA: Schema =
>> + StringSchema::new("ZFS Recordsize. Use numbers with optional k or m suffix (e.g., 128k).")
>> + .format(&ApiStringFormat::VerifyFn(verify_zfs_recordsize))
>> + .schema();
>> +
>> #[api(default: "On")]
>> #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
>> #[serde(rename_all = "lowercase")]
>> @@ -84,3 +119,36 @@ pub struct ZpoolListItem {
>> /// ZFS deduplication ratio
>> pub dedup: f64,
>> }
>> +
>> +#[cfg(test)]
>> +mod tests {
>> +
>> + use super::verify_zfs_recordsize;
>> +
>> + #[test]
>> + fn test_zfs_record_size_verify_fn() {
>> + let format_error = "Invalid format. Use numbers with optional k or m suffix (e.g., 16k).";
>> + let range_error = "Value must be a power of 2 between 512 and 16m";
>> +
>> + let valid_inputs = ["512", "1024", "16m", "16384k", "16777216"];
>> + for input in valid_inputs {
>> + assert!(verify_zfs_recordsize(input).is_ok());
>> + }
>> +
>> + let range_error_inputs = ["31m", "256", "31m", "32m", "4294967297"];
>> + for input in range_error_inputs {
>> + assert_eq!(
>> + verify_zfs_recordsize(input).unwrap_err().to_string(),
>> + range_error
>> + );
>> + }
>> +
>> + let format_error_inputs = ["0", "k12", "16g", "1.5m", "-512", "0512"];
>> + for input in format_error_inputs {
>> + assert_eq!(
>> + verify_zfs_recordsize(input).unwrap_err().to_string(),
>> + format_error
>> + );
>> + }
>> + }
>> +}
>
> thanks for adding a test too!
^ permalink raw reply [flat|nested] 8+ messages in thread
* superseded: Re: [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize
2026-08-12 11:03 [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize Shan Shaji
` (3 preceding siblings ...)
2026-08-12 13:41 ` [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize Nicolas Frey
@ 2026-08-12 14:42 ` Shan Shaji
4 siblings, 0 replies; 8+ messages in thread
From: Shan Shaji @ 2026-08-12 14:42 UTC (permalink / raw)
To: Shan Shaji, pbs-devel
superseded by v3: https://lore.proxmox.com/pbs-devel/20260812144029.129970-1-s.shaji@proxmox.com/T/#t
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-08-12 14:42 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-12 11:03 [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize Shan Shaji
2026-08-12 11:03 ` [PATCH proxmox-backup v2 1/3] partially fix #6933: ui: storage: " Shan Shaji
2026-08-12 11:03 ` [PATCH proxmox-backup v2 2/3] partially fix #6933: bin: add option to specify ZFS recordsize Shan Shaji
2026-08-12 11:03 ` [PATCH proxmox v2 3/3] pbs-api-types: zfs: define schema for recordsize Shan Shaji
2026-08-12 13:41 ` Nicolas Frey
2026-08-12 13:55 ` Shan Shaji
2026-08-12 13:41 ` [PATCH proxmox{-backup,} v2 0/3] partially fix #6933: add option to specify zfs recordsize Nicolas Frey
2026-08-12 14:42 ` superseded: " Shan Shaji
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox