|
18 | 18 |
|
19 | 19 | #include<sys/stat.h>
|
20 | 20 | #include<fcntl.h>
|
| 21 | +#ifdefHAVE_COPYFILE |
| 22 | +#include<copyfile.h> |
| 23 | +#endif |
| 24 | +#ifdef__linux__ |
| 25 | +#include<sys/ioctl.h> |
| 26 | +#include<linux/fs.h> |
| 27 | +#endif |
21 | 28 |
|
22 | 29 |
|
23 | 30 | #ifdefWIN32
|
24 | 31 | staticintwin32_pghardlink(constchar*src,constchar*dst);
|
25 | 32 | #endif
|
26 | 33 |
|
27 | 34 |
|
| 35 | +/* |
| 36 | + * cloneFile() |
| 37 | + * |
| 38 | + * Clones/reflinks a relation file from src to dst. |
| 39 | + * |
| 40 | + * schemaName/relName are relation's SQL name (used for error messages only). |
| 41 | + */ |
| 42 | +void |
| 43 | +cloneFile(constchar*src,constchar*dst, |
| 44 | +constchar*schemaName,constchar*relName) |
| 45 | +{ |
| 46 | +#if defined(HAVE_COPYFILE)&& defined(COPYFILE_CLONE_FORCE) |
| 47 | +if (copyfile(src,dst,NULL,COPYFILE_CLONE_FORCE)<0) |
| 48 | +pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n", |
| 49 | +schemaName,relName,src,dst,strerror(errno)); |
| 50 | +#elif defined(__linux__)&& defined(FICLONE) |
| 51 | +intsrc_fd; |
| 52 | +intdest_fd; |
| 53 | + |
| 54 | +if ((src_fd=open(src,O_RDONLY |PG_BINARY,0))<0) |
| 55 | +pg_fatal("error while cloning relation \"%s.%s\": could not open file \"%s\": %s\n", |
| 56 | +schemaName,relName,src,strerror(errno)); |
| 57 | + |
| 58 | +if ((dest_fd=open(dst,O_RDWR |O_CREAT |O_EXCL |PG_BINARY, |
| 59 | +pg_file_create_mode))<0) |
| 60 | +pg_fatal("error while cloning relation \"%s.%s\": could not create file \"%s\": %s\n", |
| 61 | +schemaName,relName,dst,strerror(errno)); |
| 62 | + |
| 63 | +if (ioctl(dest_fd,FICLONE,src_fd)<0) |
| 64 | +{ |
| 65 | +unlink(dst); |
| 66 | +pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n", |
| 67 | +schemaName,relName,src,dst,strerror(errno)); |
| 68 | +} |
| 69 | + |
| 70 | +close(src_fd); |
| 71 | +close(dest_fd); |
| 72 | +#endif |
| 73 | +} |
| 74 | + |
| 75 | + |
28 | 76 | /*
|
29 | 77 | * copyFile()
|
30 | 78 | *
|
@@ -270,6 +318,48 @@ rewriteVisibilityMap(const char *fromfile, const char *tofile,
|
270 | 318 | close(src_fd);
|
271 | 319 | }
|
272 | 320 |
|
| 321 | +void |
| 322 | +check_file_clone(void) |
| 323 | +{ |
| 324 | +charexisting_file[MAXPGPATH]; |
| 325 | +charnew_link_file[MAXPGPATH]; |
| 326 | + |
| 327 | +snprintf(existing_file,sizeof(existing_file),"%s/PG_VERSION",old_cluster.pgdata); |
| 328 | +snprintf(new_link_file,sizeof(new_link_file),"%s/PG_VERSION.clonetest",new_cluster.pgdata); |
| 329 | +unlink(new_link_file);/* might fail */ |
| 330 | + |
| 331 | +#if defined(HAVE_COPYFILE)&& defined(COPYFILE_CLONE_FORCE) |
| 332 | +if (copyfile(existing_file,new_link_file,NULL,COPYFILE_CLONE_FORCE)<0) |
| 333 | +pg_fatal("could not clone file between old and new data directories: %s\n", |
| 334 | +strerror(errno)); |
| 335 | +#elif defined(__linux__)&& defined(FICLONE) |
| 336 | +{ |
| 337 | +intsrc_fd; |
| 338 | +intdest_fd; |
| 339 | + |
| 340 | +if ((src_fd=open(existing_file,O_RDONLY |PG_BINARY,0))<0) |
| 341 | +pg_fatal("could not open file \"%s\": %s\n", |
| 342 | +existing_file,strerror(errno)); |
| 343 | + |
| 344 | +if ((dest_fd=open(new_link_file,O_RDWR |O_CREAT |O_EXCL |PG_BINARY, |
| 345 | +pg_file_create_mode))<0) |
| 346 | +pg_fatal("could not create file \"%s\": %s\n", |
| 347 | +new_link_file,strerror(errno)); |
| 348 | + |
| 349 | +if (ioctl(dest_fd,FICLONE,src_fd)<0) |
| 350 | +pg_fatal("could not clone file between old and new data directories: %s\n", |
| 351 | +strerror(errno)); |
| 352 | + |
| 353 | +close(src_fd); |
| 354 | +close(dest_fd); |
| 355 | +} |
| 356 | +#else |
| 357 | +pg_fatal("file cloning not supported on this platform\n"); |
| 358 | +#endif |
| 359 | + |
| 360 | +unlink(new_link_file); |
| 361 | +} |
| 362 | + |
273 | 363 | void
|
274 | 364 | check_hard_link(void)
|
275 | 365 | {
|
|