1 /*-------------------------------------------------------------------------
4 * store basebackup archives on the server
7 * src/backend/backup/basebackup_server.c
9 *-------------------------------------------------------------------------
13 #include "access/xact.h"
14 #include "backup/basebackup_sink.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"
21 typedef struct bbsink_server
23 /* Common information for all types of sink. */
26 /* Directory in which backup is to be stored. */
29 /* Currently open file (or 0 if nothing open). */
32 /* Current file position. */
36 static void bbsink_server_begin_archive(bbsink
*sink
,
37 const char *archive_name
);
38 static void bbsink_server_archive_contents(bbsink
*sink
, size_t len
);
39 static void bbsink_server_end_archive(bbsink
*sink
);
40 static void bbsink_server_begin_manifest(bbsink
*sink
);
41 static void bbsink_server_manifest_contents(bbsink
*sink
, size_t len
);
42 static void bbsink_server_end_manifest(bbsink
*sink
);
44 static const bbsink_ops bbsink_server_ops
= {
45 .begin_backup
= bbsink_forward_begin_backup
,
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
57 * Create a new 'server' bbsink.
60 bbsink_server_new(bbsink
*next
, char *pathname
)
62 bbsink_server
*sink
= palloc0(sizeof(bbsink_server
));
64 *((const bbsink_ops
**) &sink
->base
.bbs_ops
) = &bbsink_server_ops
;
65 sink
->pathname
= pathname
;
66 sink
->base
.bbs_next
= next
;
68 /* Replication permission is not sufficient in this case. */
69 StartTransactionCommand();
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")));
76 CommitTransactionCommand();
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
86 if (!is_absolute_path(pathname
))
88 (errcode(ERRCODE_INVALID_NAME
),
89 errmsg("relative path not allowed for backup stored on server")));
91 switch (pg_check_dir(pathname
))
96 * Does not exist, so create it using the same permissions we'd
97 * use for a new subdirectory of the data directory itself.
99 if (MakePGDirectory(pathname
) < 0)
101 (errcode_for_file_access(),
102 errmsg("could not create directory \"%s\": %m", pathname
)));
112 /* Exists, not empty. */
114 (errcode(ERRCODE_DUPLICATE_FILE
),
115 errmsg("directory \"%s\" exists but is not empty",
120 /* Access problem. */
122 (errcode_for_file_access(),
123 errmsg("could not access directory \"%s\": %m",
131 * Open the correct output file for this archive.
134 bbsink_server_begin_archive(bbsink
*sink
, const char *archive_name
)
136 bbsink_server
*mysink
= (bbsink_server
*) sink
;
139 Assert(mysink
->file
== 0);
140 Assert(mysink
->filepos
== 0);
142 filename
= psprintf("%s/%s", mysink
->pathname
, archive_name
);
144 mysink
->file
= PathNameOpenFile(filename
,
145 O_CREAT
| O_EXCL
| O_WRONLY
| PG_BINARY
);
146 if (mysink
->file
<= 0)
148 (errcode_for_file_access(),
149 errmsg("could not create file \"%s\": %m", filename
)));
153 bbsink_forward_begin_archive(sink
, archive_name
);
157 * Write the data to the output file.
160 bbsink_server_archive_contents(bbsink
*sink
, size_t len
)
162 bbsink_server
*mysink
= (bbsink_server
*) sink
;
165 nbytes
= FileWrite(mysink
->file
, mysink
->base
.bbs_buffer
, len
,
166 mysink
->filepos
, WAIT_EVENT_BASEBACKUP_WRITE
);
172 (errcode_for_file_access(),
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.")));
185 mysink
->filepos
+= nbytes
;
187 bbsink_forward_archive_contents(sink
, len
);
191 * fsync and close the current output file.
194 bbsink_server_end_archive(bbsink
*sink
)
196 bbsink_server
*mysink
= (bbsink_server
*) sink
;
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
204 if (FileSync(mysink
->file
, WAIT_EVENT_BASEBACKUP_SYNC
) < 0)
206 (errcode_for_file_access(),
207 errmsg("could not fsync file \"%s\": %m",
208 FilePathName(mysink
->file
))));
211 /* We're done with this file now. */
212 FileClose(mysink
->file
);
216 bbsink_forward_end_archive(sink
);
220 * Open the output file to which we will write the manifest.
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
228 bbsink_server_begin_manifest(bbsink
*sink
)
230 bbsink_server
*mysink
= (bbsink_server
*) sink
;
233 Assert(mysink
->file
== 0);
235 tmp_filename
= psprintf("%s/backup_manifest.tmp", mysink
->pathname
);
237 mysink
->file
= PathNameOpenFile(tmp_filename
,
238 O_CREAT
| O_EXCL
| O_WRONLY
| PG_BINARY
);
239 if (mysink
->file
<= 0)
241 (errcode_for_file_access(),
242 errmsg("could not create file \"%s\": %m", tmp_filename
)));
246 bbsink_forward_begin_manifest(sink
);
250 * Each chunk of manifest data is sent using a CopyData message.
253 bbsink_server_manifest_contents(bbsink
*sink
, size_t len
)
255 bbsink_server
*mysink
= (bbsink_server
*) sink
;
258 nbytes
= FileWrite(mysink
->file
, mysink
->base
.bbs_buffer
, len
,
259 mysink
->filepos
, WAIT_EVENT_BASEBACKUP_WRITE
);
265 (errcode_for_file_access(),
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.")));
278 mysink
->filepos
+= nbytes
;
280 bbsink_forward_manifest_contents(sink
, len
);
284 * fsync the backup manifest, close the file, and then rename it into place.
287 bbsink_server_end_manifest(bbsink
*sink
)
289 bbsink_server
*mysink
= (bbsink_server
*) sink
;
293 /* We're done with this file now. */
294 FileClose(mysink
->file
);
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.
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
);
308 bbsink_forward_end_manifest(sink
);