From af8214d46b81113ae910331d83c1f99e3db0ef01 Mon Sep 17 00:00:00 2001 From: John Mulligan Date: Wed, 28 May 2025 12:55:25 -0400 Subject: [PATCH] mgr/smb: remove restriction on 1MiB smb config objects in rados For convenience I had originally capped the size of objects created by the smb mgr module to 1MiB in order to avoid having to read objects with more than one rados call. This value matched a value hardcoded in the NFS mgr module. However, testers are trying to create a large number of shares and some configurations caused the JSON contents we try to write to a rados object to exceed 1MiB. Implement a _read_all function to allow objects to exceed the chunk size and remove the matching restriction from the write path. I was able to test this change by create 4096 shares. Prior to the change the a traceback similar to the following would occur. After the change it did not occur and I could verify the object in rados was >1MiB. ``` Error EINVAL: Traceback (most recent call last): File "/usr/share/ceph/mgr/mgr_module.py", line 1930, in _handle_command return CLICommand.COMMANDS[cmd['prefix']].call(self, cmd, inbuf) File "/usr/share/ceph/mgr/mgr_module.py", line 527, in call return self.func(mgr, **kwargs) File "/usr/share/ceph/mgr/object_format.py", line 592, in _format_response robj = f(*args, **kwargs) File "/usr/share/ceph/mgr/smb/module.py", line 148, in apply_resources return self._handler.apply(resources.load_text(inbuf)) File "/usr/share/ceph/mgr/smb/handler.py", line 412, in apply self._sync_modified(results) File "/usr/share/ceph/mgr/smb/handler.py", line 580, in _sync_modified self._sync_clusters(cluster_ids) File "/usr/share/ceph/mgr/smb/handler.py", line 564, in _sync_clusters self._save_cluster_settings(change_group) File "/usr/share/ceph/mgr/smb/handler.py", line 640, in _save_cluster_settings _save_pending_config( File "/usr/share/ceph/mgr/smb/handler.py", line 1397, in _save_pending_config centry.set(cconfig) File "/usr/share/ceph/mgr/smb/rados_store.py", line 89, in set self.write(json.dumps(obj)) File "/usr/share/ceph/mgr/smb/rados_store.py", line 71, in write assert len(data) < _CHUNK_SIZE AssertionError ``` Signed-off-by: John Mulligan --- src/pybind/mgr/smb/rados_store.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/pybind/mgr/smb/rados_store.py b/src/pybind/mgr/smb/rados_store.py index 8896350ee412c..9ac99645a65b5 100644 --- a/src/pybind/mgr/smb/rados_store.py +++ b/src/pybind/mgr/smb/rados_store.py @@ -27,6 +27,21 @@ SMB_POOL = '.smb' log = logging.getLogger(__name__) +def _read_all( + ioctx: rados.Ioctx, key: str, chunk_size: int = _CHUNK_SIZE +) -> bytearray: + """Read all of the data in the rados object.""" + idx = 0 + ba = bytearray() + while True: + chunk = ioctx.read(key, chunk_size, idx * chunk_size) + ba += chunk + if len(chunk) < _CHUNK_SIZE: + break + idx += 1 + return ba + + class RADOSConfigEntry: """A store entry object for the RADOS pool based store.""" @@ -58,7 +73,7 @@ class RADOSConfigEntry: with self._shared_ioctx() as ioctx: ioctx.set_namespace(self._ns) try: - val = ioctx.read(self._key, _CHUNK_SIZE).decode() + val = _read_all(ioctx, self._key).decode() except rados.ObjectNotFound: val = '' log.debug('rados read result of %s = %r', self.full_key, val) @@ -67,8 +82,7 @@ class RADOSConfigEntry: def write(self, content: str) -> None: """Write a RADOS object.""" log.debug('rados write to %s', self.full_key) - data = content.encode('utf-8') - assert len(data) < _CHUNK_SIZE + data = content.encode() with self._shared_ioctx() as ioctx: ioctx.set_namespace(self._ns) ioctx.write_full(self._key, data) -- 2.39.5