Skip to content

options: add --nice process-priority controls - #1011

Open
michaelmess-de wants to merge 24 commits into
RsyncProject:masterfrom
michaelmess-de:niceness-nice-level-improved
Open

michaelmess-de wants to merge 24 commits into
RsyncProject:masterfrom
michaelmess-de:niceness-nice-level-improved

Conversation

@michaelmess-de

@michaelmess-de michaelmess-de commented Jun 17, 2026 •

Copy link
Copy Markdown
Contributor

Introduced new option --nice=... to specify the nice/ionice level for the local/remote process

rsync --nice (LOCATION|[LOCATION:]SETTING)[,...] ...

LOCATION: local|remote|all
    LOCAL is the local rsync process that has been started by the user/script/etc.
    REMOTE it the remote rsync process that has been started via SSH on the remote system
    ALL means both, local and remote.
    The constants are not case sensitive, thus e.g. REMOTE and remote are the same value.
    If omitted, the default is: all
SETTING: NICESETTING|IONICESETTING|NICESETTING/IONICESETTING
    If the whole setting is omitted, the default is 19/IDLE
NICESETTING:   -20...19
    Higher number means lower priority, negative numbers require root permissions
    If not specified in the setting, the default is 0. 
    No system call is made to set the priority 0.
    If the setting fails, e.g. due to the lack of permission to set negative nice
    priority, the issue is ignored and rsync will continue doing its work.
IONICESETTING: RT_0|RT_1|RT_2|RT_3|RT_4|RT_5|RT_6|RT_7|NONE|BE_0|BE_1|BE_2|BE_3|BE_4|BE_5|BE_6|BE_7|IDLE
    RT_X is realtime priority, need root permission
    BE_X is best effort with the given level
    IDLE means the process gets served only when no other processes are using disk io.
    NONE means best effort with level calculated by the formula (cpu_nice + 20) / 5
         and is the default that does not need to be set.
    The constants are not case sensitive, thus e.g. IDLE and idle are the same value.
    If not specified in the setting, the default is NONE.
    No system call is made to set the priority NONE.
    If the setting fails, e.g. due to the lack of permission to set realtime
    priority, the issue is ignored and rsync will continue doing its work.

Examples:

Specifying a setting for both, local and remote:
 --nice 19/idle = --nice all:19/idle
 --nice 19      = --nice all:19       (no ionice -> set 0)
 --nice idle    = --nice all:idle     (no nice -> set 0)
 --nice 0       = --nice all:0        (nice value 0 and no ionice -> 0/0 == unset)

Specifying a setting for the given location:
 -- nice local:19,remote:5
 -- nice local:19/idle,remote:5
 -- nice local:19/be_0,remote:idle

No setting specified means default 19/idle:
 -- nice local   = --nice local:19/idle
 -- nice remote  = --nice remote:19/idle
 -- nice all, -Q = --nice local,remote = --nice local --nice remote

Any specific setting set before may be overwritten by the following setting, e. g.:
 --nice local:5 --nice all 
 --nice local:6/idle,all
 --nice local:5 --nice remote:6 -Q
would result in setting the default 19/idle for both, local and remote.

nice and ionice are always set as a pair, even when only one of them is specified.
 --nice remote:5 --nice remote:idle
therefore would result in an unset nice value and ionice value idle beeing applied.

With this approach, all valid values for nice and ionice can be applied and successfully set, provided that any necessary permissions are available (root, CAP_SYS_NICE, CAP_SYS_ADMIN) for the affected process.
In case the priority cannot be set (Permission denied), rsync will just issue a warning and continue normally.

For keeping or lowering priority, that means nice values >= 0 and ionice values of NONE, BE_X, IDLE no special permissions are required.

@steadytao

Copy link
Copy Markdown
Member

Thanks for the work on this but I think the current implementation is too large and complex for the feature it provides, especially when process priority can already be managed with nice, ionice, service managers and --rsync-path. I do not think we should merge this approach.

@michaelmess-de

Copy link
Copy Markdown
Contributor Author

Hi @steadytao ,
Many users like to have simple solutions like just adding a command line option instead of fiddling around with --rsync-path and using nice and ionice instead. Especially in scripts which might be used in different environments, this might be challenging.

This merge request is a successor of #933 and #945, thanks to @tridge and @devZer0 for your comments to help to improve the feature.
I have already rebased it to the new 3.5.0 release main.

@michaelmess-de
michaelmess-de force-pushed the niceness-nice-level-improved branch from f7a838c to 6199dac Compare August 18, 2026 21:28
@steadytao

Copy link
Copy Markdown
Member

Hmmmm. I am still a bit mixed on this one. Will try and organise my thoughts over this week/weekend.

@michaelmess-de
michaelmess-de force-pushed the niceness-nice-level-improved branch from 6199dac to 43dec56 Compare August 27, 2026 22:21
@steadytao

Copy link
Copy Markdown
Member

I have reconsidered this after the latest update but the implementation is still more than 1000 lines across 14 files for functionality already available through nice, ionice, service managers and --rsync-path. The additional parsing, platform and remote-process surface is not proportionate to the feature. I do not think we should merge this approach but I would like some opinions from @tridge on the matter.

@michaelmess-de
michaelmess-de force-pushed the niceness-nice-level-improved branch from 43dec56 to f4f9448 Compare September 9, 2026 16:27
@michaelmess-de

Copy link
Copy Markdown
Contributor Author

I think the average user will not wrickle around with --rsync-path to try to renice or ionice the process. Instead most people would be happy to just easily specify this as an option.
Without easily specifying priorities, most people would not do that at all and probably seeking other options like reducing the backup frequency or even to start it manually only to reduce the annoying performance impact on users working on the machine.
This is why I think this feature would be much beneficial.

@michaelmess-de
michaelmess-de force-pushed the niceness-nice-level-improved branch from f4f9448 to 15c6ccc Compare October 6, 2026 20:02
@steadytao

Copy link
Copy Markdown
Member

Hmmmm. I have been convinced. Will review.

@steadytao steadytao self-assigned this Oct 8, 2026
@steadytao

Copy link
Copy Markdown
Member

A bit more pressing matters at the moment. Will cycle back to this.

@steadytao steadytao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Run git diff --check as well

Comment thread main.c Outdated
Comment thread options.c
Comment thread niceness/parse_arguments.c Outdated
Comment thread niceness/parse_arguments.c
Comment thread testsuite/niceness-option-processing_test.py
Comment thread rsync.1.md Outdated
@steadytao steadytao changed the title New feature: Niceness: change nice and ionice level of the local and/or remote process using the --nice option options: add --nice process-priority controls Oct 19, 2026

@steadytao steadytao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some other reviews outstanding as well. Thank you for your work thus far.

Comment thread main.c
@michaelmess-de
michaelmess-de force-pushed the niceness-nice-level-improved branch from fb33061 to 13dba81 Compare October 21, 2026 23:52
@michaelmess-de

Copy link
Copy Markdown
Contributor Author

Hi @steadytao, thank you for your review. I hope that I have successfully resolved all the issues from it, but there are still some failing platform checks that I will have to look at, if they can be fixed or if I have to ignore them for the platform.
Maybe I should also add a light version which does not use strace, but maybe will do it on more platforms, what do you think?

Cheers,
Michael

@steadytao steadytao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks you for your work. I had another proper pass over the current head. Please do not add a second light suite. The current three test files are already 955 lines; fold the local and remote strace cases into one Linux-only test and keep the parsing and forwarding coverage portable. The six red jobs do need fixing.

There are also two daemon bugs still outstanding: direct daemon transfers never apply the option after parsing it, and the sign check still lets a client raise I/O priority with be_0. I have left comments on both. Add one real direct-daemon regression once those are fixed as well please.

Comment thread main.c
Comment thread niceness/parse_arguments.c
Comment thread Makefile.in
@michaelmess-de
michaelmess-de force-pushed the niceness-nice-level-improved branch from 334d230 to 3a2bb40 Compare October 22, 2026 12:10
@michaelmess-de

Copy link
Copy Markdown
Contributor Author

Current state is:

  • alma linux (skipped because strace is not available) - I would suggest installing strace on the test machine
  • Ubuntu/Ubuntu22 (skipped because host key verification fails) - But basic-ssh test succeeds - I will have to look what is different from that test, leading to this issue - locally (i have ubuntu) there is no issue with that.

When the tests on all three platforms succeed, we shouldn't have a failure issue due to the linux skip list.
But Linux is one of the important platforms where the tests should succeed, thus adding it to the skip list wouldn't be an option.

On other platforms the tests cat be easily skipped, when not supported by the platform.

@steadytao

Copy link
Copy Markdown
Member

Going to rework this.

@michaelmess-de

Copy link
Copy Markdown
Contributor Author

Remaining issue now:

2026-10-23T01:28:48.2692979Z checking for wchar.h... yes
2026-10-23T01:28:48.2920936Z checking linux/ioprio.h usability... no
2026-10-23T01:28:48.3018741Z checking linux/ioprio.h presence... no
2026-10-23T01:28:48.3019140Z checking for linux/ioprio.h... no
2026-10-23T01:28:48.3219629Z checking sys/syscall.h usability... yes

The header file linux/ioprio.h is not available on almalinux, thus the test is skipped because the functionality is not available:

2026-10-23T01:30:08.1806975Z SKIP    niceness-ssh-strace (Skipping tests because niceness is not supported on this platform)

@michaelmess-de

Copy link
Copy Markdown
Contributor Author

Regarding nice/ionice in daemon mode:

For renice a non-root and non-capable (CAP_SYS_NICE) user process cannot decrease the nice value;
decreasing nice value means increasing priority.
thus a process having prio 0 can switch to lower prio 1 but cannot go back to prio 0 afterwards.
Thus processes can reduce their priority for some work to be done in background but cannot
reprioritize themselves to their original priority when they want to do something in
the foreground, e. g. presenting the results of a long calculation done with low priority
in a GUI with their original priority to be responsive on a heavily loaded system.
For such purposes a main process can create child processes which decrease their priority
before starting work and die when work is done, while the main process keeps priority.

michael@thinkpad:~$ renice 3 $$
245883 (process ID) old priority 0, new priority 3
michael@thinkpad:~$ renice 2 $$
renice: failed to set priority for 245883 (process ID): Permission denied
michael@thinkpad:~$ renice 4 $$
245883 (process ID) old priority 3, new priority 4
michael@thinkpad:~$ renice 3 $$
renice: failed to set priority for 245883 (process ID): Permission denied
michael@thinkpad:~$ renice 4 $$
245883 (process ID) old priority 4, new priority 4
michael@thinkpad:~$ sudo renice -10 245883 
[sudo] password for michael: 
245883 (process ID) old priority 4, new priority -10
michael@thinkpad:~$ renice -6 $$
245883 (process ID) old priority -10, new priority -6
michael@thinkpad:~$ renice -6 $$
245883 (process ID) old priority -6, new priority -6
michael@thinkpad:~$ renice -7 $$
renice: failed to set priority for 245883 (process ID): Permission denied
michael@thinkpad:~$ renice -6 $$
245883 (process ID) old priority -6, new priority -6
michael@thinkpad:~$ renice -5 $$
245883 (process ID) old priority -6, new priority -5
michael@thinkpad:~$ renice -1 $$
245883 (process ID) old priority -5, new priority -1

But for ionice the behaviour is different:

Even for a normal process it is possible to assign every ionice value to the process, with exception of the realtime priority ("-c1").

michael@thinkpad:~$ ps $$
    PID TTY      STAT   TIME COMMAND
 245421 pts/3    Ss     0:00 bash
michael@thinkpad:~$ ps -f $$
UID          PID    PPID  C STIME TTY      STAT   TIME CMD
michael   245421    7155  0 15:22 pts/3    Ss     0:00 bash
michael@thinkpad:~$ ionice -p $$
none: prio 0
michael@thinkpad:~$ ionice -p $$ -c2 
michael@thinkpad:~$ ionice -p $$
best-effort: prio 4
michael@thinkpad:~$ ionice -p $$ -c2 -n 5
michael@thinkpad:~$ ionice -p $$
best-effort: prio 5
michael@thinkpad:~$ ionice -p $$ -c2 -n 3
michael@thinkpad:~$ ionice -p $$
best-effort: prio 3
michael@thinkpad:~$ ionice -p $$ -c2 -n 0
michael@thinkpad:~$ ionice -p $$
best-effort: prio 0
michael@thinkpad:~$ ionice -p $$ -c3
michael@thinkpad:~$ ionice -p $$
idle
michael@thinkpad:~$ ionice -p $$ -c2 -n 0
michael@thinkpad:~$ ionice -p $$
best-effort: prio 0
michael@thinkpad:~$ ionice -p $$ -c1 -n 3
ionice: ioprio_set failed: Operation not permitted
michael@thinkpad:~$ ionice -p $$
best-effort: prio 0
michael@thinkpad:~$ 

Thus (re-)increasing io-priorities is possible, with the exeption of real-time priorities.

Thus for ionice the current rsync behaviour is correct, but for nice in daemon mode we should forbid increasing the value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants