diff mbox series

bluez5: fix gatt cache sync issue

Message ID 20260608055607.1069933-1-mengshi.wu@oss.qualcomm.com
State Under Review
Headers show
Series bluez5: fix gatt cache sync issue | expand

Commit Message

Mengshi Wu June 8, 2026, 5:56 a.m. UTC
There is a timing issue to update DB Hash value.

The gatt_client_service_changed() callback in src/device.c
is called from service_changed_complete() in gatt-client.c,
which is invoked after db_hash_read_cb() has already updated
the hash. Adding store_gatt_db(device) here guarantees the
db is persisted with the correct, up-to-date hash for both
the addition and removal cases.

Upstream-Status: Backport [bluez/bluez@0fd01e9]
Signed-off-by: Mengshi Wu <mengshi.wu@oss.qualcomm.com>
---
 meta/recipes-connectivity/bluez5/bluez5.inc   |  1 +
 ...x-stored-gatt-cache-DB-Hash-value-no.patch | 84 +++++++++++++++++++
 2 files changed, 85 insertions(+)
 create mode 100644 meta/recipes-connectivity/bluez5/bluez5/0001-src-device-Fix-stored-gatt-cache-DB-Hash-value-no.patch
diff mbox series

Patch

diff --git a/meta/recipes-connectivity/bluez5/bluez5.inc b/meta/recipes-connectivity/bluez5/bluez5.inc
index e827d0a..5c55afc 100644
--- a/meta/recipes-connectivity/bluez5/bluez5.inc
+++ b/meta/recipes-connectivity/bluez5/bluez5.inc
@@ -72,6 +72,7 @@  SRC_URI = "${KERNELORG_MIRROR}/linux/bluetooth/bluez-${PV}.tar.xz \
            file://0001-tools-Work-around-broken-stdin-handling-in-home-made.patch \
            file://0001-gatt-client-Fix-use-after-free-caused-by-reentrant-c.patch \
            file://0001-transport-Fix-set-volume-failure-with-invalid-device.patch \
+           file://0001-src-device-Fix-stored-gatt-cache-DB-Hash-value-no.patch    \
            "
 S = "${UNPACKDIR}/bluez-${PV}"
 
diff --git a/meta/recipes-connectivity/bluez5/bluez5/0001-src-device-Fix-stored-gatt-cache-DB-Hash-value-no.patch b/meta/recipes-connectivity/bluez5/bluez5/0001-src-device-Fix-stored-gatt-cache-DB-Hash-value-no.patch
new file mode 100644
index 0000000..69323bd
--- /dev/null
+++ b/meta/recipes-connectivity/bluez5/bluez5/0001-src-device-Fix-stored-gatt-cache-DB-Hash-value-no.patch
@@ -0,0 +1,84 @@ 
+From 9ec8cad56e47c0555a056e928e6568d543b3ae0c Mon Sep 17 00:00:00 2001
+From: Mengshi Wu <mengshi.wu@oss.qualcomm.com>
+Date: Wed, 1 Apr 2026 19:30:04 +0800
+Subject: [PATCH v1] src/device: Fix stored gatt cache DB Hash value not update
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There is an asymmetry in behavior: when services are added during
+the same connection (via Service Changed indication), the persistent
+storage (disk) is not updated with the new DB hash, but when services
+are removed, it is updated.
+
+During the same connection, We check DB hash value stored at
+/var/lib/bluetooth/<adaptor addr>/cache/<remote addr>.
+When established connection, the stored DB Hash value is A.Then we
+add new services, the stored DB Hash value is still A which should
+change to B. However, if we remove the existing services, the stored
+DB Hash value changed to C.
+
+When performing addition, it goes like this:
+
+discover_primary_cb()
+  └─> gatt_db_insert_service()      ← NEW service inserted into db
+        └─> gatt_service_added()    ← callback fires immediately
+              └─> store_gatt_db()   ← SAVED TO DISK (hash still OLD)
+  ...
+  └─> discovery_op_complete(success=true)
+        └─> read_db_hash(op)             ← sends ATT Read By Type
+              └─> [ATT response arrives]
+                    └─> db_hash_read_cb()
+                          ├─> gatt_db_attribute_write(op->hash, ...)
+                          │     └─> hash UPDATED IN MEMORY
+                          └─> discovery_op_complete(true, 0)
+                                ├─> [no services to remove, no
+                                │    store_gatt_db called]
+                                └─> service_changed_complete()
+
+Whereas removal perform like this:
+discovery_op_complete(success=true)  [1st call]
+  └─> read_db_hash(op)
+      └─> op->hash is NULL → sends ATT request → early return
+...
+[ATT response arrives]
+db_hash_read_cb()
+  └─> gatt_db_attribute_write(op->hash, ) ← hash UPDATED IN MEMORY
+  └─> discovery_op_complete(true, 0)          [2nd call]
+      └─> read_db_hash(op)  → op->hash already set → returns false
+      └─> gatt_db_remove_service()
+          └─> gatt_service_removed()
+              └─> store_gatt_db() ← SAVED TO DISK (hash is NEW)
+
+There is a timing issue to update DB Hash value.
+
+The gatt_client_service_changed() callback in src/device.c is called
+from service_changed_complete() in gatt-client.c, which is invoked
+after db_hash_read_cb() has already updated the hash. Adding
+store_gatt_db(device) here guarantees the db is persisted with the
+correct, up-to-date hash for both the addition and removal cases.
+
+Upstream-Status: Backport [https://github.com/bluez/bluez/commit/0fd01e98cf94616a5c1c39749314cdd4a1654687]
+Signed-off-by: Mengshi Wu <mengshi.wu@oss.qualcomm.com>
+---
+ src/device.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/device.c b/src/device.c
+index 3ea683667..cfbde307b 100644
+--- a/src/device.c
++++ b/src/device.c
+@@ -6267,7 +6267,11 @@ static void gatt_client_service_changed(uint16_t start_handle,
+ 							uint16_t end_handle,
+ 							void *user_data)
+ {
++	struct btd_device *device = user_data;
++
+ 	DBG("start 0x%04x, end: 0x%04x", start_handle, end_handle);
++
++	store_gatt_db(device);
+ }
+
+ static void gatt_debug(const char *str, void *user_data)
+--
+2.34.1