From bc601d1e4e29b4377d4a662a79704a2e3ffca757 Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 09:19:12 +0200 Subject: [PATCH 01/11] Added methods renice_me() and ionice_me() to reduce priority --- niceness.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 niceness.c diff --git a/niceness.c b/niceness.c new file mode 100644 index 000000000..f1625f061 --- /dev/null +++ b/niceness.c @@ -0,0 +1,48 @@ +/* + * Renice or ionice the current process to reduce its impact on the system + * + * Copyright (C) 2026 Michael Mess + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, visit the http://fsf.org website. + */ + +#include "rsync.h" + +void renice_me() +{ +#ifdef SUPPORT_RENICE + int which = PRIO_PROCESS; // who specifies a Process ID + int who = 0; // 0 means current process + int prio = 19; // lowest CPU Priority + int result = setpriority(which, who, prio); + if ( result < 0 ) { + // Failed to set priority, TODO: log or inform user, but can be ignored (it's just not so nice). + } +#endif +} + +void ionice_me() +{ +#ifdef SUPPORT_IONICE + int which = IOPRIO_WHO_PROCESS; // who specifies a Process ID + int who = 0; // 0 means current process + int class = IOPRIO_CLASS_IDLE; + int data = 0; // Ignored when using the IOPRIO_CLASS_IDLE class + int ioprio = IOPRIO_PRIO_VALUE(class, data); + int result = syscall(SYS_ioprio_set, which, who, ioprio); + if ( result < 0 ) { + // Failed to set priority, TODO: log or inform user, but can be ignored (it's just not so ionice). + } +#endif +} From 9b590a04ed2a8456a9f9c7d95291bb2060372374 Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 11:31:09 +0200 Subject: [PATCH 02/11] configure.ac: Check for sys/resource.h linux/ioprio.h sys/syscall.h header files. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4faab5fcb..a4071f539 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \ sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h dl.h \ popt.h popt/popt.h linux/falloc.h netinet/in_systm.h netgroup.h \ zlib.h xxhash.h openssl/md4.h openssl/md5.h zstd.h lz4.h sys/file.h \ - bsd/string.h) + bsd/string.h sys/resource.h linux/ioprio.h sys/syscall.h) AC_CHECK_HEADERS([netinet/ip.h], [], [], [[#include ]]) AC_HEADER_MAJOR_FIXED From 2631ad58203df9bd9c0e453ffe86e65d42fada72 Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 11:32:20 +0200 Subject: [PATCH 03/11] Added niceness.o to Makefile.in for build --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index bde2c5897..b595aa4f2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -46,7 +46,7 @@ zlib_OBJS=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \ OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \ util1.o util2.o main.o checksum.o match.o syscall.o log.o backup.o delete.o OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \ - usage.o fileio.o batch.o clientname.o chmod.o acls.o xattrs.o + usage.o fileio.o batch.o clientname.o chmod.o acls.o xattrs.o niceness.o OBJS3=progress.o pipe.o @MD5_ASM@ @ROLL_SIMD@ @ROLL_ASM@ DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o popt_OBJS= popt/popt.o popt/poptconfig.o \ From 608cc2e70cfaa18ecb876f80db535f1c73796de7 Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 13:33:39 +0200 Subject: [PATCH 04/11] Define SUPPORT_RENICE and SUPPORT_IONICE if the necessary header files exist --- rsync.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rsync.h b/rsync.h index cdc2d2c0d..cd6225c23 100644 --- a/rsync.h +++ b/rsync.h @@ -1510,3 +1510,13 @@ const char *get_panic_action(void); #elif defined HAVE_MALLINFO #define MEM_ALLOC_INFO mallinfo #endif + + /* Some header files needed to be nice ;) */ +#ifdef HAVE_SYS_RESOURCE_H +#define SUPPORT_RENICE +#endif + +#if defined HAVE_LINUX_IOPRIO_H && defined HAVE_SYS_SYSCALL_H +#define SUPPORT_IONICE +#endif + From c058cf1b298e1ae2b2cc328b6fcec9db8132d41f Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 13:37:09 +0200 Subject: [PATCH 05/11] Added includes --- rsync.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rsync.h b/rsync.h index cd6225c23..0b4a2f769 100644 --- a/rsync.h +++ b/rsync.h @@ -1514,9 +1514,12 @@ const char *get_panic_action(void); /* Some header files needed to be nice ;) */ #ifdef HAVE_SYS_RESOURCE_H #define SUPPORT_RENICE +#include #endif #if defined HAVE_LINUX_IOPRIO_H && defined HAVE_SYS_SYSCALL_H #define SUPPORT_IONICE +#include +#include #endif From 0cc2224d4b938853323d62e4421f4de492f7d484 Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 14:00:02 +0200 Subject: [PATCH 06/11] Ensure that rsync.h definitions are included only once --- rsync.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rsync.h b/rsync.h index 0b4a2f769..0c9e935ec 100644 --- a/rsync.h +++ b/rsync.h @@ -18,6 +18,9 @@ * with this program; if not, visit the http://fsf.org website. */ +#ifndef RSYNC_H // Ensure that this header file is never included more than once, thus avoiding errors with duplicate definitions +#define RSYNC_H 1 + #define False 0 #define True 1 #define Unset (-1) /* Our BOOL values are always an int. */ @@ -1523,3 +1526,4 @@ const char *get_panic_action(void); #include #endif +#endif // ifndef RSYNC_H From bece7fe960513894ed811f0f0bd5f8fbd97805c0 Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 20:59:45 +0200 Subject: [PATCH 07/11] Option parsing for nice and ionice and remote argument --- options.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/options.c b/options.c index 3c2d23526..dccda125d 100644 --- a/options.c +++ b/options.c @@ -35,6 +35,12 @@ extern filter_rule_list daemon_filter_list; int make_backups = 0; +/* If set, be nice on the local or remote site */ +int nice_local = 0; +int nice_remote = 0; +int ionice_local = 0; +int ionice_remote = 0; + /** * If 1, send the whole file as literal data rather than trying to * create an incremental diff. @@ -594,7 +600,7 @@ enum {OPT_SERVER = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG, OPT_BLOCK_SIZE, OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_BWLIMIT, OPT_STDERR, OPT_OLD_COMPRESS, OPT_NEW_COMPRESS, OPT_NO_COMPRESS, OPT_OLD_ARGS, - OPT_STOP_AFTER, OPT_STOP_AT, + OPT_STOP_AFTER, OPT_STOP_AT, OPT_NICE, OPT_NO_NICE, OPT_IONICE, OPT_NO_IONICE, OPT_REFUSED_BASE = 9000}; static struct poptOption long_options[] = { @@ -845,6 +851,19 @@ static struct poptOption long_options[] = { {"remote-option", 'M', POPT_ARG_STRING, 0, 'M', 0, 0 }, {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 }, {"checksum-seed", 0, POPT_ARG_INT, &checksum_seed, 0, 0, 0 }, + {"nice-local", 0, POPT_ARG_VAL, &nice_local, 1, 0, 0 }, + {"nice-remote", 0, POPT_ARG_VAL, &nice_remote, 1, 0, 0 }, + {"ionice-local", 0, POPT_ARG_VAL, &ionice_local, 1, 0, 0 }, + {"ionice-remote", 0, POPT_ARG_VAL, &ionice_remote, 1, 0, 0 }, + {"no-nice-local", 0, POPT_ARG_VAL, &nice_local, 0, 0, 0 }, + {"no-nice-remote", 0, POPT_ARG_VAL, &nice_remote, 0, 0, 0 }, + {"no-ionice-local", 0, POPT_ARG_VAL, &ionice_local, 0, 0, 0 }, + {"no-ionice-remote", 0, POPT_ARG_VAL, &ionice_remote, 0, 0, 0 }, + {"nice", 0, POPT_ARG_NONE, 0, OPT_NICE, 0, 0 }, + {"ionice", 0, POPT_ARG_NONE, 0, OPT_IONICE, 0, 0 }, + {"no-nice", 0, POPT_ARG_NONE, 0, OPT_NO_NICE, 0, 0 }, + {"no-ionice", 0, POPT_ARG_NONE, 0, OPT_NO_IONICE, 0, 0 }, + {"nice-and-ionice", 'Q', POPT_ARG_NONE, 0, 'Q', 0, 0 }, {"server", 0, POPT_ARG_NONE, 0, OPT_SERVER, 0, 0 }, {"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 }, /* All the following options switch us into daemon-mode option-parsing. */ @@ -1598,6 +1617,33 @@ int parse_arguments(int *argc_p, const char ***argv_p) quiet++; break; + case 'Q': + nice_local = 1; + nice_remote = 1; + ionice_local = 1; + ionice_remote = 1; + break; + + case OPT_NICE: + nice_local = 1; + nice_remote = 1; + break; + + case OPT_IONICE: + ionice_local = 1; + ionice_remote = 1; + break; + + case OPT_NO_NICE: + nice_local = 0; + nice_remote = 0; + break; + + case OPT_NO_IONICE: + ionice_local = 0; + ionice_remote = 0; + break; + case 'x': one_file_system++; break; @@ -2996,6 +3042,12 @@ void server_options(char **args, int *argc_p) if (mkpath_dest_arg && am_sender) args[ac++] = "--mkpath"; + if (nice_remote) + args[ac++] = "--nice-local"; + + if (ionice_remote) + args[ac++] = "--ionice-local"; + if (ac > MAX_SERVER_ARGS) { /* Not possible... */ rprintf(FERROR, "argc overflow in server_options().\n"); exit_cleanup(RERR_MALLOC); From a0b5bb1dcd6dc4027acdd2f9c590fb4a78550e75 Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 21:29:39 +0200 Subject: [PATCH 08/11] rsync --help --- rsync.1.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rsync.1.md b/rsync.1.md index 2b4b75087..5bc5c7ec5 100644 --- a/rsync.1.md +++ b/rsync.1.md @@ -559,6 +559,13 @@ has its own detailed description later in this manpage. --checksum-seed=NUM set block/file checksum seed (advanced) --ipv4, -4 prefer IPv4 --ipv6, -6 prefer IPv6 +--nice-local renice local process to low priority +--nice-remote renice remote process to low priority +--ionice-local ionice local process to low priority +--ionice-remote ionice remote process to low priority +--nice, --ionice set local and remote process to low priority +--no-nice, ... prepending "no-" turns the given option off +--nice-and-ionice, -Q same as --nice --ionice --version, -V print the version + other info and exit --help, -h (*) show this help (* -h is help only on its own) ``` From 50252360da0c92d529dd5a64489a88006410d702 Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 21:40:33 +0200 Subject: [PATCH 09/11] rsync help for daemon process --- rsync.1.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rsync.1.md b/rsync.1.md index 5bc5c7ec5..115610b30 100644 --- a/rsync.1.md +++ b/rsync.1.md @@ -586,6 +586,9 @@ accepted: --log-file=FILE override the "log file" setting --log-file-format=FMT override the "log format" setting --sockopts=OPTIONS specify custom TCP options +--nice-local renice local daemon process to low priority +--ionice-local ionice local daemon process to low priority + They are given at client site as (io)nice-remote --verbose, -v increase verbosity --ipv4, -4 prefer IPv4 --ipv6, -6 prefer IPv6 From 8aa3c5016146329ae3ea9f4f35522928e558768d Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sat, 30 May 2026 21:49:41 +0200 Subject: [PATCH 10/11] Set renice or ionice locally --- main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/main.c b/main.c index c54fd79bc..6ccd9a0d7 100644 --- a/main.c +++ b/main.c @@ -107,6 +107,8 @@ extern char backup_dir_buf[MAXPATHLEN]; extern char *basis_dir[MAX_BASIS_DIRS+1]; extern struct file_list *first_flist; extern filter_rule_list daemon_filter_list, implied_filter_list; +extern int nice_local; +extern int ionice_local; uid_t our_uid; gid_t our_gid; @@ -1835,6 +1837,14 @@ int main(int argc,char *argv[]) if (write_batch < 0) dry_run = 1; + if (nice_local) { + renice_me(); + } + + if (ionice_local) { + ionice_me(); + } + if (am_server) { #ifdef ICONV_CONST setup_iconv(); From e621a6f7ef20b051204003ea4d34172a147d9088 Mon Sep 17 00:00:00 2001 From: Michael Mess Date: Sun, 31 May 2026 09:39:02 +0200 Subject: [PATCH 11/11] Added debug/warning messages for renice/ionice --- configure.ac | 2 ++ niceness.c | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index a4071f539..84e28dfb5 100644 --- a/configure.ac +++ b/configure.ac @@ -1465,6 +1465,8 @@ case "$CC" in ;; esac +AC_DEFINE_UNQUOTED([COMPILE_TARGET], ["$host"], [String describing the compiled target OS and architecture]) + AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig]) AC_OUTPUT diff --git a/niceness.c b/niceness.c index f1625f061..37bbb08b0 100644 --- a/niceness.c +++ b/niceness.c @@ -19,6 +19,8 @@ #include "rsync.h" +extern int am_server; + void renice_me() { #ifdef SUPPORT_RENICE @@ -27,8 +29,16 @@ void renice_me() int prio = 19; // lowest CPU Priority int result = setpriority(which, who, prio); if ( result < 0 ) { - // Failed to set priority, TODO: log or inform user, but can be ignored (it's just not so nice). + // Failed to set priority, inform user, but can be ignored (it's just not so nice). + rprintf(FWARNING, "renice rejected by OS (%s version %s)\n", + RSYNC_NAME, rsync_version()); + } else { + if (DEBUG_GTE(CMD, 1)) + rprintf(FINFO, "successfully reniced %s\n", am_server ? "server" : "client"); } +#else + rprintf(FWARNING, "renice not supported for %s (%s: %s version %s)\n", + COMPILE_TARGET, am_server ? "server" : "client", RSYNC_NAME, rsync_version()); #endif } @@ -42,7 +52,15 @@ void ionice_me() int ioprio = IOPRIO_PRIO_VALUE(class, data); int result = syscall(SYS_ioprio_set, which, who, ioprio); if ( result < 0 ) { - // Failed to set priority, TODO: log or inform user, but can be ignored (it's just not so ionice). + // Failed to set priority, inform user, but can be ignored (it's just not so ionice). + rprintf(FWARNING, "ionice rejected by OS (%s version %s)\n", + RSYNC_NAME, rsync_version()); + } else { + if (DEBUG_GTE(CMD, 1)) + rprintf(FINFO, "successfully ioniced %s\n", am_server ? "server" : "client"); } +#else + rprintf(FWARNING, "ionice not supported for %s (%s: %s version %s)\n", + COMPILE_TARGET, am_server ? "server" : "client", RSYNC_NAME, rsync_version()); #endif }