Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 16f2ead

Browse files
committed
When doing a parallel restore, we must guard against out-of-range dependency
dump IDs, because the array we're using is sized according to the highest dump ID actually defined in the archive file. In a partial dump there could be references to higher dump IDs that weren't dumped. Treat these the same as references to in-range IDs that weren't dumped. (The whole thing is a bit scary because the missing objects might have been part of dependency chains, which we won't know about. Not much we can do though --- throwing an error is probably overreaction.) Also, reject parallel restore with pre-1.8 archive version (made by pre-8.0 pg_dump). In these old versions the dependency entries are OIDs, not dump IDs, and we don't have enough information to interpret them. Per bug #5288 from Jon Erdman.
1 parent 85b587c commit 16f2ead

File tree

1 file changed

+26
-10
lines changed

1 file changed

+26
-10
lines changed

src/bin/pg_dump/pg_backup_archiver.c

+26-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.177 2009/12/14 00:39:10 itagaki Exp $
18+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.178 2010/01/19 18:39:19 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -134,7 +134,8 @@ static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2);
134134
static void repoint_table_dependencies(ArchiveHandle *AH,
135135
DumpId tableId, DumpId tableDataId);
136136
static void identify_locking_dependencies(TocEntry *te,
137-
TocEntry **tocsByDumpId);
137+
TocEntry **tocsByDumpId,
138+
DumpId maxDumpId);
138139
static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te,
139140
TocEntry *ready_list);
140141
static void mark_create_done(ArchiveHandle *AH, TocEntry *te);
@@ -3091,6 +3092,10 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
30913092
if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
30923093
die_horribly(AH, modulename, "parallel restore is not supported with this archive file format\n");
30933094

3095+
/* doesn't work if the archive represents dependencies as OIDs, either */
3096+
if (AH->version < K_VERS_1_8)
3097+
die_horribly(AH, modulename, "parallel restore is not supported with archives made by pre-8.0 pg_dump\n");
3098+
30943099
slots = (ParallelSlot *) calloc(sizeof(ParallelSlot), n_slots);
30953100

30963101
/* Adjust dependency information */
@@ -3649,17 +3654,23 @@ fix_dependencies(ArchiveHandle *AH)
36493654
{
36503655
TocEntry **tocsByDumpId;
36513656
TocEntry *te;
3657+
DumpId maxDumpId;
36523658
int i;
36533659

36543660
/*
36553661
* For some of the steps here, it is convenient to have an array that
36563662
* indexes the TOC entries by dump ID, rather than searching the TOC list
36573663
* repeatedly. Entries for dump IDs not present in the TOC will be NULL.
36583664
*
3665+
* NOTE: because maxDumpId is just the highest dump ID defined in the
3666+
* archive, there might be dependencies for IDs > maxDumpId. All uses
3667+
* of this array must guard against out-of-range dependency numbers.
3668+
*
36593669
* Also, initialize the depCount fields, and make sure all the TOC items
36603670
* are marked as not being in any parallel-processing list.
36613671
*/
3662-
tocsByDumpId = (TocEntry **) calloc(AH->maxDumpId, sizeof(TocEntry *));
3672+
maxDumpId = AH->maxDumpId;
3673+
tocsByDumpId = (TocEntry **) calloc(maxDumpId, sizeof(TocEntry *));
36633674
for (te = AH->toc->next; te != AH->toc; te = te->next)
36643675
{
36653676
tocsByDumpId[te->dumpId - 1] = te;
@@ -3688,7 +3699,8 @@ fix_dependencies(ArchiveHandle *AH)
36883699
{
36893700
DumpId tableId = te->dependencies[0];
36903701

3691-
if (tocsByDumpId[tableId - 1] == NULL ||
3702+
if (tableId > maxDumpId ||
3703+
tocsByDumpId[tableId - 1] == NULL ||
36923704
strcmp(tocsByDumpId[tableId - 1]->desc, "TABLE") == 0)
36933705
{
36943706
repoint_table_dependencies(AH, tableId, te->dumpId);
@@ -3733,7 +3745,9 @@ fix_dependencies(ArchiveHandle *AH)
37333745
{
37343746
for (i = 0; i < te->nDeps; i++)
37353747
{
3736-
if (tocsByDumpId[te->dependencies[i] - 1] == NULL)
3748+
DumpId depid = te->dependencies[i];
3749+
3750+
if (depid > maxDumpId || tocsByDumpId[depid - 1] == NULL)
37373751
te->depCount--;
37383752
}
37393753
}
@@ -3745,7 +3759,7 @@ fix_dependencies(ArchiveHandle *AH)
37453759
{
37463760
te->lockDeps = NULL;
37473761
te->nLockDeps = 0;
3748-
identify_locking_dependencies(te, tocsByDumpId);
3762+
identify_locking_dependencies(te, tocsByDumpId, maxDumpId);
37493763
}
37503764

37513765
free(tocsByDumpId);
@@ -3782,11 +3796,13 @@ repoint_table_dependencies(ArchiveHandle *AH,
37823796
* Identify which objects we'll need exclusive lock on in order to restore
37833797
* the given TOC entry (*other* than the one identified by the TOC entry
37843798
* itself). Record their dump IDs in the entry's lockDeps[] array.
3785-
* tocsByDumpId[] is a convenience array to avoid searching the TOC
3786-
* for each dependency.
3799+
* tocsByDumpId[] is a convenience array (of size maxDumpId) to avoid
3800+
* searching the TOC for each dependency.
37873801
*/
37883802
static void
3789-
identify_locking_dependencies(TocEntry *te, TocEntry **tocsByDumpId)
3803+
identify_locking_dependencies(TocEntry *te,
3804+
TocEntry **tocsByDumpId,
3805+
DumpId maxDumpId)
37903806
{
37913807
DumpId *lockids;
37923808
int nlockids;
@@ -3817,7 +3833,7 @@ identify_locking_dependencies(TocEntry *te, TocEntry **tocsByDumpId)
38173833
{
38183834
DumpId depid = te->dependencies[i];
38193835

3820-
if (tocsByDumpId[depid - 1] &&
3836+
if (depid <= maxDumpId && tocsByDumpId[depid - 1] &&
38213837
strcmp(tocsByDumpId[depid - 1]->desc, "TABLE DATA") == 0)
38223838
lockids[nlockids++] = depid;
38233839
}

0 commit comments

Comments
 (0)