diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 5383b0dfa53..1936ef89e57 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -29,6 +29,7 @@ Created 9/20/1997 Heikki Tuuri
 
 #include <map>
 #include <string>
+#include <unordered_map>
 #include <my_service_manager.h>
 
 #include "log0recv.h"
@@ -585,7 +586,7 @@ typedef std::map<
 static recv_spaces_t	recv_spaces;
 
 /** The last parsed FILE_RENAME records */
-static std::map<uint32_t,std::string> renamed_spaces;
+static std::map<ulint,std::string> renamed_spaces;
 
 /** Report an operation to create, delete, or rename a file during backup.
 @param[in]	space_id	tablespace identifier
@@ -2213,6 +2214,20 @@ bool recv_sys_t::parse(lsn_t checkpoint_lsn, store_t *store, bool apply)
 
         if (fn2 && apply)
         {
+//          if (fn2[0] == '.' && fn2[1] == '/')
+//            fn2 += 2;
+	if (srv_operation == SRV_OPERATION_RESTORE) {
+		/* Replace absolute DATA DIRECTORY file paths with
+		short names relative to the backup directory. */
+		if (const char* name = strrchr(fn2, OS_PATH_SEPARATOR)) {
+			while (--name > fn2
+			       && *name != OS_PATH_SEPARATOR);
+			if (name > fn2) {
+				fn2 = name + 1;
+			}
+		}
+	}
+
           const size_t len= fn2end - fn2;
           auto r= renamed_spaces.emplace(space_id, std::string{fn2, len});
           if (!r.second)
@@ -2634,6 +2649,32 @@ buf_block_t *recv_sys_t::recover_low(const page_id_t page_id)
   return block;
 }
 
+inline bool rename_space(fil_space_t *space, const std::string &new_filename)
+{
+  size_t base= new_filename.rfind(OS_PATH_SEPARATOR);
+  ut_ad(base != std::string::npos);
+  size_t start= new_filename.rfind(OS_PATH_SEPARATOR, base - 1);
+  if (start == std::string::npos)
+    start= 0;
+  /* Keep only databasename/tablename without .ibd suffix */
+  std::string space_name(new_filename, start, new_filename.size() - start - 4);
+  ut_ad(space_name[base - start] == OS_PATH_SEPARATOR);
+#if OS_PATH_SEPARATOR != '/'
+  space_name[base - start]= '/';
+#endif
+  mysql_mutex_lock(&log_sys.mutex);
+  bool result= true;
+  if (dberr_t err=
+          space->rename(space_name.c_str(), new_filename.c_str(), false))
+  {
+    ib::error() << "Cannot replay rename of tablespace " << space->id
+                << " to '" << new_filename << "': " << err;
+    result= false;
+  }
+  mysql_mutex_unlock(&log_sys.mutex);
+  return result;
+}
+
 /** Apply buffered log to persistent data pages.
 @param last_batch     whether it is possible to write more redo log */
 void recv_sys_t::apply(bool last_batch)
@@ -2807,56 +2848,66 @@ void recv_sys_t::apply(bool last_batch)
     buf_pool_invalidate();
     mysql_mutex_lock(&log_sys.mutex);
   }
-#if 1 /* Mariabackup FIXME: Remove or adjust rename_table_in_prepare() */
-  else if (srv_operation != SRV_OPERATION_NORMAL);
-#endif
   else
   {
+    std::unordered_map<std::string, ulint> reverse_renames;
     /* In the last batch, we will apply any rename operations. */
     for (auto r : renamed_spaces)
     {
-      const uint32_t id= r.first;
-      fil_space_t *space= fil_space_t::get(id);
-      if (!space)
+      const ulint id_src= r.first;
+      fil_space_t *space_src= fil_space_t::get(id_src);
+      if (!space_src)
         continue;
-      ut_ad(UT_LIST_GET_LEN(space->chain) == 1);
-      const char *old= space->chain.start->name;
-      if (r.second != old)
+      ut_ad(UT_LIST_GET_LEN(space_src->chain) == 1);
+      const char *filename_src= space_src->chain.start->name;
+      const std::string &filename_dst= r.second;
+      if (filename_dst != filename_src)
       {
         bool exists;
         os_file_type_t ftype;
-        const char *new_name= r.second.c_str();
-        if (!os_file_status(new_name, &exists, &ftype) || exists)
+        const char *filename_dst_cstr= filename_dst.c_str();
+        if (!os_file_status(filename_dst_cstr, &exists, &ftype) && !exists)
         {
-          ib::error() << "Cannot replay rename of tablespace " << id
-                      << " from '" << old << "' to '" << r.second << "'";
+          ib::error() << "Cannot access " << filename_dst
+                      << " to replay rename of tablespace " << id_src
+                      << " from '" << filename_src << "' to '" << filename_dst
+                      << "'";
           found_corrupt_fs= true;
         }
-        else
+        else if (exists)
         {
-          size_t base= r.second.rfind(OS_PATH_SEPARATOR);
-          ut_ad(base != std::string::npos);
-          size_t start= r.second.rfind(OS_PATH_SEPARATOR, base - 1);
-          if (start == std::string::npos)
-            start= 0;
-          /* Keep only databasename/tablename without .ibd suffix */
-          std::string space_name(r.second, start, r.second.size() - start - 4);
-          ut_ad(space_name[base - start] == OS_PATH_SEPARATOR);
-#if OS_PATH_SEPARATOR != '/'
-          space_name[base - start]= '/';
-#endif
-          mysql_mutex_lock(&log_sys.mutex);
-          if (dberr_t err= space->rename(space_name.c_str(), r.second.c_str(),
-                                         false))
+          auto reverse_rename_it = reverse_renames.find(filename_src);
+          if (reverse_rename_it != reverse_renames.end())
           {
-            ib::error() << "Cannot replay rename of tablespace " << id
-                        << " to '" << r.second << "': " << err;
-            found_corrupt_fs= true;
+            std::string tmp_name(filename_dst);
+            /* TODO: think about better way to form temporary file name */
+            tmp_name.append(".tmp");
+            fil_space_t *space_dst=
+                fil_space_t::get(reverse_rename_it->second);
+            if (!space_dst)
+              continue;
+            /* TODO: process errors so that any error would cause the whole
+             processing stop */
+            found_corrupt_fs |= !rename_space(space_dst, tmp_name);
+            found_corrupt_fs |= !rename_space(space_src, filename_dst);
+            found_corrupt_fs |= !rename_space(space_dst, filename_src);
+            space_dst->release();
+            reverse_renames.erase(reverse_rename_it);
           }
-          mysql_mutex_unlock(&log_sys.mutex);
+          else
+            reverse_renames[filename_dst] = space_src->id;
         }
+        else
+          found_corrupt_fs |= !rename_space(space_src, filename_dst);
       }
-      space->release();
+      space_src->release();
+    }
+    for (auto i : reverse_renames)
+    {
+      ib::error() << "Cannot replay rename of tablespace " << i.second
+                  << " from '" << renamed_spaces[i.second] << "' to '" << i.first
+                  << "' as '" << i.first << "' already exists";
+      found_corrupt_fs= true;
     }
     renamed_spaces.clear();
   }
