]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/smb: remove restriction on 1MiB smb config objects in rados 63562/head
authorJohn Mulligan <jmulligan@redhat.com>
Wed, 28 May 2025 16:55:25 +0000 (12:55 -0400)
committerJohn Mulligan <jmulligan@redhat.com>
Wed, 28 May 2025 16:55:25 +0000 (12:55 -0400)
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 <jmulligan@redhat.com>
src/pybind/mgr/smb/rados_store.py

index 8896350ee412c4670fe73acd7136b578467d7dc8..9ac99645a65b58882fcaf88350ac1f524bd600f3 100644 (file)
@@ -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)