From 1ff397a8d433bf9132ab5b1c4db9cc7d6600f5db Mon Sep 17 00:00:00 2001
From: Mark Syms <mark.syms@cloud.com>
Date: Fri, 4 Apr 2025 14:52:48 +0100
Subject: [PATCH] CA-409231: report intellicache stats with nbd

The connection from the leaf (per-vm) tapdisk to the shared parent
tapdisk when using IntelliCache now uses NBD rather than the kernel
blktap device. This causes the tapdisk-cache-stats script to fail and
exit with error 1. As a result no IntelliCache stats are produced,
fix this by adding support for the remote to be nbd to a defined path.

Signed-off-by: Mark Syms <mark.syms@cloud.com>
diff --git a/drivers/lcache.py b/drivers/lcache.py
index f1e25c3..f9c9061 100755
--- a/drivers/lcache.py
+++ b/drivers/lcache.py
@@ -18,6 +18,7 @@
 import os
 import blktap2
 import glob
+import re
 from stat import *  # S_ISBLK(), ...
 
 SECTOR_SHIFT = 9
@@ -62,6 +63,13 @@ class CachingTap(object):
             __assert(major == tapdisk.major())
 
             return LeafCachingTap(tapdisk, stats, minor)
+        elif _type == 'nbd' and 'run/blktap-control/nbd' in path:
+            minor_matcher = re.compile(r'.*run/blktap-control/nbd\d+\.(\d+)$')
+            match = minor_matcher.match(path)
+            __assert(match is not None)
+
+            parent_minor = int(match.group(1))
+            return LeafCachingTap(tapdisk, stats, parent_minor)
 
         __assert(0)
 
diff --git a/tests/test_lcache.py b/tests/test_lcache.py
new file mode 100644
index 0000000..36ec1fb
--- /dev/null
+++ b/tests/test_lcache.py
@@ -0,0 +1,64 @@
+import unittest
+
+from blktap2 import Tapdisk
+from lcache import CachingTap, LeafCachingTap
+
+class TestLcacheCachingTap(unittest.TestCase):
+
+    def test_from_tapdisk_nbd(self):
+        test_tapdisk = Tapdisk(
+            234567, 1, 'vhd',
+            'vhd:/var/run/sr-mount/21a94b1f-0909-60ee-d838-cad8a90b801d/ae34b288-dd2e-4dbc-899d-f14f21b110b2.vhdcache',
+            0)
+
+        stats =  {
+            'name': 'vhd:/var/run/sr-mount/21a94b1f-0909-60ee-d838-cad8a90b801d/ae34b288-dd2e-4dbc-899d-f14f21b110b2.vhdcache',
+            'secs': [62231944, 76640972],
+            'images': [
+                {
+                    'name': '/var/run/sr-mount/db04b2bb-6541-5da1-9299-0308a1b2daee/ae34b288-dd2e-4dbc-899d-f14f21b110b2.vhd',
+                    'hits': [36782760, 75356313],
+                    'fail': [0, 0],
+                    'driver': {
+                        'type': 4, 'name': 'vhd', 'status': None}
+                },
+                {
+                    'name': '/var/run/sr-mount/21a94b1f-0909-60ee-d838-cad8a90b801d/ae34b288-dd2e-4dbc-899d-f14f21b110b2.vhdcache',
+                    'hits': [1826692, 2844259],
+                    'fail': [0, 0],
+                    'driver': {
+                        'type': 4, 'name': 'vhd', 'status': None}
+                },
+                {
+                    'name': '/var/run/blktap-control/nbd132558.0',
+                    'hits': [23622492, 0],
+                    'fail': [0, 0],
+                    'driver': {
+                        'type': 15, 'name': 'nbd', 'status': None}
+                }
+            ],
+            'tap': {
+                'minor': 1,
+                'reqs': [0, 0],
+                'kicks': [3, 0]
+            },
+            'xenbus': {
+                'pool': 'td-xenio-default',
+                'domid': 15,
+                'devid': 768,
+                'reqs': [2685748, 2685748],
+                'kicks': [614279, 1510961],
+                'errors': {
+                    'msg': 0, 'map': 0, 'vbd': 0, 'img': 0}
+            },
+            'FIXME_enospc_redirect_count': 75356313,
+            'nbd_mirror_failed': 0,
+            'reqs_outstanding': 0,
+            'read_caching': 'true'
+        }
+
+        cachingTap = CachingTap.from_tapdisk(test_tapdisk, stats)
+
+        self.assertIsNotNone(cachingTap)
+        self.assertIsInstance(cachingTap, LeafCachingTap)
+        self.assertEqual(0, cachingTap.parent_minor)
