Skip to content

Commit 5c4daeb

Browse files
authored
add io_nice for background rsync tasks (#492)
1 parent b2151aa commit 5c4daeb

File tree

8 files changed

+72
-26
lines changed

8 files changed

+72
-26
lines changed

src/Core/Main.vala

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,11 +1659,7 @@ public class Main : GLib.Object{
16591659
task.delete_extra = true;
16601660
task.delete_excluded = true;
16611661
task.delete_after = false;
1662-
1663-
if (app_mode.length > 0){
1664-
// console mode
1665-
task.io_nice = true;
1666-
}
1662+
task.io_nice = (app_mode.length > 0);
16671663

16681664
task.execute();
16691665

@@ -4020,10 +4016,7 @@ public class Main : GLib.Object{
40204016
task.delete_excluded = true;
40214017
task.delete_after = false;
40224018

4023-
if (app_mode.length > 0){
4024-
// console mode
4025-
task.io_nice = true;
4026-
}
4019+
task.io_nice = (app_mode.length > 0);
40274020

40284021
task.dry_run = true;
40294022

src/Utility/AsyncTask.vala

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public abstract class AsyncTask : GLib.Object{
6363
public int64 prg_count = 0;
6464
public int64 prg_count_total = 0;
6565

66+
public bool io_nice = true; // renice child processes to IDlE PRIO
67+
6668
// signals
6769
public signal void stdout_line_read(string line);
6870
public signal void stderr_line_read(string line);
@@ -112,7 +114,7 @@ public abstract class AsyncTask : GLib.Object{
112114
}
113115

114116
protected abstract string build_script();
115-
117+
116118
protected virtual bool begin() {
117119
status = AppStatus.RUNNING;
118120

@@ -131,20 +133,27 @@ public abstract class AsyncTask : GLib.Object{
131133
timer = new GLib.Timer();
132134
timer.start();
133135

136+
GLib.SpawnChildSetupFunc? childsetup = null;
137+
138+
if(this.io_nice) {
139+
// change io prio of process, right before it execs
140+
childsetup = () => TeeJee.ProcessHelper.ioprio_set(0, IoPrio.prioValue(IoPrio.PrioClass.IDLE, 0));
141+
}
142+
134143
// execute script file
135144
Process.spawn_async_with_pipes(
136145
working_dir, // working dir
137146
spawn_args, // argv
138147
spawn_env, // environment
139148
SpawnFlags.SEARCH_PATH,
140-
null, // child_setup
149+
childsetup, // child_setup
141150
out child_pid,
142151
out input_fd,
143152
out output_fd,
144153
out error_fd);
145154

146155
log_debug("AsyncTask: child_pid: %d".printf(child_pid));
147-
156+
148157
// create stream readers
149158
UnixOutputStream uos_in = new UnixOutputStream(input_fd, true);
150159
UnixInputStream uis_out = new UnixInputStream(output_fd, true);

src/Utility/DeleteFileTask.vala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ public class DeleteFileTask : AsyncTask{
3333
// settings
3434
public string dest_path = "";
3535
public bool verbose = true;
36-
public bool io_nice = true;
3736
public bool use_rsync = false;
3837

3938
//private
@@ -80,10 +79,6 @@ public class DeleteFileTask : AsyncTask{
8079
protected override string build_script() {
8180
var cmd = "";
8281

83-
if (io_nice){
84-
//cmd += "ionice -c2 -n7 ";
85-
}
86-
8782
if (use_rsync){
8883

8984
cmd += "rsync -aii";

src/Utility/RsyncSpaceCheckTask.vala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ public class RsyncSpaceCheckTask : AsyncTask{
4141
public string source_path = "";
4242
public string dest_path = "";
4343
public bool verbose = true;
44-
public bool io_nice = true;
4544
public bool dry_run = false;
4645

4746
// regex

src/Utility/RsyncTask.vala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ public class RsyncTask : AsyncTask{
5757
public string source_path = "";
5858
public string dest_path = "";
5959
public bool verbose = true;
60-
public bool io_nice = true;
6160
public bool dry_run = false;
6261

6362
// regex
@@ -186,10 +185,6 @@ public class RsyncTask : AsyncTask{
186185

187186
var cmd = "export LC_ALL=C.UTF-8\n";
188187

189-
if (io_nice){
190-
//cmd += "ionice -c2 -n7 ";
191-
}
192-
193188
cmd += "rsync -aii";
194189

195190
//if (!dry_run){

src/Utility/TeeJee.Process.vala

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,9 @@ namespace TeeJee.ProcessHelper{
367367

368368
public Pid[] get_process_children (Pid parent_pid){
369369

370-
/* Returns the list of child processes owned by a given process */
370+
/* Returns the list of child processes owned by a given process
371+
This does not contain grand children
372+
*/
371373

372374
// no explicit check for the existence of /proc/ as this might be a time-of-check-time-of-use bug.
373375
File procfs = File.new_for_path("/proc/");
@@ -490,4 +492,17 @@ namespace TeeJee.ProcessHelper{
490492

491493
process_set_priority (procID, 5);
492494
}
495+
496+
/*
497+
Wrapper for the ioprio_set syscall (has no libc wrapper)
498+
see: man 2 ioprio_set
499+
500+
pid may be 0 (self)
501+
prio shall be constructed using IoPrio.prioValue
502+
returns true on success
503+
sets Posix.errno on error
504+
*/
505+
public static bool ioprio_set(Pid pid, int prio) {
506+
return 0 == IoPrio.syscall(IoPrio.SYS_ioprio_set, IoPrio.IOPRIO_WHO_PROCESS, pid, prio);
507+
}
493508
}

src/meson.build

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,25 @@ sources_app_gtk = files([
9595
'AppGtk.vala',
9696
])
9797

98+
vala_opts = [
99+
'--vapidir=' + meson.current_source_dir() / 'vapi',
100+
'--pkg', 'ioprio'
101+
]
102+
98103
timeshift = executable('timeshift',
99104
sources_app_console + sources_core + sources_utility,
100105
config_header,
101106
dependencies: dependencies,
102-
install: true
107+
install: true,
108+
vala_args: vala_opts
103109
)
104110

105111
timeshift_gtk = executable('timeshift-gtk',
106112
sources_app_gtk + sources_core + sources_utility + sources_gtk,
107113
config_header,
108114
dependencies: dependencies,
109-
install: true
115+
install: true,
116+
vala_args: vala_opts
110117
)
111118

112119
install_data(

src/vapi/ioprio.vapi

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
// iorpio syscalls
3+
4+
[CCode (cprefix = "", lower_case_cprefix = "")]
5+
namespace IoPrio {
6+
[CCode (cheader_filename = "unistd.h", sentinel = "", feature_test_macro = "_DEFAULT_SOURCE")]
7+
extern long syscall (long number, ...);
8+
9+
[CCode (cheader_filename = "sys/syscall.h")]
10+
public const int SYS_ioprio_get;
11+
12+
[CCode (cheader_filename = "sys/syscall.h")]
13+
public const int SYS_ioprio_set;
14+
15+
[CCode (cheader_filename = "linux/ioprio.h")]
16+
public const int IOPRIO_WHO_PROCESS;
17+
18+
[CCode (cheader_filename = "linux/ioprio.h", cname = "int", cprefix = "IOPRIO_CLASS_")]
19+
public enum PrioClass {
20+
NONE,
21+
RT,
22+
BE,
23+
IDLE,
24+
INVALID,
25+
}
26+
27+
/*
28+
construct a prio value using a PrioClass and a class specific data attribute
29+
See man 2 ioprio_set for details
30+
*/
31+
[CCode (cheader_filename = "linux/ioprio.h", cname = "IOPRIO_PRIO_VALUE")]
32+
extern int prioValue(PrioClass clas, int data);
33+
}

0 commit comments

Comments
 (0)