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"
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"
20 
21 typedef 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 
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);
43 
44 static const bbsink_ops bbsink_server_ops = {
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  */
59 bbsink *
60 bbsink_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))
71  ereport(ERROR,
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))
87  ereport(ERROR,
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)
100  ereport(ERROR,
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. */
113  ereport(ERROR,
114  (errcode(ERRCODE_DUPLICATE_FILE),
115  errmsg("directory \"%s\" exists but is not empty",
116  pathname)));
117  break;
118 
119  default:
120  /* Access problem. */
121  ereport(ERROR,
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  */
133 static void
134 bbsink_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 
144  mysink->file = PathNameOpenFile(filename,
145  O_CREAT | O_EXCL | O_WRONLY | PG_BINARY);
146  if (mysink->file <= 0)
147  ereport(ERROR,
149  errmsg("could not create file \"%s\": %m", filename)));
150 
151  pfree(filename);
152 
153  bbsink_forward_begin_archive(sink, archive_name);
154 }
155 
156 /*
157  * Write the data to the output file.
158  */
159 static 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)
171  ereport(ERROR,
173  errmsg("could not write file \"%s\": %m",
174  FilePathName(mysink->file)),
175  errhint("Check free disk space.")));
176  /* short write: complain appropriately */
177  ereport(ERROR,
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  */
193 static 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)
205  ereport(ERROR,
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  */
227 static 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)
240  ereport(ERROR,
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  */
252 static 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)
264  ereport(ERROR,
266  errmsg("could not write file \"%s\": %m",
267  FilePathName(mysink->file)),
268  errhint("Check free disk space.")));
269  /* short write: complain appropriately */
270  ereport(ERROR,
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  */
286 static 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);
305  pfree(filename);
306  pfree(tmp_filename);
307 
309 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5128
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)
bbsink * bbsink_server_new(bbsink *next, char *pathname)
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)
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:221
#define Assert(condition)
Definition: c.h:858
#define PG_BINARY
Definition: c.h:1273
int errcode_for_file_access(void)
Definition: elog.c:882
int errdetail(const char *fmt,...)
Definition: elog.c:1205
int errhint(const char *fmt,...)
Definition: elog.c:1319
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3913
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:782
int FileSync(File file, uint32 wait_event_info)
Definition: fd.c:2297
void FileClose(File file)
Definition: fd.c:1978
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1575
char * FilePathName(File file)
Definition: fd.c:2461
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
void pfree(void *pointer)
Definition: mcxt.c:1520
void * palloc0(Size size)
Definition: mcxt.c:1346
Oid GetUserId(void)
Definition: miscinit.c:514
const void size_t len
static char * filename
Definition: pg_dumpall.c:119
#define is_absolute_path(filename)
Definition: port.h:103
int pg_check_dir(const char *dir)
Definition: pgcheckdir.c:33
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void(* begin_backup)(bbsink *sink)
bbsink * bbs_next
char * bbs_buffer
const bbsink_ops * bbs_ops
void StartTransactionCommand(void)
Definition: xact.c:2995
void CommitTransactionCommand(void)
Definition: xact.c:3093