We've gone through the strace logs and thanks to some pointers to the dpkg code, I think I can explain this. Dpkg does something like this:
while( filename = readdir(/var/dpkg/info)) { err = rename(/var/lib/dpkg/tmp.ci/filename, /var/lib/dpkg/info); if (err) { unlink /var/lib/dpkg/info/filename } } The basic idea is that for each file in /var/lib/dpkg/info we overwrite it with a file from /var/lib/dpkg/tmp.ci. Btrfs implements readdir with a per-directory sequence number. Each time you make a new file in the directory it gets a new sequence number, which is returned as the offset for seekdir/telldir use. The rename operation is creating a new file, so it can show up again in the next readdir call. The strace shows readdir finding a file name, then renaming over it into /var/lib/dpkg/info and then finding the file name again. This could actually happen with any of the filesystems, but btrfs is especially consistent at reproducing it. A while ago, git hit a similar problem: http://www.mail-archive.com/btrfs-de...@oss.oracle.com/msg00370.html Which we solved in btrfs by forcing a very high readdir offset when the entire directory had been read, but this doesn't quite work for dpkg because it doesn't read all the directory entries before it starts processing them. Git later added a commit to avoid the problem internally as well. I would suggest changing the loop to look like this: while (filename = readdir(/var/dpkg/info)) { add filename to list of things that need processing } for each filename in list { rename (/var/lib/dpkg/tmp.ci/filename, /var/lib/dpkg/info) } In other words, buffer the readdir results. Just let me know if you have other questions about this, thanks for bringing us into the debugging. -chris -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org