PostgreSQL Source Code: src/bin/pg_upgrade/file.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
11
12#include <sys/stat.h>
13#include <limits.h>
14#include <fcntl.h>
15#ifdef HAVE_COPYFILE_H
16#include <copyfile.h>
17#endif
18#ifdef __linux__
19#include <sys/ioctl.h>
20#include <linux/fs.h>
21#endif
22
29
30
31
32
33
34
35
36
37
38void
39cloneFile(const char *src, const char *dst,
40 const char *schemaName, const char *relName)
41{
42#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
43 if (copyfile(src, dst, NULL, COPYFILE_CLONE_FORCE) < 0)
44 pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m",
45 schemaName, relName, src, dst);
46#elif defined(__linux__) && defined(FICLONE)
47 int src_fd;
48 int dest_fd;
49
50 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
51 pg_fatal("error while cloning relation \"%s.%s\": could not open file \"%s\": %m",
52 schemaName, relName, src);
53
54 if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
56 pg_fatal("error while cloning relation \"%s.%s\": could not create file \"%s\": %m",
57 schemaName, relName, dst);
58
59 if (ioctl(dest_fd, FICLONE, src_fd) < 0)
60 {
61 int save_errno = errno;
62
63 unlink(dst);
64
65 pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s",
66 schemaName, relName, src, dst, strerror(save_errno));
67 }
68
71#endif
72}
73
74
75
76
77
78
79
80
81void
82copyFile(const char *src, const char *dst,
83 const char *schemaName, const char *relName)
84{
85#ifndef WIN32
86 int src_fd;
87 int dest_fd;
88 char *buffer;
89
90 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
91 pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",
92 schemaName, relName, src);
93
94 if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
96 pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",
97 schemaName, relName, dst);
98
99
100#define COPY_BUF_SIZE (50 * BLCKSZ)
101
103
104
105 while (true)
106 {
108
109 if (nbytes < 0)
110 pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m",
111 schemaName, relName, src);
112
113 if (nbytes == 0)
114 break;
115
116 errno = 0;
117 if (write(dest_fd, buffer, nbytes) != nbytes)
118 {
119
120 if (errno == 0)
121 errno = ENOSPC;
122 pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m",
123 schemaName, relName, dst);
124 }
125 }
126
130
131#else
132
133 if (CopyFile(src, dst, true) == 0)
134 {
136 pg_fatal("error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %m",
137 schemaName, relName, src, dst);
138 }
139
140#endif
141}
142
143
144
145
146
147
148
149
150void
152 const char *schemaName, const char *relName)
153{
154#ifdef HAVE_COPY_FILE_RANGE
155 int src_fd;
156 int dest_fd;
157 ssize_t nbytes;
158
159 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
160 pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",
161 schemaName, relName, src);
162
163 if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
165 pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",
166 schemaName, relName, dst);
167
168 do
169 {
170 nbytes = copy_file_range(src_fd, NULL, dest_fd, NULL, SSIZE_MAX, 0);
171 if (nbytes < 0)
172 pg_fatal("error while copying relation \"%s.%s\": could not copy file range from \"%s\" to \"%s\": %m",
173 schemaName, relName, src, dst);
174 }
175 while (nbytes > 0);
176
179#endif
180}
181
182
183
184
185
186
187
188
189void
190linkFile(const char *src, const char *dst,
191 const char *schemaName, const char *relName)
192{
193 if (link(src, dst) < 0)
194 pg_fatal("error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m",
195 schemaName, relName, src, dst);
196}
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215void
217 const char *schemaName, const char *relName)
218{
219 int src_fd;
220 int dst_fd;
223 ssize_t totalBytesRead = 0;
224 ssize_t src_filesize;
225 int rewriteVmBytesPerPage;
227 struct stat statbuf;
228
229
231
232 if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0)
233 pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",
234 schemaName, relName, fromfile);
235
236 if (fstat(src_fd, &statbuf) != 0)
237 pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %m",
238 schemaName, relName, fromfile);
239
240 if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
242 pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",
243 schemaName, relName, tofile);
244
245
246 src_filesize = statbuf.st_size;
247
248
249
250
251
252
253
254 while (totalBytesRead < src_filesize)
255 {
256 ssize_t bytesRead;
257 char *old_cur;
258 char *old_break;
259 char *old_blkend;
261 bool old_lastblk;
262
263 if ((bytesRead = read(src_fd, buffer.data, BLCKSZ)) != BLCKSZ)
264 {
265 if (bytesRead < 0)
266 pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m",
267 schemaName, relName, fromfile);
268 else
269 pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"",
270 schemaName, relName, fromfile);
271 }
272
273 totalBytesRead += BLCKSZ;
274 old_lastblk = (totalBytesRead == src_filesize);
275
276
278
279
280
281
282
283
284
286 old_blkend = buffer.data + bytesRead;
287 old_break = old_cur + rewriteVmBytesPerPage;
288
289 while (old_break <= old_blkend)
290 {
291 char *new_cur;
292 bool empty = true;
293 bool old_lastpart;
294
295
297
298
299 old_lastpart = old_lastblk && (old_break == old_blkend);
300
302
303
304 while (old_cur < old_break)
305 {
307 uint16 new_vmbits = 0;
308 int i;
309
310
312 {
313 if (byte & (1 << i))
314 {
315 empty = false;
316 new_vmbits |=
318 }
319 }
320
321
322 new_cur[0] = (char) (new_vmbits & 0xFF);
323 new_cur[1] = (char) (new_vmbits >> 8);
324
325 old_cur++;
327 }
328
329
330 if (old_lastpart && empty)
331 break;
332
333
337
338 errno = 0;
339 if (write(dst_fd, new_vmbuf.data, BLCKSZ) != BLCKSZ)
340 {
341
342 if (errno == 0)
343 errno = ENOSPC;
344 pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m",
345 schemaName, relName, tofile);
346 }
347
348
349 old_break += rewriteVmBytesPerPage;
350 new_blkno++;
351 }
352 }
353
354
357}
358
359void
361{
364
367 unlink(new_link_file);
368
369#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
370 if (copyfile(existing_file, new_link_file, NULL, COPYFILE_CLONE_FORCE) < 0)
371 pg_fatal("could not clone file between old and new data directories: %m");
372#elif defined(__linux__) && defined(FICLONE)
373 {
374 int src_fd;
375 int dest_fd;
376
377 if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)
378 pg_fatal("could not open file \"%s\": %m",
379 existing_file);
380
381 if ((dest_fd = open(new_link_file, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
383 pg_fatal("could not create file \"%s\": %m",
384 new_link_file);
385
386 if (ioctl(dest_fd, FICLONE, src_fd) < 0)
387 pg_fatal("could not clone file between old and new data directories: %m");
388
391 }
392#else
393 pg_fatal("file cloning not supported on this platform");
394#endif
395
396 unlink(new_link_file);
397}
398
399void
401{
404
406 snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.copy_file_range_test", new_cluster.pgdata);
407 unlink(new_link_file);
408
409#if defined(HAVE_COPY_FILE_RANGE)
410 {
411 int src_fd;
412 int dest_fd;
413
414 if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)
415 pg_fatal("could not open file \"%s\": %m",
416 existing_file);
417
418 if ((dest_fd = open(new_link_file, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
420 pg_fatal("could not create file \"%s\": %m",
421 new_link_file);
422
423 if (copy_file_range(src_fd, NULL, dest_fd, NULL, SSIZE_MAX, 0) < 0)
424 pg_fatal("could not copy file range between old and new data directories: %m");
425
428 }
429#else
430 pg_fatal("copy_file_range not supported on this platform");
431#endif
432
433 unlink(new_link_file);
434}
435
436void
438{
441
444 unlink(new_link_file);
445
446 if (link(existing_file, new_link_file) < 0)
447 {
449 pg_fatal("could not create hard link between old and new data directories: %m\n"
450 "In link mode the old and new data directories must be on the same file system.");
452 pg_fatal("could not create hard link between old and new data directories: %m\n"
453 "In swap mode the old and new data directories must be on the same file system.");
454 else
455 pg_fatal("unrecognized transfer mode");
456 }
457
458 unlink(new_link_file);
459}
PageHeaderData * PageHeader
#define SizeOfPageHeaderData
uint16 pg_checksum_page(char *page, BlockNumber blkno)
void * pg_malloc(size_t size)
void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName)
void check_file_clone(void)
void rewriteVisibilityMap(const char *fromfile, const char *tofile, const char *schemaName, const char *relName)
void check_hard_link(transferMode transfer_mode)
void cloneFile(const char *src, const char *dst, const char *schemaName, const char *relName)
void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName)
void copyFile(const char *src, const char *dst, const char *schemaName, const char *relName)
void check_copy_file_range(void)
uint32 data_checksum_version
#define BITS_PER_HEAPBLOCK
#define VISIBILITYMAP_ALL_VISIBLE
void _dosmaperr(unsigned long)
int link(const char *src, const char *dst)