Subject: [PATCH] sort: rotate on ENOSPC while creating tmp files

From: Azat Khuzhin <[email-masked]>
Date: Mon, 12 May 2014 00:37:15 +0400

This can be useful in case you use partitions with different free space
on them. It will better to go to the next partition if we don't have
space on current one, instead of fail.

* src/sort.c (create_temp_file): Go through all available tmp dirs if we
got ENOSPC for the first one, and fail on the last.
---
Here is the RFC, comments are welcome. Thanks.

 src/sort.c | 38 ++++++++++++++++++++++++++------------
 1 file changed, 26 insertions(+), 12 deletions(-)

diff --git a/src/sort.c b/src/sort.c
index 3380be6..47348b7 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -853,22 +853,36 @@ create_temp_file (int *pfd, bool survive_fd_exhaustion)
   static size_t temp_dir_index;
   int fd;
   int saved_errno;
-  char const *temp_dir = temp_dirs[temp_dir_index];
-  size_t len = strlen (temp_dir);
-  struct tempnode *node =
-    xmalloc (offsetof (struct tempnode, name) + len + sizeof slashbase);
-  char *file = node->name;
+  char const *temp_dir;
+  size_t len;
+  struct tempnode *node = NULL;
+  char *file;
   struct cs_status cs;
-
-  memcpy (file, temp_dir, len);
-  memcpy (file + len, slashbase, sizeof slashbase);
-  node->next = NULL;
-  if (++temp_dir_index == temp_dir_count)
-    temp_dir_index = 0;
+  size_t start_dir_index = temp_dir_index;
 
   /* Create the temporary file in a critical section, to avoid races.  */
   cs = cs_enter ();
-  fd = mkstemp (file);
+  do
+    {
+      temp_dir = temp_dirs[temp_dir_index];
+      len = strlen (temp_dir);
+      node =
+        xrealloc (node,
+                  offsetof (struct tempnode, name) + len + sizeof slashbase);
+      file = node->name;
+      memcpy (file, temp_dir, len);
+      memcpy (file + len, slashbase, sizeof slashbase);
+      node->next = NULL;
+
+      if (++temp_dir_index == temp_dir_count)
+        temp_dir_index = 0;
+
+      fd = mkstemp (file);
+
+      if (errno != ENOSPC || temp_dir_index == start_dir_index)
+        break;
+    } while (0 <= fd);
+
   if (0 <= fd)
     {
       *temptail = node;
-- 
2.0.0.rc0