PostgreSQL Source Code git master
basebackup_server.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * basebackup_server.c
4 * store basebackup archives on the server
5 *
6 * IDENTIFICATION
7 * src/backend/backup/basebackup_server.c
8 *
9 *-------------------------------------------------------------------------
10 */
11#include "postgres.h"
12
13#include "access/xact.h"
15#include "catalog/pg_authid.h"
16#include "miscadmin.h"
17#include "storage/fd.h"
18#include "utils/acl.h"
19#include "utils/wait_event.h"
20
21typedef struct bbsink_server
22{
23 /* Common information for all types of sink. */
25
26 /* Directory in which backup is to be stored. */
27 char *pathname;
28
29 /* Currently open file (or 0 if nothing open). */
31
32 /* Current file position. */
33 off_t filepos;
35
36static void bbsink_server_begin_archive(bbsink *sink,
37 const char *archive_name);
38static void bbsink_server_archive_contents(bbsink *sink, size_t len);
39static void bbsink_server_end_archive(bbsink *sink);
40static void bbsink_server_begin_manifest(bbsink *sink);
41static void bbsink_server_manifest_contents(bbsink *sink, size_t len);
42static void bbsink_server_end_manifest(bbsink *sink);
43
46 .begin_archive = bbsink_server_begin_archive,
47 .archive_contents = bbsink_server_archive_contents,
48 .end_archive = bbsink_server_end_archive,
49 .begin_manifest = bbsink_server_begin_manifest,
50 .manifest_contents = bbsink_server_manifest_contents,
51 .end_manifest = bbsink_server_end_manifest,
52 .end_backup = bbsink_forward_end_backup,
53 .cleanup = bbsink_forward_cleanup
54};
55
56/*
57 * Create a new 'server' bbsink.
58 */
59bbsink *
60bbsink_server_new(bbsink *next, char *pathname)
61{
62 bbsink_server *sink = palloc0(sizeof(bbsink_server));
63
64 *((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_server_ops;
65 sink->pathname = pathname;
66 sink->base.bbs_next = next;
67
68 /* Replication permission is not sufficient in this case. */
70 if (!has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
72 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
73 errmsg("permission denied to create backup stored on server"),
74 errdetail("Only roles with privileges of the \"%s\" role may create a backup stored on the server.",
75 "pg_write_server_files")));
77
78 /*
79 * It's not a good idea to store your backups in the same directory that
80 * you're backing up. If we allowed a relative path here, that could
81 * easily happen accidentally, so we don't. The user could still
82 * accomplish the same thing by including the absolute path to $PGDATA in
83 * the pathname, but that's likely an intentional bad decision rather than
84 * an accident.
85 */
86 if (!is_absolute_path(pathname))
88 (errcode(ERRCODE_INVALID_NAME),
89 errmsg("relative path not allowed for backup stored on server")));
90
91 switch (pg_check_dir(pathname))
92 {
93 case 0:
94
95 /*
96 * Does not exist, so create it using the same permissions we'd
97 * use for a new subdirectory of the data directory itself.
98 */
99 if (MakePGDirectory(pathname) < 0)
102 errmsg("could not create directory \"%s\": %m", pathname)));
103 break;
104
105 case 1:
106 /* Exists, empty. */
107 break;
108
109 case 2:
110 case 3:
111 case 4:
112 /* Exists, not empty. */
114 (errcode(ERRCODE_DUPLICATE_FILE),
115 errmsg("directory \"%s\" exists but is not empty",
116 pathname)));
117 break;
118
119 default:
120 /* Access problem. */
123 errmsg("could not access directory \"%s\": %m",
124 pathname)));
125 }
126
127 return &sink->base;
128}
129
130/*
131 * Open the correct output file for this archive.
132 */
133static void
134bbsink_server_begin_archive(bbsink *sink, const char *archive_name)
135{
136 bbsink_server *mysink = (bbsink_server *) sink;
137 char *filename;
138
139 Assert(mysink->file == 0);
140 Assert(mysink->filepos == 0);
141
142 filename = psprintf("%s/%s", mysink->pathname, archive_name);
143
145 O_CREAT | O_EXCL | O_WRONLY | PG_BINARY);
146 if (mysink->file <= 0)
149 errmsg("could not create file \"%s\": %m", filename)));
150
152
153 bbsink_forward_begin_archive(sink, archive_name);
154}
155
156/*
157 * Write the data to the output file.
158 */
159static void
161{
162 bbsink_server *mysink = (bbsink_server *) sink;
163 int nbytes;
164
165 nbytes = FileWrite(mysink->file, mysink->base.bbs_buffer, len,
166 mysink->filepos, WAIT_EVENT_BASEBACKUP_WRITE);
167
168 if (nbytes != len)
169 {
170 if (nbytes < 0)
173 errmsg("could not write file \"%s\": %m",
174 FilePathName(mysink->file)),
175 errhint("Check free disk space.")));
176 /* short write: complain appropriately */
178 (errcode(ERRCODE_DISK_FULL),
179 errmsg("could not write file \"%s\": wrote only %d of %d bytes at offset %u",
180 FilePathName(mysink->file),
181 nbytes, (int) len, (unsigned) mysink->filepos),
182 errhint("Check free disk space.")));
183 }
184
185 mysink->filepos += nbytes;
186
188}
189
190/*
191 * fsync and close the current output file.
192 */
193static void
195{
196 bbsink_server *mysink = (bbsink_server *) sink;
197
198 /*
199 * We intentionally don't use data_sync_elevel here, because the server
200 * shouldn't PANIC just because we can't guarantee that the backup has
201 * been written down to disk. Running recovery won't fix anything in this
202 * case anyway.
203 */
204 if (FileSync(mysink->file, WAIT_EVENT_BASEBACKUP_SYNC) < 0)
207 errmsg("could not fsync file \"%s\": %m",
208 FilePathName(mysink->file))));
209
210
211 /* We're done with this file now. */
212 FileClose(mysink->file);
213 mysink->file = 0;
214 mysink->filepos = 0;
215
217}
218
219/*
220 * Open the output file to which we will write the manifest.
221 *
222 * Just like pg_basebackup, we write the manifest first under a temporary
223 * name and then rename it into place after fsync. That way, if the manifest
224 * is there and under the correct name, the user can be sure that the backup
225 * completed.
226 */
227static void
229{
230 bbsink_server *mysink = (bbsink_server *) sink;
231 char *tmp_filename;
232
233 Assert(mysink->file == 0);
234
235 tmp_filename = psprintf("%s/backup_manifest.tmp", mysink->pathname);
236
237 mysink->file = PathNameOpenFile(tmp_filename,
238 O_CREAT | O_EXCL | O_WRONLY | PG_BINARY);
239 if (mysink->file <= 0)
242 errmsg("could not create file \"%s\": %m", tmp_filename)));
243
244 pfree(tmp_filename);
245
247}
248
249/*
250 * Each chunk of manifest data is sent using a CopyData message.
251 */
252static void
254{
255 bbsink_server *mysink = (bbsink_server *) sink;
256 int nbytes;
257
258 nbytes = FileWrite(mysink->file, mysink->base.bbs_buffer, len,
259 mysink->filepos, WAIT_EVENT_BASEBACKUP_WRITE);
260
261 if (nbytes != len)
262 {
263 if (nbytes < 0)
266 errmsg("could not write file \"%s\": %m",
267 FilePathName(mysink->file)),
268 errhint("Check free disk space.")));
269 /* short write: complain appropriately */
271 (errcode(ERRCODE_DISK_FULL),
272 errmsg("could not write file \"%s\": wrote only %d of %d bytes at offset %u",
273 FilePathName(mysink->file),
274 nbytes, (int) len, (unsigned) mysink->filepos),
275 errhint("Check free disk space.")));
276 }
277
278 mysink->filepos += nbytes;
279
281}
282
283/*
284 * fsync the backup manifest, close the file, and then rename it into place.
285 */
286static void
288{
289 bbsink_server *mysink = (bbsink_server *) sink;
290 char *tmp_filename;
291 char *filename;
292
293 /* We're done with this file now. */
294 FileClose(mysink->file);
295 mysink->file = 0;
296
297 /*
298 * Rename it into place. This also fsyncs the temporary file, so we don't
299 * need to do that here. We don't use data_sync_elevel here for the same
300 * reasons as in bbsink_server_end_archive.
301 */
302 tmp_filename = psprintf("%s/backup_manifest.tmp", mysink->pathname);
303 filename = psprintf("%s/backup_manifest", mysink->pathname);
304 durable_rename(tmp_filename, filename, ERROR);
306 pfree(tmp_filename);
307
309}
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5268
struct bbsink_server bbsink_server
static void bbsink_server_end_manifest(bbsink *sink)
static const bbsink_ops bbsink_server_ops
static void bbsink_server_archive_contents(bbsink *sink, size_t len)
static void bbsink_server_end_archive(bbsink *sink)
static void bbsink_server_manifest_contents(bbsink *sink, size_t len)
static void bbsink_server_begin_manifest(bbsink *sink)
bbsink * bbsink_server_new(bbsink *next, char *pathname)
static void bbsink_server_begin_archive(bbsink *sink, const char *archive_name)
void bbsink_forward_begin_backup(bbsink *sink)
void bbsink_forward_begin_manifest(bbsink *sink)
void bbsink_forward_end_backup(bbsink *sink, XLogRecPtr endptr, TimeLineID endtli)
void bbsink_forward_cleanup(bbsink *sink)
void bbsink_forward_manifest_contents(bbsink *sink, size_t len)
void bbsink_forward_end_archive(bbsink *sink)
void bbsink_forward_archive_contents(bbsink *sink, size_t len)
void bbsink_forward_begin_archive(bbsink *sink, const char *archive_name)
void bbsink_forward_end_manifest(bbsink *sink)
static int32 next
Definition: blutils.c:224
#define PG_BINARY
Definition: c.h:1244
int errcode_for_file_access(void)
Definition: elog.c:876
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3936
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:781
char * FilePathName(File file)
Definition: fd.c:2483
int FileSync(File file, uint32 wait_event_info)
Definition: fd.c:2319
void FileClose(File file)
Definition: fd.c:1977
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1574
int File
Definition: fd.h:51
static ssize_t FileWrite(File file, const void *buffer, size_t amount, off_t offset, uint32 wait_event_info)
Definition: fd.h:208
Assert(PointerIsAligned(start, uint64))
void pfree(void *pointer)
Definition: mcxt.c:1524
void * palloc0(Size size)
Definition: mcxt.c:1347
Oid GetUserId(void)
Definition: miscinit.c:520
const void size_t len
static char * filename
Definition: pg_dumpall.c:124
#define is_absolute_path(filename)
Definition: port.h:104
int pg_check_dir(const char *dir)
Definition: pgcheckdir.c:33
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
void(* begin_backup)(bbsink *sink)
bbsink * bbs_next
char * bbs_buffer
const bbsink_ops * bbs_ops
void StartTransactionCommand(void)
Definition: xact.c:3059
void CommitTransactionCommand(void)
Definition: xact.c:3157