@ -10,6 +10,7 @@
# include "postgres_fe.h"
# include <sys/stat.h>
# include <limits.h>
# include <fcntl.h>
# ifdef HAVE_COPYFILE_H
# include <copyfile.h>
@ -140,6 +141,45 @@ copyFile(const char *src, const char *dst,
}
/*
* copyFileByRange ( )
*
* Copies a relation file from src to dst .
* schemaName / relName are relation ' s SQL name ( used for error messages only ) .
*/
void
copyFileByRange ( const char * src , const char * dst ,
const char * schemaName , const char * relName )
{
# ifdef HAVE_COPY_FILE_RANGE
int src_fd ;
int dest_fd ;
ssize_t nbytes ;
if ( ( src_fd = open ( src , O_RDONLY | PG_BINARY , 0 ) ) < 0 )
pg_fatal ( " error while copying relation \" %s.%s \" : could not open file \" %s \" : %s " ,
schemaName , relName , src , strerror ( errno ) ) ;
if ( ( dest_fd = open ( dst , O_RDWR | O_CREAT | O_EXCL | PG_BINARY ,
pg_file_create_mode ) ) < 0 )
pg_fatal ( " error while copying relation \" %s.%s \" : could not create file \" %s \" : %s " ,
schemaName , relName , dst , strerror ( errno ) ) ;
do
{
nbytes = copy_file_range ( src_fd , NULL , dest_fd , NULL , SSIZE_MAX , 0 ) ;
if ( nbytes < 0 )
pg_fatal ( " error while copying relation \" %s.%s \" : could not copy file range from \" %s \" to \" %s \" : %s " ,
schemaName , relName , src , dst , strerror ( errno ) ) ;
}
while ( nbytes > 0 ) ;
close ( src_fd ) ;
close ( dest_fd ) ;
# endif
}
/*
* linkFile ( )
*
@ -358,6 +398,44 @@ check_file_clone(void)
unlink ( new_link_file ) ;
}
void
check_copy_file_range ( void )
{
char existing_file [ MAXPGPATH ] ;
char new_link_file [ MAXPGPATH ] ;
snprintf ( existing_file , sizeof ( existing_file ) , " %s/PG_VERSION " , old_cluster . pgdata ) ;
snprintf ( new_link_file , sizeof ( new_link_file ) , " %s/PG_VERSION.copy_file_range_test " , new_cluster . pgdata ) ;
unlink ( new_link_file ) ; /* might fail */
# if defined(HAVE_COPY_FILE_RANGE)
{
int src_fd ;
int dest_fd ;
if ( ( src_fd = open ( existing_file , O_RDONLY | PG_BINARY , 0 ) ) < 0 )
pg_fatal ( " could not open file \" %s \" : %s " ,
existing_file , strerror ( errno ) ) ;
if ( ( dest_fd = open ( new_link_file , O_RDWR | O_CREAT | O_EXCL | PG_BINARY ,
pg_file_create_mode ) ) < 0 )
pg_fatal ( " could not create file \" %s \" : %s " ,
new_link_file , strerror ( errno ) ) ;
if ( copy_file_range ( src_fd , NULL , dest_fd , NULL , SSIZE_MAX , 0 ) < 0 )
pg_fatal ( " could not copy file range between old and new data directories: %s " ,
strerror ( errno ) ) ;
close ( src_fd ) ;
close ( dest_fd ) ;
}
# else
pg_fatal ( " copy_file_range not supported on this platform " ) ;
# endif
unlink ( new_link_file ) ;
}
void
check_hard_link ( void )
{