diff --git a/cinder/tests/unit/volume/drivers/test_rbd.py b/cinder/tests/unit/volume/drivers/test_rbd.py
index f80f165ef66..83399c4954f 100644
--- a/cinder/tests/unit/volume/drivers/test_rbd.py
+++ b/cinder/tests/unit/volume/drivers/test_rbd.py
@@ -2006,6 +2006,63 @@ class RBDTestCase(test.TestCase):
         # Make sure the exception was raised
         self.assertEqual([self.mock_rbd.ImageExists], RAISED_EXCEPTIONS)
 
+    @common_mocks
+    def test_get_manageable_snapshots(self):
+        cinder_snaps = [{'id': '00000000-0000-0000-0000-000000000000',
+                         'volume_id': '11111111-1111-1111-1111-111111111111'}]
+        vols = ['volume-11111111-1111-1111-1111-111111111111', 'vol1']
+        self.mock_rbd.RBD.return_value.list.return_value = vols
+        image = self.mock_proxy.return_value.__enter__.return_value
+        image.list_snaps.side_effect = [
+            [{'id': 1, 'name': 'snapshot-00000000-0000-0000-0000-000000000000',
+              'size': 2 * units.Gi},
+             {'id': 2, 'name': 'snap1', 'size': 6 * units.Gi},
+             {'id': 3, 'size': 8 * units.Gi,
+              'name': 'volume-22222222-2222-2222-2222-222222222222.clone_snap'
+              },
+             {'id': 4, 'size': 5 * units.Gi,
+              'name': 'backup.33333333-3333-3333-3333-333333333333.snap.123'}],
+            [{'id': 1, 'name': 'snap2', 'size': 4 * units.Gi}]]
+        res = self.driver.get_manageable_snapshots(
+            cinder_snaps, None, 1000, 0, ['size'], ['desc'])
+        exp = [
+            {'size': 8, 'safe_to_manage': False, 'extra_info': None,
+             'reason_not_safe': 'used for clone snap', 'cinder_id': None,
+             'reference': {
+                 'source-name':
+                     'volume-22222222-2222-2222-2222-222222222222.clone_snap'},
+             'source_reference': {
+                 'source-name': 'volume-11111111-1111-1111-1111-111111111111'}
+             },
+            {'size': 6, 'safe_to_manage': True, 'extra_info': None,
+             'reason_not_safe': None, 'cinder_id': None,
+             'reference': {'source-name': 'snap1'},
+             'source_reference': {
+                 'source-name': 'volume-11111111-1111-1111-1111-111111111111'}
+             },
+            {'size': 5, 'safe_to_manage': False, 'extra_info': None,
+             'reason_not_safe': 'used for volume backup', 'cinder_id': None,
+             'reference': {
+                 'source-name':
+                     'backup.33333333-3333-3333-3333-333333333333.snap.123'},
+             'source_reference': {
+                 'source-name': 'volume-11111111-1111-1111-1111-111111111111'}
+             },
+            {'size': 4, 'safe_to_manage': True, 'extra_info': None,
+             'reason_not_safe': None, 'cinder_id': None,
+             'reference': {'source-name': 'snap2'},
+             'source_reference': {'source-name': 'vol1'}
+             },
+            {'size': 2, 'safe_to_manage': False, 'extra_info': None,
+             'reason_not_safe': 'already managed',
+             'cinder_id': '00000000-0000-0000-0000-000000000000',
+             'reference': {'source-name':
+                           'snapshot-00000000-0000-0000-0000-000000000000'},
+             'source_reference': {
+                 'source-name': 'volume-11111111-1111-1111-1111-111111111111'}
+             }]
+        self.assertEqual(exp, res)
+
     @common_mocks
     def test_unmanage_snapshot(self):
         proxy = self.mock_proxy.return_value
diff --git a/cinder/volume/drivers/rbd.py b/cinder/volume/drivers/rbd.py
index ec1ef53c4ee..fa1bd5dab85 100644
--- a/cinder/volume/drivers/rbd.py
+++ b/cinder/volume/drivers/rbd.py
@@ -1770,6 +1770,57 @@ class RBDDriver(driver.CloneableImageVD, driver.MigrateVD,
             if not volume.is_protected_snap(snapshot.name):
                 volume.protect_snap(snapshot.name)
 
+    def get_manageable_snapshots(self, cinder_snapshots, marker, limit, offset,
+                                 sort_keys, sort_dirs):
+        """List manageable snapshots on RBD backend."""
+        manageable_snapshots = []
+        cinder_snapshot_ids = [resource['id'] for resource in cinder_snapshots]
+
+        with RADOSClient(self) as client:
+            for image_name in self.RBDProxy().list(client.ioctx):
+                with RBDVolumeProxy(self, image_name, read_only=True,
+                                    client=client.cluster,
+                                    ioctx=client.ioctx) as image:
+                    try:
+                        for snapshot in image.list_snaps():
+                            snapshot_id = (
+                                volume_utils.extract_id_from_snapshot_name(
+                                    snapshot['name']))
+                            snapshot_info = {
+                                'reference': {'source-name': snapshot['name']},
+                                'size': int(math.ceil(
+                                    float(snapshot['size']) / units.Gi)),
+                                'cinder_id': None,
+                                'extra_info': None,
+                                'safe_to_manage': False,
+                                'reason_not_safe': None,
+                                'source_reference': {'source-name': image_name}
+                            }
+
+                            if snapshot_id in cinder_snapshot_ids:
+                                # Exclude snapshots already managed.
+                                snapshot_info['reason_not_safe'] = (
+                                    'already managed')
+                                snapshot_info['cinder_id'] = snapshot_id
+                            elif snapshot['name'].endswith('.clone_snap'):
+                                # Exclude clone snapshot.
+                                snapshot_info['reason_not_safe'] = (
+                                    'used for clone snap')
+                            elif (snapshot['name'].startswith('backup')
+                                  and '.snap.' in snapshot['name']):
+                                # Exclude intermediate snapshots created by the
+                                # Ceph backup driver.
+                                snapshot_info['reason_not_safe'] = (
+                                    'used for volume backup')
+                            else:
+                                snapshot_info['safe_to_manage'] = True
+                            manageable_snapshots.append(snapshot_info)
+                    except self.rbd.ImageNotFound:
+                        LOG.debug("Image %s is not found.", image_name)
+
+        return volume_utils.paginate_entries_list(
+            manageable_snapshots, marker, limit, offset, sort_keys, sort_dirs)
+
     def unmanage_snapshot(self, snapshot):
         """Removes the specified snapshot from Cinder management."""
         with RBDVolumeProxy(self, snapshot.volume_name) as volume:
diff --git a/releasenotes/notes/rbd-support-list-manageable-snapshots-3474c62ed83fb788.yaml b/releasenotes/notes/rbd-support-list-manageable-snapshots-3474c62ed83fb788.yaml
new file mode 100644
index 00000000000..5cece82febe
--- /dev/null
+++ b/releasenotes/notes/rbd-support-list-manageable-snapshots-3474c62ed83fb788.yaml
@@ -0,0 +1,3 @@
+---
+features:
+  - Allow rbd driver to list manageable snapshots.