raster pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=15e1519d640f87a0b5946d72546d522c2538615d

commit 15e1519d640f87a0b5946d72546d522c2538615d
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
Date:   Tue Feb 9 13:25:13 2021 +0000

    efm - sync much more often to avoid hangs/stalls with lots of data
    
    do big ops like big copies of 3 or 5gb files over to an nfs mount or a
    slow thumbdrive... the os can happily store it all in RAM. but then
    any stats on that file still being flushed stall - definitely on nfs.
    this leads to much badness. so sync ever 0.2 sec OR every 512k worth
    of writes to stay interactive. it's a big worse for perf and maybe a
    bit worse on wear but it's far more usable.
    
    @opt
---
 src/bin/e_fm_op.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)

diff --git a/src/bin/e_fm_op.c b/src/bin/e_fm_op.c
index 043642ed2..aa12887dd 100644
--- a/src/bin/e_fm_op.c
+++ b/src/bin/e_fm_op.c
@@ -48,6 +48,8 @@ void *alloca(size_t);
 #define COPYBUFSIZE     16384
 #define REMOVECHUNKSIZE 4096
 #define NB_PASS         3
+#define SYNC_TIME       0.2
+#define SYNC_BYTES      (512 * 1024)
 
 #define E_FREE(p) do { free(p); p = NULL; } while (0)
 
@@ -126,6 +128,9 @@ Eina_List *_e_fm_op_separator = NULL;
 
 char *_e_fm_op_stdin_buffer = NULL;
 
+double _e_fm_op_last_sync = 0.0;
+unsigned long long _e_fm_op_bytes_sync = 0;
+
 struct _E_Fm_Op_Task
 {
    struct
@@ -422,6 +427,7 @@ skip_arg:
 
    _e_fm_op_set_up_idlers();
 
+   _e_fm_op_last_sync = ecore_time_get();
    ecore_main_loop_begin();
 
 quit:
@@ -1160,6 +1166,7 @@ static void
 _e_fm_op_copy_stat_info(E_Fm_Op_Task *task)
 {
    struct utimbuf ut;
+   double now = ecore_time_get();
 
    if (!task->dst.name) return;
 
@@ -1170,6 +1177,17 @@ _e_fm_op_copy_stat_info(E_Fm_Op_Task *task)
    ut.actime = task->src.st.st_atime;
    ut.modtime = task->src.st.st_mtime;
    utime(task->dst.name, &ut);
+   if ((now - _e_fm_op_last_sync) > SYNC_TIME)
+     {
+        int fd = open(task->dst.name, O_RDWR);
+
+        if (fd >= 0)
+          {
+             syncfs(fd);
+             _e_fm_op_last_sync = now;
+             close(fd);
+          }
+     }
 }
 
 static int
@@ -1234,6 +1252,7 @@ static int
 _e_fm_op_copy_dir(E_Fm_Op_Task *task)
 {
    struct stat st;
+   double now = ecore_time_get();
 
    /* Directory. Just create one in destatation. */
    if (mkdir(task->dst.name,
@@ -1264,7 +1283,20 @@ _e_fm_op_copy_dir(E_Fm_Op_Task *task)
                                    "Cannot make directory '%s': %s.",
                                    task->dst.name);
      }
+   else
+     {
+        if ((now - _e_fm_op_last_sync) > SYNC_TIME)
+          {
+             int fd = open(task->dst.name, O_RDWR);
 
+             if (fd >= 0)
+               {
+                  syncfs(fd);
+                  _e_fm_op_last_sync = now;
+                  close(fd);
+               }
+          }
+     }
    task->dst.done += task->src.st.st_size;
    _e_fm_op_update_progress(task, task->src.st.st_size, 0);
 
@@ -1279,6 +1311,7 @@ _e_fm_op_copy_link(E_Fm_Op_Task *task)
 {
    char *lnk_path;
    size_t lnk_len;
+   double now = ecore_time_get();
 
    lnk_path = ecore_file_readlink(task->src.name);
    if (!lnk_path)
@@ -1316,6 +1349,20 @@ _e_fm_op_copy_link(E_Fm_Op_Task *task)
              _E_FM_OP_ERROR_SEND_WORK(task, E_FM_OP_ERROR, "Cannot create link 
from '%s' to '%s': %s.", buf, task->dst.name);
           }
      }
+   else
+     {
+        if ((now - _e_fm_op_last_sync) > SYNC_TIME)
+          {
+             int fd = open(task->dst.name, O_RDWR);
+
+             if (fd >= 0)
+               {
+                  syncfs(fd);
+                  _e_fm_op_last_sync = now;
+                  close(fd);
+               }
+          }
+     }
    free(lnk_path);
 
    task->dst.done += task->src.st.st_size;
@@ -1330,6 +1377,8 @@ _e_fm_op_copy_link(E_Fm_Op_Task *task)
 static int
 _e_fm_op_copy_fifo(E_Fm_Op_Task *task)
 {
+   double now = ecore_time_get();
+
    if (mkfifo(task->dst.name, task->src.st.st_mode) == -1)
      {
         if (errno == EEXIST)
@@ -1342,6 +1391,20 @@ _e_fm_op_copy_fifo(E_Fm_Op_Task *task)
         else
           _E_FM_OP_ERROR_SEND_WORK(task, E_FM_OP_ERROR, "Cannot make FIFO at 
'%s': %s.", task->dst.name);
      }
+   else
+     {
+        if ((now - _e_fm_op_last_sync) > SYNC_TIME)
+          {
+             int fd = open(task->dst.name, O_RDWR);
+
+             if (fd >= 0)
+               {
+                  syncfs(fd);
+                  _e_fm_op_last_sync = now;
+                  close(fd);
+               }
+          }
+     }
 
    _e_fm_op_copy_stat_info(task);
 
@@ -1389,13 +1452,19 @@ static int
 _e_fm_op_copy_chunk(E_Fm_Op_Task *task)
 {
    E_Fm_Op_Copy_Data *data;
-   size_t dread, dwrite;
+   unsigned long long dread, dwrite;
    char buf[COPYBUFSIZE];
+   double now = ecore_time_get();
 
    data = task->data;
 
    if (_e_fm_op_abort)
      {
+        if ((now - _e_fm_op_last_sync) > SYNC_TIME)
+          {
+             syncfs(fileno(data->to));
+             _e_fm_op_last_sync = now;
+          }
         _e_fm_op_rollback(task);
 
         task->finished = 1;
@@ -1408,6 +1477,12 @@ _e_fm_op_copy_chunk(E_Fm_Op_Task *task)
         if (!feof(data->from))
           _E_FM_OP_ERROR_SEND_WORK(task, E_FM_OP_ERROR, "Cannot read data from 
'%s': %s.", task->dst.name);
 
+        if ((now - _e_fm_op_last_sync) > SYNC_TIME)
+          {
+             fflush(data->to);
+             syncfs(fileno(data->to));
+             _e_fm_op_last_sync = now;
+          }
         fclose(data->from);
         fclose(data->to);
         data->to = NULL;
@@ -1425,6 +1500,15 @@ _e_fm_op_copy_chunk(E_Fm_Op_Task *task)
      }
 
    dwrite = fwrite(buf, 1, dread, data->to);
+   _e_fm_op_bytes_sync += dread;
+   if (((now - _e_fm_op_last_sync) > SYNC_TIME) ||
+       (_e_fm_op_bytes_sync > SYNC_BYTES))
+     {
+        fflush(data->to);
+        syncfs(fileno(data->to));
+        _e_fm_op_last_sync = now;
+        _e_fm_op_bytes_sync = 0;
+     }
 
    if (dwrite < dread)
      _E_FM_OP_ERROR_SEND_WORK(task, E_FM_OP_ERROR, "Cannot write data to '%s': 
%s.", task->dst.name);
@@ -1700,6 +1784,8 @@ _e_fm_op_symlink_atom(E_Fm_Op_Task *task)
 static int
 _e_fm_op_remove_atom(E_Fm_Op_Task *task)
 {
+   double now = ecore_time_get();
+
    if (_e_fm_op_abort) return 1;
 
    E_FM_OP_DEBUG("Remove: %s\n", task->src.name);
@@ -1715,6 +1801,17 @@ _e_fm_op_remove_atom(E_Fm_Op_Task *task)
                      If this happens (for example new files were created after 
the scan was
                      complete), implicitly delete everything. */
                   ecore_file_recursive_rm(task->src.name);
+                  if ((now - _e_fm_op_last_sync) > SYNC_TIME)
+                    {
+                       int fd = open(task->src.name, O_RDWR);
+
+                       if (fd >= 0)
+                         {
+                            syncfs(fd);
+                            _e_fm_op_last_sync = now;
+                            close(fd);
+                         }
+                    }
                   task->finished = 1; /* Make sure that task is removed. */
                   return 1;
                }
@@ -1724,6 +1821,17 @@ _e_fm_op_remove_atom(E_Fm_Op_Task *task)
      }
    else if (unlink(task->src.name) == -1)
      _E_FM_OP_ERROR_SEND_WORK(task, E_FM_OP_ERROR, "Cannot remove file '%s': 
%s.", task->src.name);
+   if ((now - _e_fm_op_last_sync) > SYNC_TIME)
+     {
+        int fd = open(task->src.name, O_RDWR);
+
+        if (fd >= 0)
+          {
+             syncfs(fd);
+             _e_fm_op_last_sync = now;
+             close(fd);
+          }
+     }
 
    task->dst.done += REMOVECHUNKSIZE;
    _e_fm_op_update_progress(task, REMOVECHUNKSIZE, 0);

-- 


Reply via email to