]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/smb: add fruit:nfs_aces=no for macOS compatibility mode 69930/head
authorShwetha Acharya <shwetha174@gmail.com>
Fri, 3 Jul 2026 06:56:34 +0000 (12:26 +0530)
committerShwetha K Acharya <Shwetha.K.Acharya@ibm.com>
Wed, 8 Jul 2026 12:18:58 +0000 (17:48 +0530)
When macOS client compatibility is enabled, add the global Samba
configuration option 'fruit:nfs_aces = no' to disable NFS ACE
handling in the fruit VFS module. This improves compatibility
with macOS SMB clients by preventing conflicts between NFS-style
ACLs and macOS extended attributes.

The configuration is automatically applied when:
- Creating a new cluster with --client-compat=macos
- Updating an existing cluster to macOS mode

Signed-off-by: Shwetha K Acharya <Shwetha.K.Acharya@ibm.com>
src/pybind/mgr/smb/handler.py
src/pybind/mgr/smb/tests/test_handler.py

index a6270243ba92a8a8b226cfef6f6841d0813d70f4..ec081aad4d84a3988b8a2b92f0b27cf66014dfb7 100644 (file)
@@ -1176,6 +1176,11 @@ def _generate_config(conf: _ClusterConf) -> Dict[str, Any]:
     cluster_global_opts['smb ports'] = str(_smb_port(cluster))
     _set_debug_level(cluster_global_opts, conf)
 
+    # Disable NFS ACE handling for macOS compatibility
+    # See https://tracker.ceph.com/issues/78052 for rationale and follow-up.
+    if cluster.is_macos_compatibility_enabled:
+        cluster_global_opts['fruit:nfs_aces'] = 'no'
+
     # Check if cluster has RGW shares and add global RGW options
     has_rgw_shares = any(share.resource.rgw for share in conf.shares)
     if has_rgw_shares:
index eb470cdc4148ed9b7aef20c188dce2354d8883b2..1564605c65571625a4402ce9af42b4376ca76cac 100644 (file)
@@ -1824,3 +1824,91 @@ def test_apply_share_with_qos(thandler):
     assert share_dict['cephfs']['qos']['write_bw_limit'] == "2097152"
     assert share_dict['cephfs']['qos']['read_burst_mult'] == 20
     assert share_dict['cephfs']['qos']['write_burst_mult'] == 15
+
+
+def test_generate_config_macos_compat(thandler):
+    """Test that macOS compatibility adds fruit:nfs_aces = no to global config."""
+    thandler.internal_store.overwrite(
+        {
+            'clusters.foo': {
+                'resource_type': 'ceph.smb.cluster',
+                'cluster_id': 'foo',
+                'auth_mode': 'user',
+                'intent': 'present',
+                'client_compat': 'macos',
+                'user_group_settings': [
+                    {
+                        'source_type': 'empty',
+                    }
+                ],
+            },
+            'shares.foo.s1': {
+                'resource_type': 'ceph.smb.share',
+                'cluster_id': 'foo',
+                'share_id': 's1',
+                'intent': 'present',
+                'name': 'MacShare',
+                'readonly': False,
+                'browseable': True,
+                'cephfs': {
+                    'volume': 'cephfs',
+                    'path': '/',
+                    'provider': 'samba-vfs',
+                },
+            },
+        }
+    )
+
+    thandler._sync_clusters(['foo'])
+    cfg = thandler.public_store['foo', 'config.smb'].get()
+    assert cfg
+    # Verify fruit:nfs_aces is set to 'no' in global options
+    assert cfg['globals']['foo']['options']['fruit:nfs_aces'] == 'no'
+    # Verify VFS modules include fruit and streams_xattr
+    share_vfs = cfg['shares']['MacShare']['options']['vfs objects']
+    assert 'fruit' in share_vfs
+    assert 'streams_xattr' in share_vfs
+
+
+def test_generate_config_default_compat(thandler):
+    """Test that default compatibility does not add fruit:nfs_aces."""
+    thandler.internal_store.overwrite(
+        {
+            'clusters.foo': {
+                'resource_type': 'ceph.smb.cluster',
+                'cluster_id': 'foo',
+                'auth_mode': 'user',
+                'intent': 'present',
+                'client_compat': 'default',
+                'user_group_settings': [
+                    {
+                        'source_type': 'empty',
+                    }
+                ],
+            },
+            'shares.foo.s1': {
+                'resource_type': 'ceph.smb.share',
+                'cluster_id': 'foo',
+                'share_id': 's1',
+                'intent': 'present',
+                'name': 'DefaultShare',
+                'readonly': False,
+                'browseable': True,
+                'cephfs': {
+                    'volume': 'cephfs',
+                    'path': '/',
+                    'provider': 'samba-vfs',
+                },
+            },
+        }
+    )
+
+    thandler._sync_clusters(['foo'])
+    cfg = thandler.public_store['foo', 'config.smb'].get()
+    assert cfg
+    # Verify fruit:nfs_aces is NOT in global options
+    assert 'fruit:nfs_aces' not in cfg['globals']['foo']['options']
+    # Verify VFS modules do NOT include fruit and streams_xattr
+    share_vfs = cfg['shares']['DefaultShare']['options']['vfs objects']
+    assert 'fruit' not in share_vfs
+    assert 'streams_xattr' not in share_vfs