@@ -45,7 +45,7 @@ typedef struct
4545}basebackup_options ;
4646
4747
48- static int64 sendDir (char * path ,int basepathlen ,bool sizeonly );
48+ static int64 sendDir (char * path ,int basepathlen ,bool sizeonly , List * tablespaces );
4949static int64 sendTablespace (char * path ,bool sizeonly );
5050static bool sendFile (char * readfilename ,char * tarfilename ,
5151struct stat * statbuf ,bool missing_ok );
@@ -72,6 +72,7 @@ typedef struct
7272{
7373char * oid ;
7474char * path ;
75+ char * rpath ;/* relative path within PGDATA, or NULL */
7576int64 size ;
7677}tablespaceinfo ;
7778
@@ -100,6 +101,9 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
100101XLogRecPtr endptr ;
101102TimeLineID endtli ;
102103char * labelfile ;
104+ int datadirpathlen ;
105+
106+ datadirpathlen = strlen (DataDir );
103107
104108backup_started_in_recovery = RecoveryInProgress ();
105109
@@ -119,6 +123,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
119123{
120124char fullpath [MAXPGPATH ];
121125char linkpath [MAXPGPATH ];
126+ char * relpath = NULL ;
122127int rllen ;
123128
124129/* Skip special stuff */
@@ -145,9 +150,20 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
145150}
146151linkpath [rllen ]= '\0' ;
147152
153+ /*
154+ * Relpath holds the relative path of the tablespace directory
155+ * when it's located within PGDATA, or NULL if it's located
156+ * elsewhere.
157+ */
158+ if (rllen > datadirpathlen &&
159+ strncmp (linkpath ,DataDir ,datadirpathlen )== 0 &&
160+ IS_DIR_SEP (linkpath [datadirpathlen ]))
161+ relpath = linkpath + datadirpathlen + 1 ;
162+
148163ti = palloc (sizeof (tablespaceinfo ));
149164ti -> oid = pstrdup (de -> d_name );
150165ti -> path = pstrdup (linkpath );
166+ ti -> rpath = relpath ?pstrdup (relpath ) :NULL ;
151167ti -> size = opt -> progress ?sendTablespace (fullpath , true) :-1 ;
152168tablespaces = lappend (tablespaces ,ti );
153169#else
@@ -165,7 +181,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
165181
166182/* Add a node for the base directory at the end */
167183ti = palloc0 (sizeof (tablespaceinfo ));
168- ti -> size = opt -> progress ?sendDir ("." ,1 , true) :-1 ;
184+ ti -> size = opt -> progress ?sendDir ("." ,1 , true, tablespaces ) :-1 ;
169185tablespaces = lappend (tablespaces ,ti );
170186
171187/* Send tablespace header */
@@ -191,7 +207,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
191207sendFileWithContent (BACKUP_LABEL_FILE ,labelfile );
192208
193209/* ... then the bulk of the files ... */
194- sendDir ("." ,1 , false);
210+ sendDir ("." ,1 , false, tablespaces );
195211
196212/* ... and pg_control after everything else. */
197213if (lstat (XLOG_CONTROL_FILE ,& statbuf )!= 0 )
@@ -744,6 +760,8 @@ sendFileWithContent(const char *filename, const char *content)
744760 * Include the tablespace directory pointed to by 'path' in the output tar
745761 * stream.If 'sizeonly' is true, we just calculate a total length and return
746762 * it, without actually sending anything.
763+ *
764+ * Only used to send auxiliary tablespaces, not PGDATA.
747765 */
748766static int64
749767sendTablespace (char * path ,bool sizeonly )
@@ -779,7 +797,7 @@ sendTablespace(char *path, bool sizeonly)
779797size = 512 ;/* Size of the header just added */
780798
781799/* Send all the files in the tablespace version directory */
782- size += sendDir (pathbuf ,strlen (path ),sizeonly );
800+ size += sendDir (pathbuf ,strlen (path ),sizeonly , NIL );
783801
784802return size ;
785803}
@@ -788,9 +806,12 @@ sendTablespace(char *path, bool sizeonly)
788806 * Include all files from the given directory in the output tar stream. If
789807 * 'sizeonly' is true, we just calculate a total length and return it, without
790808 * actually sending anything.
809+ *
810+ * Omit any directory in the tablespaces list, to avoid backing up
811+ * tablespaces twice when they were created inside PGDATA.
791812 */
792813static int64
793- sendDir (char * path ,int basepathlen ,bool sizeonly )
814+ sendDir (char * path ,int basepathlen ,bool sizeonly , List * tablespaces )
794815{
795816DIR * dir ;
796817struct dirent * de ;
@@ -931,6 +952,9 @@ sendDir(char *path, int basepathlen, bool sizeonly)
931952}
932953else if (S_ISDIR (statbuf .st_mode ))
933954{
955+ bool skip_this_dir = false;
956+ ListCell * lc ;
957+
934958/*
935959 * Store a directory entry in the tar file so we can get the
936960 * permissions right.
@@ -939,8 +963,29 @@ sendDir(char *path, int basepathlen, bool sizeonly)
939963_tarWriteHeader (pathbuf + basepathlen + 1 ,NULL ,& statbuf );
940964size += 512 ;/* Size of the header just added */
941965
942- /* call ourselves recursively for a directory */
943- size += sendDir (pathbuf ,basepathlen ,sizeonly );
966+ /*
967+ * Call ourselves recursively for a directory, unless it happens
968+ * to be a separate tablespace located within PGDATA.
969+ */
970+ foreach (lc ,tablespaces )
971+ {
972+ tablespaceinfo * ti = (tablespaceinfo * )lfirst (lc );
973+
974+ /*
975+ * ti->rpath is the tablespace relative path within PGDATA, or
976+ * NULL if the tablespace has been properly located somewhere
977+ * else.
978+ *
979+ * Skip past the leading "./" in pathbuf when comparing.
980+ */
981+ if (ti -> rpath && strcmp (ti -> rpath ,pathbuf + 2 )== 0 )
982+ {
983+ skip_this_dir = true;
984+ break ;
985+ }
986+ }
987+ if (!skip_this_dir )
988+ size += sendDir (pathbuf ,basepathlen ,sizeonly ,tablespaces );
944989}
945990else if (S_ISREG (statbuf .st_mode ))
946991{