LXD: database disk image is malformed

Hi everyone,

Thanks for LXC/D! I’m having an issue where our containers are not listing properly and other functions like snapshots are not working. We’re running Ubuntu 20.04 on the host and containers. encrypted+mirrored ZFS for the storage pool.

I’ve seemed to narrowed the issue to a database corruption on a specific container by doing the following:

lxc list

±-------------±--------±-------------------±--------------------------±----------±----------+
| container_name | ERROR | | | CONTAINER | 0 |
±-------------±--------±-------------------±--------------------------±----------±----------+

Let’s look at the logs:
sudo tail -f /var/snap/lxd/common/lxd/logs/lxd.log

t=2021-04-29T10:43:58-0700 lvl=eror msg="Failed to list instance snapshots" err="Failed to fetch instance_snapshots: id" instance=container_name project=default

A look at the specific container:
lxd sql global "SELECT id, instance_id, name, creation_date, stateful, description, expiry_date FROM instances_snapshots WHERE instance_id = 14" error: Got a row error: id

So I decided to open up sqlite to try and fine the problematic row:
sqlite3 /var/snap/lxd/common/lxd/database/global/db.bin

sqlite> SELECT id, instance_id, name, creation_date, stateful, description, expiry_date  FROM instances_snapshots WHERE instance_id = 14 AND id > 2360 AND id < 2600;
2368|14|snapshot-65|2021-04-17 19:00:08.875615999+00:00|0||2021-05-17 12:00:08.874972385-07:00
2380|14|snapshot-66|2021-04-18 01:00:17.732227872+00:00|0||2021-05-17 18:00:17.731749164-07:00
Error: database disk image is malformed

Doing an integrity check reveals:

sqlite> pragma integrity_check;
*** in database main ***
On tree page 126 cell 65: Rowid 2359 out of order 
On tree page 43 cell 106: Rowid 71835 out of order
On tree page 43 cell 97: Rowid 71291 out of order 
On tree page 43 cell 91: Rowid 70960 out of order 
On tree page 43 cell 90: Rowid 70911 out of order 
On tree page 43 cell 79: Rowid 70272 out of order 
On tree page 43 cell 76: Rowid 70097 out of order 
On tree page 43 cell 51: Rowid 63037 out of order 
On tree page 43 cell 50: Rowid 62740 out of order 
On tree page 354 cell 51: Rowid 68748 out of order
row 66 missing from index sqlite_autoindex_instances_snapshots_1
wrong # of entries in index sqlite_autoindex_instances_snapshots_1
row 66 missing from index sqlite_autoindex_storage_volumes_snapshots_2
row 66 missing from index sqlite_autoindex_storage_volumes_snapshots_1
row 93 missing from index sqlite_autoindex_storage_volumes_snapshots_2
--- continues ----
row 241 missing from index sqlite_autoindex_storage_volumes_snapshots_2 
row 243 missing from index sqlite_autoindex_storage_volumes_snapshots_2 
row 248 missing from index sqlite_autoindex_storage_volumes_snapshots_2

Any advice on how to recover/repair/rebuild the database? There are more snapshots for that container, but the db seems corrupted and out of sync. Thanks!

What LXD version is that?

@mbordere this may be one for you

lxd --version
4.13

on the latest/stable version of the snap

tracking:     latest/stable
refresh-date: yesterday at 20:59 PDT
channels:
  latest/stable:    4.13        2021-04-29 (20222) 72MB -

Could you make a tarball of /var/snap/lxd/common/lxd/database and send that to me at stgraber at ubuntu dot com?

That should let me reproduce the issue and will allow @mbordere to look at what happened.

db.bin itself being unreadable isn’t really an issue, that file isn’t actually read by LXD and is mostly there for debugging purposes but it sounds like something else is wrong with that DB.

Yes, sent. thanks!

Okay, there’s some pretty clear corruption in there and that seems to have happened quite a while ago. I’m trying to figure out how far back to go to get it back to a sane state without losing too much in the process.

Ok, so looks like you’ll need to go back to the 27th at midnight for things to behave.
To do that, you should do:

  • Stop LXD
  • cp -R /var/snap/lxd/common/lxd/database /var/snap/lxd/common/lxd/database.broken
  • rm /var/snap/lxd/common/lxd/database/global/snapshot-1-29696-5488881652* /var/snap/lxd/common/lxd/database/global/00*
  • Start LXD

Basically the 28672 snapshots doesn’t appear corrupt but the segment immediately following it (28419-28899) appears to be the source of the corruption, so the only safe revert is that full snapshot from the 27th at midnight.

1 Like

@mbordere forwarded the tarball to you for investigation, would be good to know if it looks like a dqlite bug or if it was sqlite doing something wrong or disk/memory corruption.

Thank you, I followed these steps and lxc list works and containers are back up!

Maybe spoke a little too soon. there are two containers that I migrated to this host since the 27th and they’re no longer appearing. trying to do lxd import streams produces:
Error: The instance's directory "/var/snap/lxd/common/lxd/storage-pools/data/containers/streams" appears to be empty. Please ensure that the instance's storage volume is mounted

Right, in this case, you’ll need to do:

  • nsenter --mount=/run/snapd/ns/lxd.mnt mount -t zfs data/lxc/containers/streams /var/snap/lxd/common/lxd/storage-pools/data/containers/stream

Which should mount it so that lxd import streams then can process it.

1 Like

Perfect, that did it.

We have planned work for a new lxd recover command which will much better handle mounting what’s needed and will replace lxd import. We unfortunately had to bump the work to later this year as we took a bit longer than planned to add some networking and clustering features.

1 Like

That will be much appreciated, I know I’ve struggled in the past with understanding nsenter and the right commands to use with zfs and in the moment where things are down it’s hard to learn and study docs :laughing:

Apparently just removing snapshot-1-29696-5488881652 and snapshot-1-29696-5488881652.meta would have done the trick. Still investigating why that last snapshot appears to be corrupt. The segments are intact and the oldest snapshot was also intact.

It’s hard to detect a disk corruption on the snapshot file as there is no crc check being performed on it. We do perform crc checks on the snapshot.meta files and segment files. I plan to tackle this soon, we will be using a new disk format for compressed snapshot files and I will add a crc check while doing that.

@kpfa can I share your database with @freeekanayaka? He’s the original developer of dqlite and might have some insights.

Yes, that’s fine. Thank you.