if (info == XLOG_SMGR_CREATE)
        {
                xl_smgr_create *xlrec = (xl_smgr_create *) rec;
-               char       *path = relpathperm(xlrec->rlocator, xlrec->forkNum);
 
-               appendStringInfoString(buf, path);
-               pfree(path);
+               appendStringInfoString(buf,
+                                                          relpathperm(xlrec->rlocator, xlrec->forkNum).str);
        }
        else if (info == XLOG_SMGR_TRUNCATE)
        {
                xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec;
-               char       *path = relpathperm(xlrec->rlocator, MAIN_FORKNUM);
 
-               appendStringInfo(buf, "%s to %u blocks flags %d", path,
+               appendStringInfo(buf, "%s to %u blocks flags %d",
+                                                relpathperm(xlrec->rlocator, MAIN_FORKNUM).str,
                                                 xlrec->blkno, xlrec->flags);
-               pfree(path);
        }
 }
 
 
                appendStringInfo(buf, "; %s:", label);
                for (i = 0; i < nrels; i++)
                {
-                       char       *path = relpathperm(xlocators[i], MAIN_FORKNUM);
-
-                       appendStringInfo(buf, " %s", path);
-                       pfree(path);
+                       appendStringInfo(buf, " %s",
+                                                        relpathperm(xlocators[i], MAIN_FORKNUM).str);
                }
        }
 }
 
 report_invalid_page(int elevel, RelFileLocator locator, ForkNumber forkno,
                                        BlockNumber blkno, bool present)
 {
-       char       *path = relpathperm(locator, forkno);
+       RelPathStr      path = relpathperm(locator, forkno);
 
        if (present)
                elog(elevel, "page %u of relation %s is uninitialized",
-                        blkno, path);
+                        blkno, path.str);
        else
                elog(elevel, "page %u of relation %s does not exist",
-                        blkno, path);
-       pfree(path);
+                        blkno, path.str);
 }
 
 /* Log a reference to an invalid page */
                        hentry->key.forkno == forkno &&
                        hentry->key.blkno >= minblkno)
                {
-                       if (message_level_is_interesting(DEBUG2))
-                       {
-                               char       *path = relpathperm(hentry->key.locator, forkno);
-
-                               elog(DEBUG2, "page %u of relation %s has been dropped",
-                                        hentry->key.blkno, path);
-                               pfree(path);
-                       }
+                       elog(DEBUG2, "page %u of relation %s has been dropped",
+                                hentry->key.blkno,
+                                relpathperm(hentry->key.locator, forkno).str);
 
                        if (hash_search(invalid_page_tab,
                                                        &hentry->key,
        {
                if (hentry->key.locator.dbOid == dbid)
                {
-                       if (message_level_is_interesting(DEBUG2))
-                       {
-                               char       *path = relpathperm(hentry->key.locator, hentry->key.forkno);
-
-                               elog(DEBUG2, "page %u of relation %s has been dropped",
-                                        hentry->key.blkno, path);
-                               pfree(path);
-                       }
+                       elog(DEBUG2, "page %u of relation %s has been dropped",
+                                hentry->key.blkno,
+                                relpathperm(hentry->key.locator, hentry->key.forkno).str);
 
                        if (hash_search(invalid_page_tab,
                                                        &hentry->key,
 
 GetIncrementalFilePath(Oid dboid, Oid spcoid, RelFileNumber relfilenumber,
                                           ForkNumber forknum, unsigned segno)
 {
-       char       *path;
+       RelPathStr      path;
        char       *lastslash;
        char       *ipath;
 
        path = GetRelationPath(dboid, spcoid, relfilenumber, INVALID_PROC_NUMBER,
                                                   forknum);
 
-       lastslash = strrchr(path, '/');
+       lastslash = strrchr(path.str, '/');
        Assert(lastslash != NULL);
        *lastslash = '\0';
 
        if (segno > 0)
-               ipath = psprintf("%s/INCREMENTAL.%s.%u", path, lastslash + 1, segno);
+               ipath = psprintf("%s/INCREMENTAL.%s.%u", path.str, lastslash + 1, segno);
        else
-               ipath = psprintf("%s/INCREMENTAL.%s", path, lastslash + 1);
-
-       pfree(path);
+               ipath = psprintf("%s/INCREMENTAL.%s", path.str, lastslash + 1);
 
        return ipath;
 }
 
 GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
 {
        RelFileLocatorBackend rlocator;
-       char       *rpath;
+       RelPathStr      rpath;
        bool            collides;
        ProcNumber      procNumber;
 
                /* Check for existing file of same name */
                rpath = relpath(rlocator, MAIN_FORKNUM);
 
-               if (access(rpath, F_OK) == 0)
+               if (access(rpath.str, F_OK) == 0)
                {
                        /* definite collision */
                        collides = true;
                         */
                        collides = false;
                }
-
-               pfree(rpath);
        } while (collides);
 
        return rlocator.locator.relNumber;
 
                         * (errcontext callbacks shouldn't be risking any such thing, but
                         * people have been known to forget that rule.)
                         */
-                       char       *relpath = relpathbackend(src->smgr_rlocator.locator,
+                       RelPathStr      relpath = relpathbackend(src->smgr_rlocator.locator,
                                                                                                 src->smgr_rlocator.backend,
                                                                                                 forkNum);
 
                        ereport(ERROR,
                                        (errcode(ERRCODE_DATA_CORRUPTED),
                                         errmsg("invalid page in block %u of relation %s",
-                                                       blkno, relpath)));
+                                                       blkno, relpath.str)));
                }
 
                /*
 
                                        else if (reloid == InvalidOid)
                                                elog(ERROR, "could not map filenumber \"%s\" to relation OID",
                                                         relpathperm(change->data.tp.rlocator,
-                                                                                MAIN_FORKNUM));
+                                                                                MAIN_FORKNUM).str);
 
                                        relation = RelationIdGetRelation(reloid);
 
                                                elog(ERROR, "could not open relation with OID %u (for filenumber \"%s\")",
                                                         reloid,
                                                         relpathperm(change->data.tp.rlocator,
-                                                                                MAIN_FORKNUM));
+                                                                                MAIN_FORKNUM).str);
 
                                        if (!RelationIsLogicallyLogged(relation))
                                                goto change_done;
 
                                                        (errcode(ERRCODE_DATA_CORRUPTED),
                                                         errmsg("invalid page in block %u of relation %s; zeroing out page",
                                                                        io_first_block + j,
-                                                                       relpath(operation->smgr->smgr_rlocator, forknum))));
+                                                                       relpath(operation->smgr->smgr_rlocator, forknum).str)));
                                        memset(bufBlock, 0, BLCKSZ);
                                }
                                else
                                                        (errcode(ERRCODE_DATA_CORRUPTED),
                                                         errmsg("invalid page in block %u of relation %s",
                                                                        io_first_block + j,
-                                                                       relpath(operation->smgr->smgr_rlocator, forknum))));
+                                                                       relpath(operation->smgr->smgr_rlocator, forknum).str)));
                        }
 
                        /* Terminate I/O and set BM_VALID. */
                ereport(ERROR,
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                 errmsg("cannot extend relation %s beyond %u blocks",
-                                               relpath(bmr.smgr->smgr_rlocator, fork),
+                                               relpath(bmr.smgr->smgr_rlocator, fork).str,
                                                MaxBlockNumber)));
 
        /*
                        if (valid && !PageIsNew((Page) buf_block))
                                ereport(ERROR,
                                                (errmsg("unexpected data beyond EOF in block %u of relation %s",
-                                                               existing_hdr->tag.blockNum, relpath(bmr.smgr->smgr_rlocator, fork)),
+                                                               existing_hdr->tag.blockNum,
+                                                               relpath(bmr.smgr->smgr_rlocator, fork).str),
                                                 errhint("This has been seen to occur with buggy kernels; consider updating your system.")));
 
                        /*
 {
        BufferDesc *buf;
        int32           loccount;
-       char       *path;
        char       *result;
        ProcNumber      backend;
        uint32          buf_state;
        }
 
        /* theoretically we should lock the bufhdr here */
-       path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
-                                                 BufTagGetForkNum(&buf->tag));
        buf_state = pg_atomic_read_u32(&buf->state);
 
        result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
-                                         buffer, path,
+                                         buffer,
+                                         relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
+                                                                        BufTagGetForkNum(&buf->tag)).str,
                                          buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
                                          BUF_STATE_GET_REFCOUNT(buf_state), loccount);
-       pfree(path);
        return result;
 }
 
                if (buf_state & BM_IO_ERROR)
                {
                        /* Buffer is pinned, so we can read tag without spinlock */
-                       char       *path;
-
-                       path = relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag),
-                                                          BufTagGetForkNum(&buf_hdr->tag));
                        ereport(WARNING,
                                        (errcode(ERRCODE_IO_ERROR),
                                         errmsg("could not write block %u of %s",
-                                                       buf_hdr->tag.blockNum, path),
+                                                       buf_hdr->tag.blockNum,
+                                                       relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag),
+                                                                               BufTagGetForkNum(&buf_hdr->tag)).str),
                                         errdetail("Multiple failures --- write error might be permanent.")));
-                       pfree(path);
                }
        }
 
 
        /* Buffer is pinned, so we can read the tag without locking the spinlock */
        if (bufHdr != NULL)
-       {
-               char       *path = relpathperm(BufTagGetRelFileLocator(&bufHdr->tag),
-                                                                          BufTagGetForkNum(&bufHdr->tag));
-
                errcontext("writing block %u of relation %s",
-                                  bufHdr->tag.blockNum, path);
-               pfree(path);
-       }
+                                  bufHdr->tag.blockNum,
+                                  relpathperm(BufTagGetRelFileLocator(&bufHdr->tag),
+                                                          BufTagGetForkNum(&bufHdr->tag)).str);
 }
 
 /*
        BufferDesc *bufHdr = (BufferDesc *) arg;
 
        if (bufHdr != NULL)
-       {
-               char       *path = relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
-                                                                                 MyProcNumber,
-                                                                                 BufTagGetForkNum(&bufHdr->tag));
-
                errcontext("writing block %u of relation %s",
-                                  bufHdr->tag.blockNum, path);
-               pfree(path);
-       }
+                                  bufHdr->tag.blockNum,
+                                  relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
+                                                                 MyProcNumber,
+                                                                 BufTagGetForkNum(&bufHdr->tag)).str);
 }
 
 /*
 
                ereport(ERROR,
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                 errmsg("cannot extend relation %s beyond %u blocks",
-                                               relpath(bmr.smgr->smgr_rlocator, fork),
+                                               relpath(bmr.smgr->smgr_rlocator, fork).str,
                                                MaxBlockNumber)));
 
        for (uint32 i = 0; i < extend_by; i++)
                                         bufHdr->tag.blockNum,
                                         relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
                                                                        MyProcNumber,
-                                                                       BufTagGetForkNum(&bufHdr->tag)),
+                                                                       BufTagGetForkNum(&bufHdr->tag)).str,
                                         LocalRefCount[i]);
 
                        /* Remove entry from hashtable */
                                         bufHdr->tag.blockNum,
                                         relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
                                                                        MyProcNumber,
-                                                                       BufTagGetForkNum(&bufHdr->tag)),
+                                                                       BufTagGetForkNum(&bufHdr->tag)).str,
                                         LocalRefCount[i]);
                        /* Remove entry from hashtable */
                        hresult = (LocalBufferLookupEnt *)
 
 mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
 {
        MdfdVec    *mdfd;
-       char       *path;
+       RelPathStr      path;
        File            fd;
 
        if (isRedo && reln->md_num_open_segs[forknum] > 0)
 
        path = relpath(reln->smgr_rlocator, forknum);
 
-       fd = PathNameOpenFile(path, _mdfd_open_flags() | O_CREAT | O_EXCL);
+       fd = PathNameOpenFile(path.str, _mdfd_open_flags() | O_CREAT | O_EXCL);
 
        if (fd < 0)
        {
                int                     save_errno = errno;
 
                if (isRedo)
-                       fd = PathNameOpenFile(path, _mdfd_open_flags());
+                       fd = PathNameOpenFile(path.str, _mdfd_open_flags());
                if (fd < 0)
                {
                        /* be sure to report the error reported by create, not open */
                        errno = save_errno;
                        ereport(ERROR,
                                        (errcode_for_file_access(),
-                                        errmsg("could not create file \"%s\": %m", path)));
+                                        errmsg("could not create file \"%s\": %m", path.str)));
                }
        }
 
-       pfree(path);
-
        _fdvec_resize(reln, forknum, 1);
        mdfd = &reln->md_seg_fds[forknum][0];
        mdfd->mdfd_vfd = fd;
 static void
 mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
 {
-       char       *path;
+       RelPathStr      path;
        int                     ret;
        int                     save_errno;
 
                if (!RelFileLocatorBackendIsTemp(rlocator))
                {
                        /* Prevent other backends' fds from holding on to the disk space */
-                       ret = do_truncate(path);
+                       ret = do_truncate(path.str);
 
                        /* Forget any pending sync requests for the first segment */
                        save_errno = errno;
                /* Next unlink the file, unless it was already found to be missing */
                if (ret >= 0 || errno != ENOENT)
                {
-                       ret = unlink(path);
+                       ret = unlink(path.str);
                        if (ret < 0 && errno != ENOENT)
                        {
                                save_errno = errno;
                                ereport(WARNING,
                                                (errcode_for_file_access(),
-                                                errmsg("could not remove file \"%s\": %m", path)));
+                                                errmsg("could not remove file \"%s\": %m", path.str)));
                                errno = save_errno;
                        }
                }
        else
        {
                /* Prevent other backends' fds from holding on to the disk space */
-               ret = do_truncate(path);
+               ret = do_truncate(path.str);
 
                /* Register request to unlink first segment later */
                save_errno = errno;
         */
        if (ret >= 0 || errno != ENOENT)
        {
-               char       *segpath = (char *) palloc(strlen(path) + 12);
+               char       *segpath = (char *) palloc(strlen(path.str) + 12);
                BlockNumber segno;
 
                for (segno = 1;; segno++)
                {
-                       sprintf(segpath, "%s.%u", path, segno);
+                       sprintf(segpath, "%s.%u", path.str, segno);
 
                        if (!RelFileLocatorBackendIsTemp(rlocator))
                        {
                }
                pfree(segpath);
        }
-
-       pfree(path);
 }
 
 /*
                ereport(ERROR,
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                 errmsg("cannot extend file \"%s\" beyond %u blocks",
-                                               relpath(reln->smgr_rlocator, forknum),
+                                               relpath(reln->smgr_rlocator, forknum).str,
                                                InvalidBlockNumber)));
 
        v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE);
                ereport(ERROR,
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                 errmsg("cannot extend file \"%s\" beyond %u blocks",
-                                               relpath(reln->smgr_rlocator, forknum),
+                                               relpath(reln->smgr_rlocator, forknum).str,
                                                InvalidBlockNumber)));
 
        while (remblocks > 0)
 mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
 {
        MdfdVec    *mdfd;
-       char       *path;
+       RelPathStr      path;
        File            fd;
 
        /* No work if already open */
 
        path = relpath(reln->smgr_rlocator, forknum);
 
-       fd = PathNameOpenFile(path, _mdfd_open_flags());
+       fd = PathNameOpenFile(path.str, _mdfd_open_flags());
 
        if (fd < 0)
        {
                if ((behavior & EXTENSION_RETURN_NULL) &&
                        FILE_POSSIBLY_DELETED(errno))
-               {
-                       pfree(path);
                        return NULL;
-               }
                ereport(ERROR,
                                (errcode_for_file_access(),
-                                errmsg("could not open file \"%s\": %m", path)));
+                                errmsg("could not open file \"%s\": %m", path.str)));
        }
 
-       pfree(path);
-
        _fdvec_resize(reln, forknum, 1);
        mdfd = &reln->md_seg_fds[forknum][0];
        mdfd->mdfd_vfd = fd;
                        return;
                ereport(ERROR,
                                (errmsg("could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
-                                               relpath(reln->smgr_rlocator, forknum),
+                                               relpath(reln->smgr_rlocator, forknum).str,
                                                nblocks, curnblk)));
        }
        if (nblocks == curnblk)
 static char *
 _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
 {
-       char       *path,
-                          *fullpath;
+       RelPathStr      path;
+       char       *fullpath;
 
        path = relpath(reln->smgr_rlocator, forknum);
 
        if (segno > 0)
-       {
-               fullpath = psprintf("%s.%u", path, segno);
-               pfree(path);
-       }
+               fullpath = psprintf("%s.%u", path.str, segno);
        else
-               fullpath = path;
+               fullpath = pstrdup(path.str);
 
        return fullpath;
 }
 int
 mdunlinkfiletag(const FileTag *ftag, char *path)
 {
-       char       *p;
+       RelPathStr      p;
 
        /* Compute the path. */
        p = relpathperm(ftag->rlocator, MAIN_FORKNUM);
-       strlcpy(path, p, MAXPGPATH);
-       pfree(p);
+       strlcpy(path, p.str, MAXPGPATH);
 
        /* Try to unlink the file. */
        return unlink(path);
 
 calculate_relation_size(RelFileLocator *rfn, ProcNumber backend, ForkNumber forknum)
 {
        int64           totalsize = 0;
-       char       *relationpath;
+       RelPathStr      relationpath;
        char            pathname[MAXPGPATH];
        unsigned int segcount = 0;
 
 
                if (segcount == 0)
                        snprintf(pathname, MAXPGPATH, "%s",
-                                        relationpath);
+                                        relationpath.str);
                else
                        snprintf(pathname, MAXPGPATH, "%s.%u",
-                                        relationpath, segcount);
+                                        relationpath.str, segcount);
 
                if (stat(pathname, &fst) < 0)
                {
        Form_pg_class relform;
        RelFileLocator rlocator;
        ProcNumber      backend;
-       char       *path;
+       RelPathStr      path;
 
        tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
        if (!HeapTupleIsValid(tuple))
 
        path = relpathbackend(rlocator, backend, MAIN_FORKNUM);
 
-       PG_RETURN_TEXT_P(cstring_to_text(path));
+       PG_RETURN_TEXT_P(cstring_to_text(path.str));
 }
 
 static char *
 datasegpath(RelFileLocator rlocator, ForkNumber forknum, BlockNumber segno)
 {
-       char       *path;
+       RelPathStr      path;
        char       *segpath;
 
        path = relpathperm(rlocator, forknum);
        if (segno > 0)
        {
-               segpath = psprintf("%s.%u", path, segno);
-               pfree(path);
+               segpath = psprintf("%s.%u", path.str, segno);
                return segpath;
        }
        else
-               return path;
+               return pstrdup(path.str);
 }
 
 /*
 
 /*
  * GetRelationPath - construct path to a relation's file
  *
- * Result is a palloc'd string.
+ * The result is returned in-place as a struct, to make it suitable for use in
+ * critical sections etc.
  *
  * Note: ideally, procNumber would be declared as type ProcNumber, but
  * relpath.h would have to include a backend-only header to do that; doesn't
  * seem worth the trouble considering ProcNumber is just int anyway.
  */
-char *
+RelPathStr
 GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
                                int procNumber, ForkNumber forkNumber)
 {
-       char       *path;
+       RelPathStr      rp;
 
        if (spcOid == GLOBALTABLESPACE_OID)
        {
                Assert(dbOid == 0);
                Assert(procNumber == INVALID_PROC_NUMBER);
                if (forkNumber != MAIN_FORKNUM)
-                       path = psprintf("global/%u_%s",
-                                                       relNumber, forkNames[forkNumber]);
+                       sprintf(rp.str, "global/%u_%s",
+                                       relNumber, forkNames[forkNumber]);
                else
-                       path = psprintf("global/%u", relNumber);
+                       sprintf(rp.str, "global/%u",
+                                       relNumber);
        }
        else if (spcOid == DEFAULTTABLESPACE_OID)
        {
                if (procNumber == INVALID_PROC_NUMBER)
                {
                        if (forkNumber != MAIN_FORKNUM)
-                               path = psprintf("base/%u/%u_%s",
-                                                               dbOid, relNumber,
-                                                               forkNames[forkNumber]);
+                       {
+                               sprintf(rp.str, "base/%u/%u_%s",
+                                               dbOid, relNumber,
+                                               forkNames[forkNumber]);
+                       }
                        else
-                               path = psprintf("base/%u/%u",
-                                                               dbOid, relNumber);
+                               sprintf(rp.str, "base/%u/%u",
+                                               dbOid, relNumber);
                }
                else
                {
                        if (forkNumber != MAIN_FORKNUM)
-                               path = psprintf("base/%u/t%d_%u_%s",
-                                                               dbOid, procNumber, relNumber,
-                                                               forkNames[forkNumber]);
+                               sprintf(rp.str, "base/%u/t%d_%u_%s",
+                                               dbOid, procNumber, relNumber,
+                                               forkNames[forkNumber]);
                        else
-                               path = psprintf("base/%u/t%d_%u",
-                                                               dbOid, procNumber, relNumber);
+                               sprintf(rp.str, "base/%u/t%d_%u",
+                                               dbOid, procNumber, relNumber);
                }
        }
        else
                if (procNumber == INVALID_PROC_NUMBER)
                {
                        if (forkNumber != MAIN_FORKNUM)
-                               path = psprintf("%s/%u/%s/%u/%u_%s",
-                                                               PG_TBLSPC_DIR, spcOid,
-                                                               TABLESPACE_VERSION_DIRECTORY,
-                                                               dbOid, relNumber,
-                                                               forkNames[forkNumber]);
+                               sprintf(rp.str, "%s/%u/%s/%u/%u_%s",
+                                               PG_TBLSPC_DIR, spcOid,
+                                               TABLESPACE_VERSION_DIRECTORY,
+                                               dbOid, relNumber,
+                                               forkNames[forkNumber]);
                        else
-                               path = psprintf("%s/%u/%s/%u/%u",
-                                                               PG_TBLSPC_DIR, spcOid,
-                                                               TABLESPACE_VERSION_DIRECTORY,
-                                                               dbOid, relNumber);
+                               sprintf(rp.str, "%s/%u/%s/%u/%u",
+                                               PG_TBLSPC_DIR, spcOid,
+                                               TABLESPACE_VERSION_DIRECTORY,
+                                               dbOid, relNumber);
                }
                else
                {
                        if (forkNumber != MAIN_FORKNUM)
-                               path = psprintf("%s/%u/%s/%u/t%d_%u_%s",
-                                                               PG_TBLSPC_DIR, spcOid,
-                                                               TABLESPACE_VERSION_DIRECTORY,
-                                                               dbOid, procNumber, relNumber,
-                                                               forkNames[forkNumber]);
+                               sprintf(rp.str, "%s/%u/%s/%u/t%d_%u_%s",
+                                               PG_TBLSPC_DIR, spcOid,
+                                               TABLESPACE_VERSION_DIRECTORY,
+                                               dbOid, procNumber, relNumber,
+                                               forkNames[forkNumber]);
                        else
-                               path = psprintf("%s/%u/%s/%u/t%d_%u",
-                                                               PG_TBLSPC_DIR, spcOid,
-                                                               TABLESPACE_VERSION_DIRECTORY,
-                                                               dbOid, procNumber, relNumber);
+                               sprintf(rp.str, "%s/%u/%s/%u/t%d_%u",
+                                               PG_TBLSPC_DIR, spcOid,
+                                               TABLESPACE_VERSION_DIRECTORY,
+                                               dbOid, procNumber, relNumber);
                }
        }
-       return path;
+
+       Assert(strnlen(rp.str, REL_PATH_STR_MAXLEN + 1) <= REL_PATH_STR_MAXLEN);
+
+       return rp;
 }
 
 extern ForkNumber forkname_to_number(const char *forkName);
 extern int     forkname_chars(const char *str, ForkNumber *fork);
 
+
+/*
+ * Unfortunately, there's no easy way to derive PROCNUMBER_CHARS from
+ * MAX_BACKENDS. MAX_BACKENDS is 2^18-1. Crosschecked in test_relpath().
+ */
+#define PROCNUMBER_CHARS       6
+
+/*
+ * The longest possible relation path lengths is from the following format:
+ * sprintf(rp.path, "%s/%u/%s/%u/t%d_%u",
+ *         PG_TBLSPC_DIR, spcOid,
+ *         TABLESPACE_VERSION_DIRECTORY,
+ *         dbOid, procNumber, relNumber);
+ *
+ * Note this does *not* include the trailing null-byte, to make it easier to
+ * combine it with other lengths.
+ */
+#define REL_PATH_STR_MAXLEN \
+       ( \
+               sizeof(PG_TBLSPC_DIR) - 1 \
+               + sizeof((char)'/') \
+               + OIDCHARS /* spcOid */ \
+               + sizeof((char)'/') \
+               + sizeof(TABLESPACE_VERSION_DIRECTORY) - 1 \
+               + sizeof((char)'/') \
+               + OIDCHARS /* dbOid */ \
+               + sizeof((char)'/') \
+               + sizeof((char)'t') /* temporary table indicator */ \
+               + PROCNUMBER_CHARS /* procNumber */ \
+               + sizeof((char)'_') \
+               + OIDCHARS /* relNumber */ \
+               + sizeof((char)'_') \
+               + FORKNAMECHARS /* forkNames[forkNumber] */ \
+       )
+
+/*
+ * String of the exact length required to represent a relation path. We return
+ * this struct, instead of char[REL_PATH_STR_MAXLEN + 1], as the pointer would
+ * decay to a plain char * too easily, possibly preventing the compiler from
+ * detecting invalid references to the on-stack return value of
+ * GetRelationPath().
+ */
+typedef struct RelPathStr
+{
+       char            str[REL_PATH_STR_MAXLEN + 1];
+} RelPathStr;
+
+
 /*
  * Stuff for computing filesystem pathnames for relations.
  */
 extern char *GetDatabasePath(Oid dbOid, Oid spcOid);
 
-extern char *GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
-                                                        int procNumber, ForkNumber forkNumber);
+extern RelPathStr GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber,
+                                                                 int procNumber, ForkNumber forkNumber);
 
 /*
  * Wrapper macros for GetRelationPath.  Beware of multiple
 
                    18
 (1 row)
 
+-- relpath tests
+CREATE FUNCTION test_relpath()
+    RETURNS void
+    AS :'regresslib'
+    LANGUAGE C;
+SELECT test_relpath();
+ test_relpath 
+--------------
+ 
+(1 row)
+
 
 #include "optimizer/plancat.h"
 #include "parser/parse_coerce.h"
 #include "port/atomics.h"
+#include "postmaster/postmaster.h"     /* for MAX_BACKENDS */
 #include "storage/spin.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 
        PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype));
 }
+
+/*
+ * Sanity checks for functions in relpath.h
+ */
+PG_FUNCTION_INFO_V1(test_relpath);
+Datum
+test_relpath(PG_FUNCTION_ARGS)
+{
+       RelPathStr      rpath;
+
+       /*
+        * Verify that PROCNUMBER_CHARS and MAX_BACKENDS stay in sync.
+        * Unfortunately I don't know how to express that in a way suitable for a
+        * static assert.
+        */
+       if ((int) ceil(log10(MAX_BACKENDS)) != PROCNUMBER_CHARS)
+               elog(WARNING, "mismatch between MAX_BACKENDS and PROCNUMBER_CHARS");
+
+       /* verify that the max-length relpath is generated ok */
+       rpath = GetRelationPath(OID_MAX, OID_MAX, OID_MAX, MAX_BACKENDS - 1,
+                                                       INIT_FORKNUM);
+
+       if (strlen(rpath.str) != REL_PATH_STR_MAXLEN)
+               elog(WARNING, "maximum length relpath is if length %zu instead of %zu",
+                        strlen(rpath.str), REL_PATH_STR_MAXLEN);
+
+       PG_RETURN_VOID();
+}
 
 -- test stratnum support functions
 SELECT gist_stratnum_common(7);
 SELECT gist_stratnum_common(3);
+
+
+-- relpath tests
+CREATE FUNCTION test_relpath()
+    RETURNS void
+    AS :'regresslib'
+    LANGUAGE C;
+SELECT test_relpath();
 
 RelMapping
 RelOptInfo
 RelOptKind
+RelPathStr
 RelStatsInfo
 RelToCheck
 RelToCluster