*** a/src/backend/replication/basebackup.c
--- b/src/backend/replication/basebackup.c
***************
*** 45,51 **** typedef struct
  } basebackup_options;
  
  
! static int64 sendDir(char *path, int basepathlen, bool sizeonly);
  static int64 sendTablespace(char *path, bool sizeonly);
  static bool sendFile(char *readfilename, char *tarfilename,
  		 struct stat * statbuf, bool missing_ok);
--- 45,52 ----
  } basebackup_options;
  
  
! static int64 sendDir(char *path, int basepathlen, int rootpathlen,
! 					 bool sizeonly, List *tablespaces);
  static int64 sendTablespace(char *path, bool sizeonly);
  static bool sendFile(char *readfilename, char *tarfilename,
  		 struct stat * statbuf, bool missing_ok);
***************
*** 100,105 **** perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
--- 101,119 ----
  	XLogRecPtr	endptr;
  	TimeLineID	endtli;
  	char	   *labelfile;
+ 	char	    cwd[MAXPGPATH];
+ 	int         rootpathlen;
+ 
+ 	/*
+ 	 * We need to compute rootpathlen to allow for skipping tablespaces
+ 	 * installed within PGDATA.
+ 	 */
+ 	if (!getcwd(cwd, MAXPGPATH))
+ 		ereport(ERROR,
+ 				(errcode_for_file_access(),
+ 				 errmsg("could not determine current directory: %m")));
+ 
+ 	rootpathlen = strlen(cwd) + 1;
  
  	backup_started_in_recovery = RecoveryInProgress();
  
***************
*** 165,171 **** perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
  
  		/* Add a node for the base directory at the end */
  		ti = palloc0(sizeof(tablespaceinfo));
! 		ti->size = opt->progress ? sendDir(".", 1, true) : -1;
  		tablespaces = lappend(tablespaces, ti);
  
  		/* Send tablespace header */
--- 179,186 ----
  
  		/* Add a node for the base directory at the end */
  		ti = palloc0(sizeof(tablespaceinfo));
! 		ti->size = opt->progress ?
! 			sendDir(".", 1, rootpathlen, true, tablespaces) : -1;
  		tablespaces = lappend(tablespaces, ti);
  
  		/* Send tablespace header */
***************
*** 191,197 **** perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
  				sendFileWithContent(BACKUP_LABEL_FILE, labelfile);
  
  				/* ... then the bulk of the files ... */
! 				sendDir(".", 1, false);
  
  				/* ... and pg_control after everything else. */
  				if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
--- 206,212 ----
  				sendFileWithContent(BACKUP_LABEL_FILE, labelfile);
  
  				/* ... then the bulk of the files ... */
! 				sendDir(".", 1, rootpathlen, false, tablespaces);
  
  				/* ... and pg_control after everything else. */
  				if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
***************
*** 778,785 **** sendTablespace(char *path, bool sizeonly)
  		_tarWriteHeader(TABLESPACE_VERSION_DIRECTORY, NULL, &statbuf);
  	size = 512;					/* Size of the header just added */
  
! 	/* Send all the files in the tablespace version directory */
! 	size += sendDir(pathbuf, strlen(path), sizeonly);
  
  	return size;
  }
--- 793,805 ----
  		_tarWriteHeader(TABLESPACE_VERSION_DIRECTORY, NULL, &statbuf);
  	size = 512;					/* Size of the header just added */
  
! 	/*
! 	 * Send all the files in the tablespace version directory.
! 	 * Since we don't protect against nested tablespaces anywhere
! 	 * other than the root directory, no need to pass rootpathlen
! 	 * and tablespaces list.
! 	 */
! 	size += sendDir(pathbuf, strlen(path), 0, sizeonly, NIL);
  
  	return size;
  }
***************
*** 788,796 **** sendTablespace(char *path, bool sizeonly)
   * Include all files from the given directory in the output tar stream. If
   * 'sizeonly' is true, we just calculate a total length and return it, without
   * actually sending anything.
   */
  static int64
! sendDir(char *path, int basepathlen, bool sizeonly)
  {
  	DIR		   *dir;
  	struct dirent *de;
--- 808,820 ----
   * Include all files from the given directory in the output tar stream. If
   * 'sizeonly' is true, we just calculate a total length and return it, without
   * actually sending anything.
+  *
+  * Omit any directory listed in tablepaces, so as to avoid backuping
+  * tablespaces twice when users created their tablespaces inside PGDATA.
   */
  static int64
! sendDir(char *path, int basepathlen, int rootpathlen,
! 		bool sizeonly, List *tablespaces)
  {
  	DIR		   *dir;
  	struct dirent *de;
***************
*** 931,936 **** sendDir(char *path, int basepathlen, bool sizeonly)
--- 955,964 ----
  		}
  		else if (S_ISDIR(statbuf.st_mode))
  		{
+ 			bool skip_this_dir = false;
+ 			int pathbuflen = strlen(pathbuf);
+ 			ListCell *lc;
+ 
  			/*
  			 * Store a directory entry in the tar file so we can get the
  			 * permissions right.
***************
*** 939,946 **** sendDir(char *path, int basepathlen, bool sizeonly)
  				_tarWriteHeader(pathbuf + basepathlen + 1, NULL, &statbuf);
  			size += 512;		/* Size of the header just added */
  
! 			/* call ourselves recursively for a directory */
! 			size += sendDir(pathbuf, basepathlen, sizeonly);
  		}
  		else if (S_ISREG(statbuf.st_mode))
  		{
--- 967,1000 ----
  				_tarWriteHeader(pathbuf + basepathlen + 1, NULL, &statbuf);
  			size += 512;		/* Size of the header just added */
  
! 			/*
! 			 * call ourselves recursively for a directory, unless that
! 			 * directory is listed in the tablespaces list (which indicates
! 			 * that this is a tablespace that happens to be placed inside
! 			 * PGADATA)
! 			 */
! 			foreach(lc, tablespaces)
! 			{
! 				tablespaceinfo *ti = (tablespaceinfo *) lfirst(lc);
! 
! 				/*
! 				 * ti->path will have the complete absolute path to the
! 				 * tablespace target, whereas pathbuf holds a relative
! 				 * path (from the data directory, including "./").
! 				 * Compare the relative parts only */
! 				 */
! 				if (ti->path &&
! 					pathbuflen > 2 && /* ./ */
! 					strlen(ti->path) > rootpathlen &&
! 					strcmp(ti->path + rootpathlen, pathbuf + 2) == 0)
! 				{
! 					skip_this_dir = true;
! 					break;
! 				}
! 			}
! 			if (!skip_this_dir)
! 				size += sendDir(pathbuf, basepathlen, rootpathlen,
! 								sizeonly, tablespaces);
  		}
  		else if (S_ISREG(statbuf.st_mode))
  		{
