From f6e1ffa4b425c735543d6c87f93c2e4bf207f1bb Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Mon, 22 Mar 2010 16:08:10 +0000 Subject: [PATCH] Properly deal with inodes excluded from incremental dump Files which are excluded from a dump (via -e or the nodump attribute) still have their inode marked as in-use in the dump header. This can cause problems when restoring from an incremental dump, if that inode is currently assigned in the symtable: - If assigned to a file that is being overwritten by another inode, the old entry will be renamed away, but never reclaimed, thus leaving the TMPNAME flag turned on and preventing its removal. - If assigned to a directory, that directory will not be removed by removeoldleaves(), and its entry will linger on in its parent's e_entries. - If its parent is being updated, removeleaf() will wrongly be called on the entry. The above comment about TMPNAME also applies. - If its parent is being deleted, this will fail due to the entry's presence. --- CHANGES | 7 ++++++- restore/restore.c | 29 +++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index ae9f283..b31b75a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,4 @@ -$Id: CHANGES,v 1.309 2010/03/22 15:40:55 stelian Exp $ +$Id: CHANGES,v 1.310 2010/03/22 16:08:10 stelian Exp $ Changes between versions 0.4b42 and 0.4b43 (released ?????????????) =================================================================== @@ -33,6 +33,11 @@ Changes between versions 0.4b42 and 0.4b43 (released ?????????????) to John Austin for reporting the bug. +8. Fix some issues when restoring a dump which was generated using + exclusion patterns (either via -e or via the nodump attribute) + (see the Debian bug #574667 for details. Thanks to Frédéric + Brière for the bug report and the associated + patch. Changes between versions 0.4b41 and 0.4b42 (released June 18, 2009) =================================================================== diff --git a/restore/restore.c b/restore/restore.c index c87b532..780fd76 100644 --- a/restore/restore.c +++ b/restore/restore.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: restore.c,v 1.38 2008/04/17 15:22:56 stelian Exp $"; + "$Id: restore.c,v 1.39 2010/03/22 16:08:10 stelian Exp $"; #endif /* not lint */ #include @@ -566,6 +566,9 @@ keyval(int key) /* * Find unreferenced link names. + * + * This also takes care of directories which were missed by removeoldleaves(), + * because their inode has been reused, but excluded from the dump. */ void findunreflinks(void) @@ -583,12 +586,19 @@ findunreflinks(void) continue; for (j = 0; j < dirhash_size; j++) { for (np = ep->e_entries[j]; np != NULL; np = np->e_sibling) { - if (np->e_flags == 0) { + if ((np->e_flags & ~TMPNAME) == 0) { Dprintf(stdout, "%s: remove unreferenced name\n", myname(np)); - removeleaf(np); - freeentry(np); + if (np->e_type == LEAF) { + removeleaf(np); + freeentry(np); + } else { + np->e_flags |= TMPNAME; + deleteino(np->e_ino); + np->e_next = removelist; + removelist = np; + } } } } @@ -609,6 +619,17 @@ findunreflinks(void) myname(np)); removeleaf(np); freeentry(np); + } else { + if ((np->e_flags & ~TMPNAME) != 0) + badentry(np, "unreferenced with flags"); + + if (np->e_flags == 0) { + Dprintf(stdout, + "%s: remove unreferenced name\n", + myname(np)); + np->e_next = ep->e_next; + ep->e_next = np; + } } } } -- 2.39.5