Skip to content

Commit 64b55ea

Browse files
committed
2 parents c34b2e2 + f6f6789 commit 64b55ea

File tree

9 files changed

+128
-5
lines changed

9 files changed

+128
-5
lines changed

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Snapfs is released under the PostgreSQL License, a liberal Open Source
2+
license, similar to the BSD or MIT licenses.
3+
4+
Copyright (c) 2018, Postgres Professional
5+
Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
6+
Portions Copyright (c) 1994, The Regents of the University of California
7+
8+
Permission to use, copy, modify, and distribute this software and its
9+
documentation for any purpose, without fee, and without a written agreement is
10+
hereby granted, provided that the above copyright notice and this paragraph and
11+
the following two paragraphs appear in all copies.
12+
13+
IN NO EVENT SHALL POSTGRES PROFESSIONAL BE LIABLE TO ANY PARTY FOR DIRECT,
14+
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
15+
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF POSTGRES
16+
PROFESSIONAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17+
18+
POSTGRES PROFESSIONAL SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
19+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20+
PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
21+
POSTGRES PROFESSIONAL HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
22+
UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

src/backend/replication/basebackup.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "storage/fd.h"
3838
#include "storage/ipc.h"
3939
#include "storage/reinit.h"
40+
#include "storage/snapfs.h"
4041
#include "utils/builtins.h"
4142
#include "utils/ps_status.h"
4243
#include "utils/relcache.h"
@@ -52,6 +53,7 @@ typedef struct
5253
bool includewal;
5354
uint32 maxrate;
5455
bool sendtblspcmapfile;
56+
SnapshotId snapshot;
5557
} basebackup_options;
5658

5759

@@ -74,6 +76,8 @@ static int compareWalFileNames(const void *a, const void *b);
7476
static void throttle(size_t increment);
7577
static bool is_checksummed_file(const char *fullpath, const char *filename);
7678

79+
#define BACKUP_ALL_SNAPSHOTS ((SnapshotId)~0)
80+
7781
/* Was the backup currently in-progress initiated in recovery mode? */
7882
static bool backup_started_in_recovery = false;
7983

@@ -234,6 +238,7 @@ perform_base_backup(basebackup_options *opt)
234238
tblspc_map_file = makeStringInfo();
235239

236240
total_checksum_failures = 0;
241+
sfs_backend_snapshot = opt->snapshot;
237242

238243
startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &starttli,
239244
labelfile, &tablespaces,
@@ -643,8 +648,11 @@ parse_basebackup_options(List *options, basebackup_options *opt)
643648
bool o_maxrate = false;
644649
bool o_tablespace_map = false;
645650
bool o_noverify_checksums = false;
651+
bool o_snapshot = false;
646652

647653
MemSet(opt, 0, sizeof(*opt));
654+
opt->snapshot = BACKUP_ALL_SNAPSHOTS;
655+
648656
foreach(lopt, options)
649657
{
650658
DefElem *defel = (DefElem *) lfirst(lopt);
@@ -658,6 +666,15 @@ parse_basebackup_options(List *options, basebackup_options *opt)
658666
opt->label = strVal(defel->arg);
659667
o_label = true;
660668
}
669+
else if (strcmp(defel->defname, "snapshot") == 0)
670+
{
671+
if (o_snapshot)
672+
ereport(ERROR,
673+
(errcode(ERRCODE_SYNTAX_ERROR),
674+
errmsg("duplicate option \"%s\"", defel->defname)));
675+
opt->snapshot = intVal(defel->arg);
676+
o_snapshot = true;
677+
}
661678
else if (strcmp(defel->defname, "progress") == 0)
662679
{
663680
if (o_progress)
@@ -764,8 +781,10 @@ SendBaseBackup(BaseBackupCmd *cmd)
764781
opt.label);
765782
set_ps_display(activitymsg, false);
766783
}
767-
784+
sfs_basebackup = true;
768785
perform_base_backup(&opt);
786+
sfs_basebackup = false;
787+
sfs_backend_snapshot = SFS_INVALID_SNAPSHOT;
769788
}
770789

771790
static void
@@ -1140,6 +1159,10 @@ sendDir(const char *path, int basepathlen, bool sizeonly, List *tablespaces,
11401159
continue;
11411160
}
11421161

1162+
/* Do not backup snapfs files */
1163+
if (sfs_backend_snapshot != BACKUP_ALL_SNAPSHOTS && is_snapfs_file(de->d_name))
1164+
continue;
1165+
11431166
snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name);
11441167

11451168
/* Skip pg_control here to back up it last */
@@ -1373,6 +1396,13 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
13731396
int segmentno = 0;
13741397
char *segmentpath;
13751398
bool verify_checksum = false;
1399+
SnapshotId current_snapshot;
1400+
File file = -1;
1401+
1402+
current_snapshot = sfs_backend_snapshot != SFS_INVALID_SNAPSHOT && sfs_backend_snapshot != BACKUP_ALL_SNAPSHOTS
1403+
? sfs_backend_snapshot : ControlFile->active_snapshot;
1404+
if (current_snapshot != SFS_INVALID_SNAPSHOT)
1405+
file = PathNameOpenFile(readfilename, O_RDONLY|PG_BINARY);
13761406

13771407
fp = AllocateFile(readfilename, "rb");
13781408
if (fp == NULL)
@@ -1523,6 +1553,34 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
15231553
}
15241554
}
15251555

1556+
if (current_snapshot != SFS_INVALID_SNAPSHOT)
1557+
{
1558+
for (i = 0; i < cnt / BLCKSZ; i++)
1559+
{
1560+
int rc;
1561+
page = buf + BLCKSZ * i;
1562+
rc = FileRead(file, page, BLCKSZ, WAIT_EVENT_DATA_FILE_READ);
1563+
if (rc < 0)
1564+
ereport(ERROR,
1565+
(errmsg("base backup could not read snapshot file, aborting backup")));
1566+
}
1567+
}
1568+
1569+
/* Remove information about snapshots from control file */
1570+
if (SFS_KEEPING_SNAPSHOT()
1571+
&& sfs_backend_snapshot != BACKUP_ALL_SNAPSHOTS
1572+
&& strcmp(readfilename, XLOG_CONTROL_FILE) == 0)
1573+
{
1574+
ControlFileData* ctl = (ControlFileData*)buf;
1575+
ctl->oldest_snapshot = 1;
1576+
ctl->recent_snapshot = SFS_INVALID_SNAPSHOT;
1577+
ctl->active_snapshot = SFS_INVALID_SNAPSHOT;
1578+
INIT_CRC32C(ctl->crc);
1579+
COMP_CRC32C(ctl->crc,
1580+
(char *) ctl,
1581+
offsetof(ControlFileData, crc));
1582+
FIN_CRC32C(ctl->crc);
1583+
}
15261584
/* Send the chunk as a CopyData message */
15271585
if (pq_putmessage('d', buf, cnt))
15281586
ereport(ERROR,
@@ -1541,6 +1599,8 @@ sendFile(const char *readfilename, const char *tarfilename, struct stat *statbuf
15411599
break;
15421600
}
15431601
}
1602+
if (file >= 0)
1603+
FileClose(file);
15441604

15451605
/* If the file was truncated while we were sending it, pad it with zeros */
15461606
if (len < statbuf->st_size)

src/backend/replication/repl_gram.y

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ static SQLCmd *make_sqlcmd(void);
7070
%token K_DROP_REPLICATION_SLOT
7171
%token K_TIMELINE_HISTORY
7272
%token K_LABEL
73+
%token K_SNAPSHOT
7374
%token K_PROGRESS
7475
%token K_FAST
7576
%token K_WAIT
@@ -179,6 +180,11 @@ base_backup_opt:
179180
$$ = makeDefElem("label",
180181
(Node *)makeString($2), -1);
181182
}
183+
| K_SNAPSHOT UCONST
184+
{
185+
$$ = makeDefElem("snapshot",
186+
(Node *)makeInteger($2), -1);
187+
}
182188
| K_PROGRESS
183189
{
184190
$$ = makeDefElem("progress",

src/backend/replication/repl_scanner.l

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ FAST { return K_FAST; }
8787
IDENTIFY_SYSTEM { return K_IDENTIFY_SYSTEM; }
8888
SHOW { return K_SHOW; }
8989
LABEL { return K_LABEL; }
90+
SNAPSHOT { return K_SNAPSHOT; }
9091
NOWAIT { return K_NOWAIT; }
9192
PROGRESS { return K_PROGRESS; }
9293
MAX_RATE { return K_MAX_RATE; }

src/backend/storage/file/fd.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,9 +2054,24 @@ FileRead(File file, char *buffer, int amount, uint32 wait_event_info)
20542054
elog(ERROR, "[SFS] Field to read snapshot file: %m");
20552055

20562056
pgstat_report_wait_end();
2057+
if (sfs_basebackup)
2058+
{
2059+
/* We should move file position in case of base backup to avoid explicit seeks */
2060+
vfdP->seekPos += amount;
2061+
}
20572062
return amount;
20582063
}
20592064
}
2065+
/*
2066+
* In case of performing pg_basebackup of particular snapshot
2067+
* we are interested only in reading original image of the page.
2068+
*/
2069+
if (sfs_basebackup)
2070+
{
2071+
/* We should move file position in case of base backup to avoid explicit seeks */
2072+
vfdP->seekPos += amount;
2073+
return 0;
2074+
}
20602075
}
20612076
retry:
20622077
pgstat_report_wait_start(wait_event_info);
@@ -2174,8 +2189,6 @@ FileWrite(File file, char *buffer, int amount, uint32 wait_event_info)
21742189
char orig_block[BLCKSZ];
21752190
int rc;
21762191

2177-
vfdP->snap_map->offs[block_no] = snap_offs + 1;
2178-
21792192
rc = sfs_read_file(vfdP->fd, orig_block, BLCKSZ);
21802193
if (rc < 0)
21812194
elog(ERROR, "[SFS] Could not read file: %m");
@@ -2190,6 +2203,9 @@ FileWrite(File file, char *buffer, int amount, uint32 wait_event_info)
21902203

21912204
if (!sfs_write_file(vfdP->snap_fd, orig_block, BLCKSZ))
21922205
elog(ERROR, "[SFS] Could not write file: %m");
2206+
2207+
/* Update map only after saving original page */
2208+
vfdP->snap_map->offs[block_no] = snap_offs + 1;
21932209
}
21942210
}
21952211

@@ -3450,6 +3466,13 @@ RemovePgTempRelationFilesInDbspace(const char *dbspacedirname)
34503466
FreeDir(dbspace_dir);
34513467
}
34523468

3469+
/* <file>.snap.SNAPSHOT or <file>.snapmap.SNAPSHOT */
3470+
bool
3471+
is_snapfs_file(const char* name)
3472+
{
3473+
return strstr(name, ".snap") != NULL;
3474+
}
3475+
34533476
/* t<digits>_<digits>, or t<digits>_<digits>_<forkname> */
34543477
bool
34553478
looks_like_temp_rel_name(const char *name)

src/backend/storage/file/snapfs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
SnapshotId sfs_backend_snapshot = SFS_INVALID_SNAPSHOT;
4343
SnapshotId sfs_active_snapshot;
44+
bool sfs_basebackup;
4445

4546
int
4647
sfs_msync(SnapshotMap * map)

src/bin/pg_basebackup/pg_basebackup.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ static bool temp_replication_slot = true;
9999
static bool create_slot = false;
100100
static bool no_slot = false;
101101
static bool verify_checksums = true;
102+
static char *snapshot = NULL;
102103

103104
static bool success = false;
104105
static bool made_new_pgdata = false;
@@ -366,6 +367,7 @@ usage(void)
366367
printf(_(" -v, --verbose output verbose messages\n"));
367368
printf(_(" -V, --version output version information, then exit\n"));
368369
printf(_(" --no-slot prevent creation of temporary replication slot\n"));
370+
printf(_(" --snapshot=SNAPID snapfs snapshot\n"));
369371
printf(_(" --no-verify-checksums\n"
370372
" do not verify checksums\n"));
371373
printf(_(" -?, --help show this help, then exit\n"));
@@ -1814,15 +1816,17 @@ BaseBackup(void)
18141816
}
18151817

18161818
basebkp =
1817-
psprintf("BASE_BACKUP LABEL '%s' %s %s %s %s %s %s %s",
1819+
psprintf("BASE_BACKUP LABEL '%s' %s %s %s %s %s %s %s %s %s",
18181820
escaped_label,
18191821
showprogress ? "PROGRESS" : "",
18201822
includewal == FETCH_WAL ? "WAL" : "",
18211823
fastcheckpoint ? "FAST" : "",
18221824
includewal == NO_WAL ? "" : "NOWAIT",
18231825
maxrate_clause ? maxrate_clause : "",
18241826
format == 't' ? "TABLESPACE_MAP" : "",
1825-
verify_checksums ? "" : "NOVERIFY_CHECKSUMS");
1827+
verify_checksums ? "" : "NOVERIFY_CHECKSUMS",
1828+
snapshot ? "SNAPSHOT" : "",
1829+
snapshot ? snapshot : "");
18261830

18271831
if (PQsendQuery(conn, basebkp) == 0)
18281832
{
@@ -2163,6 +2167,7 @@ main(int argc, char **argv)
21632167
{"waldir", required_argument, NULL, 1},
21642168
{"no-slot", no_argument, NULL, 2},
21652169
{"no-verify-checksums", no_argument, NULL, 3},
2170+
{"snapshot", required_argument, NULL, 4},
21662171
{NULL, 0, NULL, 0}
21672172
};
21682173
int c;
@@ -2334,6 +2339,9 @@ main(int argc, char **argv)
23342339
case 3:
23352340
verify_checksums = false;
23362341
break;
2342+
case 4:
2343+
snapshot = pg_strdup(optarg);
2344+
break;
23372345
default:
23382346

23392347
/*

src/include/storage/fd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ extern void AtEOXact_Files(bool isCommit);
126126
extern void AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
127127
SubTransactionId parentSubid);
128128
extern void RemovePgTempFiles(void);
129+
extern bool is_snapfs_file(const char *name);
129130
extern bool looks_like_temp_rel_name(const char *name);
130131

131132
extern int pg_fsync(int fd);

src/include/storage/snapfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ typedef struct SnapshotMap
7474

7575
extern SnapshotId sfs_backend_snapshot;
7676
extern SnapshotId sfs_active_snapshot;
77+
extern bool sfs_basebackup;
7778

7879
/* Memory mapping function */
7980
extern int sfs_munmap(SnapshotMap * map);

0 commit comments

Comments
 (0)