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

Commit c6dec8c

Browse files
committed
Fix map recovery procedure
1 parent fd6b510 commit c6dec8c

File tree

2 files changed

+48
-26
lines changed

2 files changed

+48
-26
lines changed

src/backend/storage/file/cfs.c

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -470,17 +470,17 @@ int cfs_munmap(FileMap* map)
470470
*/
471471
uint32 cfs_alloc_page(FileMap* map, uint32 oldSize, uint32 newSize)
472472
{
473-
pg_atomic_fetch_add_u32(&map->usedSize, newSize - oldSize);
474-
return pg_atomic_fetch_add_u32(&map->physSize, newSize);
473+
pg_atomic_fetch_add_u32(&map->hdr.usedSize, newSize - oldSize);
474+
return pg_atomic_fetch_add_u32(&map->hdr.physSize, newSize);
475475
}
476476

477477
/*
478478
* Update logical file size
479479
*/
480480
void cfs_extend(FileMap* map, uint32 newSize)
481481
{
482-
uint32 oldSize = pg_atomic_read_u32(&map->virtSize);
483-
while (newSize > oldSize && !pg_atomic_compare_exchange_u32(&map->virtSize, &oldSize, newSize));
482+
uint32 oldSize = pg_atomic_read_u32(&map->hdr.virtSize);
483+
while (newSize > oldSize && !pg_atomic_compare_exchange_u32(&map->hdr.virtSize, &oldSize, newSize));
484484
}
485485

486486
/*
@@ -584,8 +584,10 @@ void cfs_lock_file(FileMap* map, char const* file_path)
584584
if (md2 >= 0)
585585
{
586586
/* Recover map. */
587-
if (!cfs_read_file(md2, map, sizeof(FileMap)))
588-
elog(WARNING, "CFS failed to read file %s: %m", map_bck_path);
587+
if (!cfs_read_file(md2, &map->hdr, sizeof(map->hdr)))
588+
elog(WARNING, "CFS failed to read file header %s: %m", map_bck_path);
589+
else if (!cfs_read_file(md2, map->inodes, sizeof(map->inodes)))
590+
elog(WARNING, "CFS failed to read file inodes %s: %m", map_bck_path);
589591

590592
close(md2);
591593
}
@@ -699,9 +701,9 @@ static bool cfs_gc_file(char* map_path, bool background)
699701
}
700702

701703
succeed = true;
702-
usedSize = pg_atomic_read_u32(&map->usedSize);
703-
physSize = pg_atomic_read_u32(&map->physSize);
704-
virtSize = pg_atomic_read_u32(&map->virtSize);
704+
usedSize = pg_atomic_read_u32(&map->hdr.usedSize);
705+
physSize = pg_atomic_read_u32(&map->hdr.physSize);
706+
virtSize = pg_atomic_read_u32(&map->hdr.virtSize);
705707

706708
cfs_state->gc_stat.scannedFiles += 1;
707709

@@ -754,15 +756,20 @@ static bool cfs_gc_file(char* map_path, bool background)
754756
if (md2 >= 0)
755757
{
756758
/* Recover map */
757-
if (!cfs_read_file(md2, newMap, sizeof(FileMap)))
759+
if (!cfs_read_file(md2, &newMap->hdr, sizeof(newMap->hdr)))
758760
{
759-
elog(WARNING, "CFS failed to read file %s: %m", map_bck_path);
761+
elog(WARNING, "CFS failed to read file header %s: %m", map_bck_path);
762+
goto Cleanup;
763+
}
764+
if (!cfs_read_file(md2, newMap->inodes, sizeof(newMap->inodes)))
765+
{
766+
elog(WARNING, "CFS failed to read file inodes %s: %m", map_bck_path);
760767
goto Cleanup;
761768
}
762769
close(md2);
763770
md2 = -1;
764-
newSize = pg_atomic_read_u32(&newMap->usedSize);
765-
virtSize = pg_atomic_read_u32(&newMap->virtSize);
771+
newSize = pg_atomic_read_u32(&newMap->hdr.usedSize);
772+
virtSize = pg_atomic_read_u32(&newMap->hdr.virtSize);
766773
n_pages = virtSize / BLCKSZ;
767774
remove_backups = false;
768775
goto ReplaceMap;
@@ -791,9 +798,9 @@ static bool cfs_gc_file(char* map_path, bool background)
791798
}
792799

793800
/* Reread variables after locking file */
794-
usedSize = pg_atomic_read_u32(&map->usedSize);
795-
physSize = pg_atomic_read_u32(&map->physSize);
796-
virtSize = pg_atomic_read_u32(&map->virtSize);
801+
usedSize = pg_atomic_read_u32(&map->hdr.usedSize);
802+
physSize = pg_atomic_read_u32(&map->hdr.physSize);
803+
virtSize = pg_atomic_read_u32(&map->hdr.virtSize);
797804
n_pages = virtSize / BLCKSZ;
798805

799806
md2 = open(map_bck_path, O_CREAT|O_RDWR|PG_BINARY|O_TRUNC, 0600);
@@ -872,8 +879,17 @@ static bool cfs_gc_file(char* map_path, bool background)
872879
}
873880
fd2 = -1;
874881

882+
pg_atomic_write_u32(&newMap->hdr.usedSize, newSize);
883+
pg_atomic_write_u32(&newMap->hdr.physSize, newSize);
884+
pg_atomic_write_u32(&newMap->hdr.virtSize, virtSize);
885+
875886
/* Persist copy of map file */
876-
if (!cfs_write_file(md2, newMap, sizeof(FileMap)))
887+
if (!cfs_write_file(md2, &newMap->hdr, sizeof(newMap->hdr)))
888+
{
889+
elog(WARNING, "CFS failed to write file %s: %m", map_bck_path);
890+
goto Cleanup;
891+
}
892+
if (!cfs_write_file(md2, newMap->inodes, sizeof(newMap->inodes)))
877893
{
878894
elog(WARNING, "CFS failed to write file %s: %m", map_bck_path);
879895
goto Cleanup;
@@ -963,8 +979,8 @@ static bool cfs_gc_file(char* map_path, bool background)
963979
* If crash happens at this point, map can be recovered from backup file
964980
*/
965981
memcpy(map->inodes, newMap->inodes, n_pages * sizeof(inode_t));
966-
pg_atomic_write_u32(&map->usedSize, newSize);
967-
pg_atomic_write_u32(&map->physSize, newSize);
982+
pg_atomic_write_u32(&map->hdr.usedSize, newSize);
983+
pg_atomic_write_u32(&map->hdr.physSize, newSize);
968984
map->generation += 1; /* force all backends to reopen the file */
969985

970986
/* Before removing backup files and releasing locks
@@ -1370,8 +1386,8 @@ Datum cfs_compression_ratio(PG_FUNCTION_ARGS)
13701386
break;
13711387
}
13721388

1373-
virtSize += pg_atomic_read_u32(&map->virtSize);
1374-
physSize += pg_atomic_read_u32(&map->physSize);
1389+
virtSize += pg_atomic_read_u32(&map->hdr.virtSize);
1390+
physSize += pg_atomic_read_u32(&map->hdr.physSize);
13751391

13761392
if (cfs_munmap(map) < 0)
13771393
elog(WARNING, "CFS failed to unmap file %s: %m", map_path);
@@ -1421,8 +1437,8 @@ Datum cfs_fragmentation(PG_FUNCTION_ARGS)
14211437
close(md);
14221438
break;
14231439
}
1424-
usedSize += pg_atomic_read_u32(&map->usedSize);
1425-
physSize += pg_atomic_read_u32(&map->physSize);
1440+
usedSize += pg_atomic_read_u32(&map->hdr.usedSize);
1441+
physSize += pg_atomic_read_u32(&map->hdr.physSize);
14261442

14271443
if (cfs_munmap(map) < 0)
14281444
elog(WARNING, "CFS failed to unmap file %s: %m", map_path);

src/include/storage/cfs.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,22 @@ typedef struct
9191
rijndael_ctx aes_context;
9292
} CfsState;
9393

94-
95-
/* Map file format (mmap in memory and shared by all backends) */
96-
typedef struct
94+
typedef struct FileHeader
9795
{
9896
/* Physical size of the file (size of the file on disk) */
9997
pg_atomic_uint32 physSize;
10098
/* Virtual size of the file (Postgres page size (8k) * number of used pages) */
10199
pg_atomic_uint32 virtSize;
102100
/* Total size of used pages. File may contain multiple versions of the same page, this is why physSize can be larger than usedSize */
103101
pg_atomic_uint32 usedSize;
102+
} FileHeader;
103+
104+
105+
106+
/* Map file format (mmap in memory and shared by all backends) */
107+
typedef struct
108+
{
109+
FileHeader hdr;
104110
/* Lock used to synchronize access to the file */
105111
pg_atomic_uint32 lock;
106112
/* PID (process identifier) of postmaster. We check it at open time to revoke lock in case when postgres is restarted.

0 commit comments

Comments
 (0)