aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/storage/smgr/md.c89
1 files changed, 65 insertions, 24 deletions
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 200cc7f657a..424dfef6dd1 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -406,6 +406,41 @@ mdunlink(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
mdunlinkfork(rnode, forkNum, isRedo);
}
+/*
+ * Truncate a file to release disk space.
+ */
+static int
+do_truncate(const char *path)
+{
+ int save_errno;
+ int ret;
+ int fd;
+
+ /* truncate(2) would be easier here, but Windows hasn't got it */
+ fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
+ if (fd >= 0)
+ {
+ ret = ftruncate(fd, 0);
+ save_errno = errno;
+ CloseTransientFile(fd);
+ errno = save_errno;
+ }
+ else
+ ret = -1;
+
+ /* Log a warning here to avoid repetition in callers. */
+ if (ret < 0 && errno != ENOENT)
+ {
+ save_errno = errno;
+ ereport(WARNING,
+ (errcode_for_file_access(),
+ errmsg("could not truncate file \"%s\": %m", path)));
+ errno = save_errno;
+ }
+
+ return ret;
+}
+
static void
mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
{
@@ -419,33 +454,28 @@ mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
*/
if (isRedo || forkNum != MAIN_FORKNUM || RelFileNodeBackendIsTemp(rnode))
{
- ret = unlink(path);
- if (ret < 0 && errno != ENOENT)
- ereport(WARNING,
- (errcode_for_file_access(),
- errmsg("could not remove file \"%s\": %m", path)));
- }
- else
- {
- /* truncate(2) would be easier here, but Windows hasn't got it */
- int fd;
-
- fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
- if (fd >= 0)
+ if (!RelFileNodeBackendIsTemp(rnode))
{
- int save_errno;
-
- ret = ftruncate(fd, 0);
- save_errno = errno;
- CloseTransientFile(fd);
- errno = save_errno;
+ /* Prevent other backends' fds from holding on to the disk space */
+ ret = do_truncate(path);
}
else
- ret = -1;
- if (ret < 0 && errno != ENOENT)
- ereport(WARNING,
- (errcode_for_file_access(),
- errmsg("could not truncate file \"%s\": %m", path)));
+ ret = 0;
+
+ /* Next unlink the file, unless it was already found to be missing */
+ if (ret == 0 || errno != ENOENT)
+ {
+ ret = unlink(path);
+ if (ret < 0 && errno != ENOENT)
+ ereport(WARNING,
+ (errcode_for_file_access(),
+ errmsg("could not remove file \"%s\": %m", path)));
+ }
+ }
+ else
+ {
+ /* Prevent other backends' fds from holding on to the disk space */
+ ret = do_truncate(path);
/* Register request to unlink first segment later */
register_unlink(rnode);
@@ -466,6 +496,17 @@ mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
for (segno = 1;; segno++)
{
sprintf(segpath, "%s.%u", path, segno);
+
+ if (!RelFileNodeBackendIsTemp(rnode))
+ {
+ /*
+ * Prevent other backends' fds from holding on to the disk
+ * space.
+ */
+ if (do_truncate(segpath) < 0 && errno == ENOENT)
+ break;
+ }
+
if (unlink(segpath) < 0)
{
/* ENOENT is expected after the last segment... */