From b9e424bd2241813c54926fc2bf89e2f327a91460 Mon Sep 17 00:00:00 2001 From: Caleb Date: Fri, 6 Dec 2024 09:07:11 -0500 Subject: [PATCH] update iscsi ro prop if zvol readonly changes (cherry picked from commit 9a264ed09b3543395da0176dc6cf7e7bb7a58172) --- .../middlewared/plugins/iscsi_/global_linux.py | 17 +++++++++++++++++ .../middlewared/plugins/pool_/dataset.py | 16 ++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/middlewared/middlewared/plugins/iscsi_/global_linux.py b/src/middlewared/middlewared/plugins/iscsi_/global_linux.py index 4e889eed25e09..4cf85c0db0261 100644 --- a/src/middlewared/middlewared/plugins/iscsi_/global_linux.py +++ b/src/middlewared/middlewared/plugins/iscsi_/global_linux.py @@ -3,6 +3,7 @@ from middlewared.schema import Bool, Dict, Int, Str from middlewared.service import filterable, filterable_returns, private, Service +from middlewared.service_exception import MatchNotFound from middlewared.utils import filter_list, run @@ -94,6 +95,22 @@ def sessions(self, filters, options): sessions.append(session_dict) return filter_list(sessions, filters, options) + @private + def resync_readonly_property_for_zvol(self, id_, read_only_value): + if not self.middleware.call_sync('service.started', 'iscsitarget'): + return + + try: + extent = self.middleware.call_sync( + 'iscsi.extent.query', + [['enabled', '=', True], ['path', '=', f'zvol/{id_}']], + {'get': True} + ) + ro = True if read_only_value.lower() == 'on' else False + self.middleware.call_sync('iscsi.extent.update', extent['id'], {'ro': ro}) + except MatchNotFound: + return + @private def resync_lun_size_for_zvol(self, id_): if not self.middleware.call_sync('service.started', 'iscsitarget'): diff --git a/src/middlewared/middlewared/plugins/pool_/dataset.py b/src/middlewared/middlewared/plugins/pool_/dataset.py index 416a58a74eadc..b40b509c13578 100644 --- a/src/middlewared/middlewared/plugins/pool_/dataset.py +++ b/src/middlewared/middlewared/plugins/pool_/dataset.py @@ -939,10 +939,18 @@ async def do_update(self, audit_callback, id_, data): verrors.add_child('pool_dataset_update', self.__handle_zfs_set_property_error(e, properties_definitions)) raise verrors - if data['type'] == 'VOLUME' and 'volsize' in data and data['volsize'] > dataset[0]['volsize']['parsed']: - # means the zvol size has increased so we need to check if this zvol is shared via SCST (iscsi) - # and if it is, resync it so the connected initiators can see the new size of the zvol - await self.middleware.call('iscsi.global.resync_lun_size_for_zvol', id_) + if data['type'] == 'VOLUME': + if 'volsize' in data and data['volsize'] > dataset[0]['volsize']['parsed']: + # means the zvol size has increased so we need to check if this zvol is shared via SCST (iscsi) + # and if it is, resync it so the connected initiators can see the new size of the zvol + await self.middleware.call('iscsi.global.resync_lun_size_for_zvol', id_) + + if 'readonly' in data: + # depending on the iscsi client connected to us, if someone marks a zvol + # as R/O (or R/W), we need to be sure and update the associated extent so + # that we don't get into a scenario where the iscsi extent is R/W but the + # underlying zvol is R/O. Windows clients seem to not handle this very well. + await self.middleware.call('iscsi.global.resync_readonly_property_for_zvol', id_) updated_ds = await self.get_instance(id_) self.middleware.send_event('pool.dataset.query', 'CHANGED', id=id_, fields=updated_ds)