From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id DEE251FF0E3 for ; Tue, 04 Aug 2026 14:40:44 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id A6354216C4; Tue, 04 Aug 2026 14:40:44 +0200 (CEST) From: Shan Shaji To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup 1/3] partially fix #6933: ui: storage: add option to specify zfs recordsize Date: Tue, 4 Aug 2026 14:40:19 +0200 Message-ID: <20260804124021.83704-2-s.shaji@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260804124021.83704-1-s.shaji@proxmox.com> References: <20260804124021.83704-1-s.shaji@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1785847228235 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.119 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_LOW -0.7 Sender listed at https://www.dnswl.org/, low trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: DJYEKCOD73GAIYT2S2UWV6V4IPIAAXHO X-Message-ID-Hash: DJYEKCOD73GAIYT2S2UWV6V4IPIAAXHO X-MailFrom: s.shaji@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: 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 --- 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 { type: bool, optional: true, }, + recordsize: { + schema: ZFS_RECORD_SIZE_SCHEMA, + optional: true, + } }, }, returns: { @@ -155,6 +159,7 @@ pub fn create_zpool( compression: Option, ashift: Option, add_datastore: Option, + recordsize: Option, rpcenv: &mut dyn RpcEnvironment, ) -> Result { 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