diff --git a/doc/src/sgml/ref/pg_basebackup.sgml b/doc/src/sgml/ref/pg_basebackup.sgml
index eb0c1d6..4c4d06d 100644
--- a/doc/src/sgml/ref/pg_basebackup.sgml
+++ b/doc/src/sgml/ref/pg_basebackup.sgml
@@ -203,6 +203,18 @@ PostgreSQL documentation
      </varlistentry>
 
      <varlistentry>
+      <term><option>--xlogdir=<replaceable class="parameter">xlogdir</replaceable></option></term>
+      <listitem>
+       <para>
+        Specify the location for the transaction log directory. 
+        <literal>xlogdir</literal> should be an absolute path.
+        User can specify the xlog directory, only if the format is plain.
+        Data directory and xlog directory shouldn't be same.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
       <term><option>-x</option></term>
       <term><option>--xlog</option></term>
       <listitem>
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index a1e12a8..acaedac 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -35,6 +35,7 @@
 
 /* Global options */
 char	   *basedir = NULL;
+static char *xlog_dir = "";
 char		format = 'p';		/* p(lain)/t(ar) */
 char	   *label = "pg_basebackup base backup";
 bool		showprogress = false;
@@ -73,6 +74,8 @@ static PQExpBuffer recoveryconfcontents = NULL;
 
 /* Function headers */
 static void usage(void);
+static char *get_current_working_dir();
+static char *get_absolute_path(const char *input_path);
 static void verify_dir_is_empty_or_create(char *dirname);
 static void progress_report(int tablespacenum, const char *filename);
 
@@ -115,6 +118,7 @@ usage(void)
 	printf(_("  -x, --xlog             include required WAL files in backup (fetch mode)\n"));
 	printf(_("  -X, --xlog-method=fetch|stream\n"
 			 "                         include required WAL files with specified method\n"));
+	printf(_("      --xlogdir=XLOGDIR  location for the transaction log directory\n"));
 	printf(_("  -z, --gzip             compress tar output\n"));
 	printf(_("  -Z, --compress=0-9     compress tar output with given compression level\n"));
 	printf(_("\nGeneral options:\n"));
@@ -343,6 +347,81 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
 }
 
 /*
+ * Returns the malloced string of containing current working directory.
+ * The caller has to take care of freeing the memory.
+ * On failure exits with error code.
+ */
+static char *
+get_current_working_dir()
+{
+	char	   *buf;
+	size_t		buflen;
+
+	buflen = MAXPGPATH;
+	for (;;)
+	{
+		buf = pg_malloc(buflen);
+		if (getcwd(buf, buflen))
+			break;
+		else if (errno == ERANGE)
+		{
+			pg_free(buf);
+			buflen *= 2;
+			continue;
+		}
+		else
+		{
+			pg_free(buf);
+			fprintf(stderr,
+					_("%s: could not get current working directory: %s\n"),
+					progname, strerror(errno));
+			exit(1);
+		}
+	}
+
+	return buf;
+}
+
+/*
+ * calculates the absolute path for the given path. The output absolute path
+ * is a malloced string. The caller needs to take care of freeing the memory.
+ */
+static char *
+get_absolute_path(const char *input_path)
+{
+	char	   *pwd = NULL;
+	char	   *abspath = NULL;
+
+	/* Getting the present working directory */
+	pwd = get_current_working_dir();
+
+	if (chdir(input_path) < 0)
+	{
+		pg_free(pwd);
+		/* Directory doesn't exist */
+		if (errno == ENOENT)
+			return NULL;
+
+		fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),
+				progname, input_path, strerror(errno));
+		exit(1);
+	}
+
+	abspath = get_current_working_dir();
+
+	/* Returning back to old working directory */
+	if (chdir(pwd) < 0)
+	{
+		fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),
+				progname, pwd, strerror(errno));
+		exit(1);
+	}
+
+	pg_free(pwd);
+	return abspath;
+}
+
+/*
  * Verify that the given directory exists and is empty. If it does not
  * exist, it is created. If it exists but is not empty, an error will
  * be give and the process ended.
@@ -979,11 +1058,12 @@ ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
 					if (mkdir(filename, S_IRWXU) != 0)
 					{
 						/*
-						 * When streaming WAL, pg_xlog will have been created
-						 * by the wal receiver process, so just ignore failure
-						 * on that.
+						 * If user specified xlog_dir or when streaming WAL,
+						 * pg_xlog will have been created. So just ignore
+						 * failure on that.
 						 */
-						if (!streamwal || strcmp(filename + strlen(filename) - 8, "/pg_xlog") != 0)
+						if ((!streamwal && (strcmp(xlog_dir, "") == 0))
+							|| strcmp(filename + strlen(filename) - 8, "/pg_xlog") != 0)
 						{
 							fprintf(stderr,
 							_("%s: could not create directory \"%s\": %s\n"),
@@ -1666,6 +1746,7 @@ main(int argc, char **argv)
 		{"status-interval", required_argument, NULL, 's'},
 		{"verbose", no_argument, NULL, 'v'},
 		{"progress", no_argument, NULL, 'P'},
+		{"xlogdir", required_argument, NULL, 1},
 		{NULL, 0, NULL, 0}
 	};
 	int			c;
@@ -1750,6 +1831,9 @@ main(int argc, char **argv)
 					exit(1);
 				}
 				break;
+			case 1:
+				xlog_dir = pg_strdup(optarg);
+				break;
 			case 'l':
 				label = pg_strdup(optarg);
 				break;
@@ -1862,10 +1946,11 @@ main(int argc, char **argv)
 		exit(1);
 	}
 
-	if (format != 'p' && streamwal)
+	if (format != 'p' && (streamwal || (strcmp(xlog_dir, "") != 0)))
 	{
 		fprintf(stderr,
-				_("%s: WAL streaming can only be used in plain mode\n"),
+				_("%s: Providing user specified xlog directory or "
+				  "WAL streaming can only be used in plain mode\n"),
 				progname);
 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
 				progname);
@@ -1882,6 +1967,20 @@ main(int argc, char **argv)
 	}
 #endif
 
+	/* validating the provided xlog directory path */
+	if (strcmp(xlog_dir, "") != 0)
+	{
+		/* clean up xlog directory name, check it's absolute */
+		canonicalize_path(xlog_dir);
+		if (!is_absolute_path(xlog_dir))
+		{
+			fprintf(stderr, _("%s: transaction log directory location must be "
+							  "an absolute path\n"), progname);
+			exit(1);
+		}
+	}
+
+
 	/*
 	 * Verify that the target directory exists, or create it. For plaintext
 	 * backups, always require the directory. For tar backups, require it
@@ -1890,6 +1989,53 @@ main(int argc, char **argv)
 	if (format == 'p' || strcmp(basedir, "-") != 0)
 		verify_dir_is_empty_or_create(basedir);
 
+	/* Create transaction log symlink, if required */
+	if (strcmp(xlog_dir, "") != 0)
+	{
+		char	   *datadir = NULL;
+		char	   *linkloc;
+
+		/* Get the absolute path for provided data directory */
+		datadir = get_absolute_path(basedir);
+		if (datadir != NULL)
+		{
+			/*
+			 * checking the provided data and xlog directories are same or
+			 * not?
+			 */
+			canonicalize_path(datadir);
+			if (strcmp(datadir, xlog_dir) == 0)
+			{
+				rmdir(basedir);
+				fprintf(stderr, _("%s: Provided data directory and transaction"
+								  " log directories are same\n"), progname);
+				exit(1);
+			}
+
+			pg_free(datadir);
+		}
+
+		verify_dir_is_empty_or_create(xlog_dir);
+
+		/* form name of the place where the symlink must go */
+		linkloc = (char *) pg_malloc0(strlen(basedir) + 8 + 1);
+		sprintf(linkloc, "%s/pg_xlog", basedir);
+
+#ifdef HAVE_SYMLINK
+		if (symlink(xlog_dir, linkloc) != 0)
+		{
+			fprintf(stderr, _("%s: could not create symbolic link \"%s\": %s\n"),
+					progname, linkloc, strerror(errno));
+			exit(1);
+		}
+#else
+		fprintf(stderr, _("%s: symlinks are not supported on this platform "
+						  "cannot use xlogdir"));
+		exit(1);
+#endif
+		pg_free(linkloc);
+	}
+
 	BaseBackup();
 
 	return 0;
