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.h"
15 #include "backup/basebackup_sink.h"
16 #include "catalog/pg_authid.h"
17 #include "miscadmin.h"
18 #include "storage/fd.h"
19 #include "utils/acl.h"
20 #include "utils/timestamp.h"
21 #include "utils/wait_event.h"
22 
23 typedef struct bbsink_server
24 {
25  /* Common information for all types of sink. */
27 
28  /* Directory in which backup is to be stored. */
29  char *pathname;
30 
31  /* Currently open file (or 0 if nothing open). */
33 
34  /* Current file position. */
35  off_t filepos;
37 
38 static void bbsink_server_begin_archive(bbsink *sink,
39  const char *archive_name);
40 static void bbsink_server_archive_contents(bbsink *sink, size_t len);
41 static void bbsink_server_end_archive(bbsink *sink);
42 static void bbsink_server_begin_manifest(bbsink *sink);
43 static void bbsink_server_manifest_contents(bbsink *sink, size_t len);
44 static void bbsink_server_end_manifest(bbsink *sink);
45 
46 static const bbsink_ops bbsink_server_ops = {
48  .begin_archive = bbsink_server_begin_archive,
49  .archive_contents = bbsink_server_archive_contents,
50  .end_archive = bbsink_server_end_archive,
51  .begin_manifest = bbsink_server_begin_manifest,
52  .manifest_contents = bbsink_server_manifest_contents,
53  .end_manifest = bbsink_server_end_manifest,
54  .end_backup = bbsink_forward_end_backup,
55  .cleanup = bbsink_forward_cleanup
56 };
57 
58 /*
59  * Create a new 'server' bbsink.
60  */
61 bbsink *
62 bbsink_server_new(bbsink *next, char *pathname)
63 {
64  bbsink_server *sink = palloc0(sizeof(bbsink_server));
65 
66  *((const bbsink_ops **) &sink->base.bbs_ops) = &bbsink_server_ops;
67  sink->pathname = pathname;
68  sink->base.bbs_next = next;
69 
70  /* Replication permission is not sufficient in this case. */
72  if (!has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
73  ereport(ERROR,
74  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
75  errmsg("permission denied to create backup stored on server"),
76  errdetail("Only roles with privileges of the \"%s\" role may create a backup stored on the server.",
77  "pg_write_server_files")));
79 
80  /*
81  * It's not a good idea to store your backups in the same directory that
82  * you're backing up. If we allowed a relative path here, that could
83  * easily happen accidentally, so we don't. The user could still
84  * accomplish the same thing by including the absolute path to $PGDATA in
85  * the pathname, but that's likely an intentional bad decision rather than
86  * an accident.
87  */
88  if (!is_absolute_path(pathname))
89  ereport(ERROR,
90  (errcode(ERRCODE_INVALID_NAME),
91  errmsg("relative path not allowed for backup stored on server")));
92 
93  switch (pg_check_dir(pathname))
94  {
95  case 0:
96 
97  /*
98  * Does not exist, so create it using the same permissions we'd
99  * use for a new subdirectory of the data directory itself.
100  */
101  if (MakePGDirectory(pathname) < 0)
102  ereport(ERROR,
104  errmsg("could not create directory \"%s\": %m", pathname)));
105  break;
106 
107  case 1:
108  /* Exists, empty. */
109  break;
110 
111  case 2:
112  case 3:
113  case 4:
114  /* Exists, not empty. */
115  ereport(ERROR,
116  (errcode(ERRCODE_DUPLICATE_FILE),
117  errmsg("directory \"%s\" exists but is not empty",
118  pathname)));
119  break;
120 
121  default:
122  /* Access problem. */
123  ereport(ERROR,
125  errmsg("could not access directory \"%s\": %m",
126  pathname)));
127  }
128 
129  return &sink->base;
130 }
131 
132 /*
133  * Open the correct output file for this archive.
134  */
135 static void
136 bbsink_server_begin_archive(bbsink *sink, const char *archive_name)
137 {
138  bbsink_server *mysink = (bbsink_server *) sink;
139  char *filename;
140 
141  Assert(mysink->file == 0);
142  Assert(mysink->filepos == 0);
143 
144  filename = psprintf("%s/%s", mysink->pathname, archive_name);
145 
146  mysink->file = PathNameOpenFile(filename,
147  O_CREAT | O_EXCL | O_WRONLY | PG_BINARY);
148  if (mysink->file <= 0)
149  ereport(ERROR,
151  errmsg("could not create file \"%s\": %m", filename)));
152 
153  pfree(filename);
154 
155  bbsink_forward_begin_archive(sink, archive_name);
156 }
157 
158 /*
159  * Write the data to the output file.
160  */
161 static void
163 {
164  bbsink_server *mysink = (bbsink_server *) sink;
165  int nbytes;
166 
167  nbytes = FileWrite(mysink->file, mysink->base.bbs_buffer, len,
169 
170  if (nbytes != len)
171  {
172  if (nbytes < 0)
173  ereport(ERROR,
175  errmsg("could not write file \"%s\": %m",
176  FilePathName(mysink->file)),
177  errhint("Check free disk space.")));
178  /* short write: complain appropriately */
179  ereport(ERROR,
180  (errcode(ERRCODE_DISK_FULL),
181  errmsg("could not write file \"%s\": wrote only %d of %d bytes at offset %u",
182  FilePathName(mysink->file),
183  nbytes, (int) len, (unsigned) mysink->filepos),
184  errhint("Check free disk space.")));
185  }
186 
187  mysink->filepos += nbytes;
188 
190 }
191 
192 /*
193  * fsync and close the current output file.
194  */
195 static void
197 {
198  bbsink_server *mysink = (bbsink_server *) sink;
199 
200  /*
201  * We intentionally don't use data_sync_elevel here, because the server
202  * shouldn't PANIC just because we can't guarantee that the backup has
203  * been written down to disk. Running recovery won't fix anything in this
204  * case anyway.
205  */
206  if (FileSync(mysink->file, WAIT_EVENT_BASEBACKUP_SYNC) < 0)
207  ereport(ERROR,
209  errmsg("could not fsync file \"%s\": %m",
210  FilePathName(mysink->file))));
211 
212 
213  /* We're done with this file now. */
214  FileClose(mysink->file);
215  mysink->file = 0;
216  mysink->filepos = 0;
217 
219 }
220 
221 /*
222  * Open the output file to which we will write the manifest.
223  *
224  * Just like pg_basebackup, we write the manifest first under a temporary
225  * name and then rename it into place after fsync. That way, if the manifest
226  * is there and under the correct name, the user can be sure that the backup
227  * completed.
228  */
229 static void
231 {
232  bbsink_server *mysink = (bbsink_server *) sink;
233  char *tmp_filename;
234 
235  Assert(mysink->file == 0);
236 
237  tmp_filename = psprintf("%s/backup_manifest.tmp", mysink->pathname);
238 
239  mysink->file = PathNameOpenFile(tmp_filename,
240  O_CREAT | O_EXCL | O_WRONLY | PG_BINARY);
241  if (mysink->file <= 0)
242  ereport(ERROR,
244  errmsg("could not create file \"%s\": %m", tmp_filename)));
245 
246  pfree(tmp_filename);
247 
249 }
250 
251 /*
252  * Each chunk of manifest data is sent using a CopyData message.
253  */
254 static void
256 {
257  bbsink_server *mysink = (bbsink_server *) sink;
258  int nbytes;
259 
260  nbytes = FileWrite(mysink->file, mysink->base.bbs_buffer, len,
262 
263  if (nbytes != len)
264  {
265  if (nbytes < 0)
266  ereport(ERROR,
268  errmsg("could not write file \"%s\": %m",
269  FilePathName(mysink->file)),
270  errhint("Check free disk space.")));
271  /* short write: complain appropriately */
272  ereport(ERROR,
273  (errcode(ERRCODE_DISK_FULL),
274  errmsg("could not write file \"%s\": wrote only %d of %d bytes at offset %u",
275  FilePathName(mysink->file),
276  nbytes, (int) len, (unsigned) mysink->filepos),
277  errhint("Check free disk space.")));
278  }
279 
280  mysink->filepos += nbytes;
281 
283 }
284 
285 /*
286  * fsync the backup manifest, close the file, and then rename it into place.
287  */
288 static void
290 {
291  bbsink_server *mysink = (bbsink_server *) sink;
292  char *tmp_filename;
293  char *filename;
294 
295  /* We're done with this file now. */
296  FileClose(mysink->file);
297  mysink->file = 0;
298 
299  /*
300  * Rename it into place. This also fsyncs the temporary file, so we don't
301  * need to do that here. We don't use data_sync_elevel here for the same
302  * reasons as in bbsink_server_end_archive.
303  */
304  tmp_filename = psprintf("%s/backup_manifest.tmp", mysink->pathname);
305  filename = psprintf("%s/backup_manifest", mysink->pathname);
306  durable_rename(tmp_filename, filename, ERROR);
307  pfree(filename);
308  pfree(tmp_filename);
309 
311 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4969
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:219
#define PG_BINARY
Definition: c.h:1278
int errcode_for_file_access(void)
Definition: elog.c:881
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3810
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:693
int FileSync(File file, uint32 wait_event_info)
Definition: fd.c:2197
void FileClose(File file)
Definition: fd.c:1889
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1486
int FileWrite(File file, const void *buffer, size_t amount, off_t offset, uint32 wait_event_info)
Definition: fd.c:2099
char * FilePathName(File file)
Definition: fd.c:2358
int File
Definition: fd.h:55
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc0(Size size)
Definition: mcxt.c:1257
Oid GetUserId(void)
Definition: miscinit.c:510
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
@ WAIT_EVENT_BASEBACKUP_SYNC
Definition: wait_event.h:165
@ WAIT_EVENT_BASEBACKUP_WRITE
Definition: wait_event.h:166
void StartTransactionCommand(void)
Definition: xact.c:2937
void CommitTransactionCommand(void)
Definition: xact.c:3034