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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy