Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package mbuffer for openSUSE:Factory checked in at 2026-04-22 16:56:53 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mbuffer (Old) and /work/SRC/openSUSE:Factory/.mbuffer.new.11940 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mbuffer" Wed Apr 22 16:56:53 2026 rev:30 rq:1348540 version:20260301 Changes: -------- --- /work/SRC/openSUSE:Factory/mbuffer/mbuffer.changes 2026-01-19 18:42:38.881336631 +0100 +++ /work/SRC/openSUSE:Factory/.mbuffer.new.11940/mbuffer.changes 2026-04-22 16:57:00.557576867 +0200 @@ -1,0 +2,10 @@ +Mon Apr 20 21:26:10 UTC 2026 - Dirk Müller <[email protected]> + +- update to 20260301: + * drop speed limitations at the start and end of transfer + * fix input stalling unintential in -M/-R mode + * fix: do not close an already closed file + * added dynamic speed adjustment with low speed + * add support to bind network input to a specific interface + +------------------------------------------------------------------- Old: ---- mbuffer-20251025.tgz New: ---- mbuffer-20260301.tgz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mbuffer.spec ++++++ --- /var/tmp/diff_new_pack.15whSQ/_old 2026-04-22 16:57:01.553618094 +0200 +++ /var/tmp/diff_new_pack.15whSQ/_new 2026-04-22 16:57:01.557618259 +0200 @@ -18,7 +18,7 @@ Name: mbuffer -Version: 20251025 +Version: 20260301 Release: 0 Summary: Replacement for "buffer" with many more Features License: GPL-3.0-or-later ++++++ mbuffer-20251025.tgz -> mbuffer-20260301.tgz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mbuffer-20251025/.hg_archival.txt new/mbuffer-20260301/.hg_archival.txt --- old/mbuffer-20251025/.hg_archival.txt 2025-10-27 21:14:45.000000000 +0100 +++ new/mbuffer-20260301/.hg_archival.txt 2026-03-01 16:47:32.000000000 +0100 @@ -1,4 +1,4 @@ repo: 6e3b485d74645931e2408ed1f57e659029b5639a -node: d633a540b192a132bfe13faa3c5e861055ba5acf +node: 3f8b8febe218721e3fcd1097b64d2d4324b156f5 branch: default -tag: R20251025 +tag: R20260301 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mbuffer-20251025/.hgtags new/mbuffer-20260301/.hgtags --- old/mbuffer-20251025/.hgtags 2025-10-27 21:14:45.000000000 +0100 +++ new/mbuffer-20260301/.hgtags 2026-03-01 16:47:32.000000000 +0100 @@ -122,3 +122,5 @@ cbd7b2d41454936d4bd2dcc44eaa189fb066133e R20241007 220a607ab1f50fe5b42e04d86dff200bc680d575 R20250429 13ae9bf1e1df470cdfd51c6b2433dc531eff0c0d R20250809 +d633a540b192a132bfe13faa3c5e861055ba5acf R20251025 +a9a9bba352d3bcf98dcb513f5c17c4e1140a8776 R20260221 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mbuffer-20251025/ChangeLog new/mbuffer-20260301/ChangeLog --- old/mbuffer-20251025/ChangeLog 2025-10-27 21:14:45.000000000 +0100 +++ new/mbuffer-20260301/ChangeLog 2026-03-01 16:47:32.000000000 +0100 @@ -1,3 +1,12 @@ +20260301: +- drop speed limitations at the start and end of transfer +- fix input stalling unintential in -M/-R mode +- fix: do not close an already closed file + +20260221: +- added dynamic speed adjustment with low speed +- add support to bind network input to a specific interface + 20251025: - updated config.sub, config.guess, and instal-sh - added MacOS support (submitted by Grady McBride) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mbuffer-20251025/input.c new/mbuffer-20260301/input.c --- old/mbuffer-20251025/input.c 2025-10-27 21:14:45.000000000 +0100 +++ new/mbuffer-20260301/input.c 2026-03-01 16:47:32.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2024, Thomas Maier-Komor + * Copyright (C) 2000-2026, Thomas Maier-Komor * * This file is part of mbuffer's source code. * @@ -52,10 +52,10 @@ int err; fd_set readfds; - FD_ZERO(&readfds); - FD_SET(TermQ[0],&readfds); - FD_SET(In,&readfds); do { + FD_ZERO(&readfds); + FD_SET(TermQ[0],&readfds); + FD_SET(In,&readfds); err = select(maxfd,&readfds,0,0,0); debugiomsg("inputThread: select(%d, {%d,%d}, 0, 0, 0) = %d\n", maxfd,In,TermQ[0],err); assert((err > 0) || (errno == EBADF || errno == EINTR)); @@ -362,7 +362,7 @@ for (;;) { int err; - if (startread < 1) { + if ((startread < 1) && (MinSpeed == 0)) { err = pthread_mutex_lock(&LowMut); assert(err == 0); counter_getvalue(&FullBlocks,&fill); @@ -374,13 +374,14 @@ pthread_cleanup_pop(0); ++FullCount; debugmsg("inputThread: low watermark reached, continuing...\n"); + (void) clock_gettime(ClockSrc,&last); } err = pthread_mutex_unlock(&LowMut); assert(err == 0); } if (Terminate) { /* for async termination requests */ debugmsg("inputThread: terminating early upon request...\n"); - if (-1 == close(In)) + if ((-1 != In) && (-1 == close(In))) errormsg("error closing input: %s\n",strerror(errno)); if (Status) pthread_exit((void *)1); @@ -391,8 +392,24 @@ debugmsg("inputThread: no more blocks\n"); return 0; } - if (MaxReadSpeed) - xfer = enforceSpeedLimit(MaxReadSpeed,xfer,&last); + if ((0 != MaxReadSpeed) && (0 != Numout)) { + unsigned long long speedlimit = MaxReadSpeed; + if (MinSpeed != 0) { + counter_getvalue(&FullBlocks,&fill); + double frac = (double)fill/(double)Numblocks; + if (frac >= StartWrite) { + speedlimit = MinSpeed; + } else if (frac <= StartRead) { + speedlimit = MaxReadSpeed; + } else { + unsigned long long speeddiff = MaxReadSpeed-MinSpeed; + double quot = ((double)(frac-StartRead))/((double)(StartWrite-StartRead)); + speedlimit = MaxReadSpeed-speeddiff*quot; + } + debugmsg("frac %f, input speed limit %llu\n",frac,speedlimit); + } + xfer = enforceSpeedLimit(speedlimit,xfer,&last); + } counter_post(&FullBlocks); if (startwrite > 0) { err = pthread_mutex_lock(&HighMut); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mbuffer-20251025/mbuffer.1.in new/mbuffer-20260301/mbuffer.1.in --- old/mbuffer-20251025/mbuffer.1.in 2025-10-27 21:14:45.000000000 +0100 +++ new/mbuffer-20260301/mbuffer.1.in 2026-03-01 16:47:32.000000000 +0100 @@ -66,10 +66,11 @@ \fB\-\-truncate\fR Truncate next output file given via option \-o when opening it. .TP -\fB\-I\fR <\fIport\fP> +\fB\-I\fR <\fI[hostname:]port[@interface]\fP> Use network port \fIport\fP as input instead of the standard input. If given a hostname and a port in the form \fIhostname:port\fP, only the given -host is allowed to connect. +host is allowed to connect. If \fIinterface\fP is specified, connections are +only accepted on the specified interface. .TP \fB\-O\fR <\fIhostname:port\fP> Write output to \fIhostname:port\fP instead of the standard output (will @@ -106,6 +107,17 @@ \fB\-R\fR <\fIrate\fP> Same as above only for setting the transfer limit for the writer. .TP +\fB\-M\fR <\fIrate\fP> +Set minimum rate for dynamic transfer rate limitation. The data rate is +adjusted dynamically, between the high- and low-watermark values (-p and -P), +which must also be provided. + +When used in input mode, data rate starts with the -r rate and declines to the +-M rate based on the fill level of the buffer. + +When used in output mode, the data rate is adjusted similarly, but starting +with the minimum rate and increasing to the -R rate for the output. +.TP \fB\-f\fR Overwrite output file if it exists already. .TP @@ -283,6 +295,15 @@ \fImaster: \fPtar cf \- /tree_to_clone | mbuffer \-O clone0:8000 \-O clone1:8000 .LP \fIclones: \fPmbuffer \-I master:8000 | tar xf \- +.LP +.LP +Operating a drive tape with dynamic speed scaling: +.LP +tar cf - / | mbuffer -o /dev/tape -p20% -p80% -M 50M -R 120M +.LP +mbuffer -i /dev/tape -p20% -p80% -M 50M -r 120M | tar xf - +.LP +.LP .SH "EXITCODE" .LP mbuffer returns 0 upon success. Any kind of failure will yield a non-zero diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mbuffer-20251025/mbuffer.c new/mbuffer-20260301/mbuffer.c --- old/mbuffer-20251025/mbuffer.c 2025-10-27 21:14:45.000000000 +0100 +++ new/mbuffer-20260301/mbuffer.c 2026-03-01 16:47:32.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2025, Thomas Maier-Komor + * Copyright (C) 2000-2026, Thomas Maier-Komor * * This file is part of mbuffer's source code. * @@ -189,6 +189,7 @@ ErrorOccurred = 1; Terminate = 1; (void) close(In); + In = -1; if (TermQ[1] != -1) if (-1 == write(TermQ[1],"0",1)) {} if (StartWrite > 0) @@ -615,7 +616,8 @@ out = open(outfile,mode,0666); if (-1 == out) errormsg("error reopening output file: %s\n",strerror(errno)); - enable_directio(out,outfile); + else + enable_directio(out,outfile); } while (-1 == out); (void) clock_gettime(ClockSrc,&volstart); diff = volstart.tv_sec - now.tv_sec + (double) (volstart.tv_nsec - now.tv_nsec) * 1E-9; @@ -855,8 +857,24 @@ if (multipleSenders == 0) { counter_post(&FreeBlocks); } - if (MaxWriteSpeed) - xfer = enforceSpeedLimit(MaxWriteSpeed,xfer,&last); + if ((0 != MaxWriteSpeed) && (-1 == Finish)) { + unsigned long long speedlimit = MaxWriteSpeed; + if (MinSpeed) { + counter_getvalue(&FullBlocks,&fill); + double frac = (double)fill/(double)Numblocks; + if (frac <= StartRead) { + speedlimit = MinSpeed; + } else if (frac >= StartWrite) { + speedlimit = MaxWriteSpeed; + } else { + unsigned long long speeddiff = MaxWriteSpeed-MinSpeed; + double quot = ((double)(frac-StartRead))/((double)(StartWrite-StartRead)); + speedlimit = speeddiff*quot+MinSpeed; + } + debugmsg("frac %f, output speed limit %llu\n",frac,speedlimit); + } + xfer = enforceSpeedLimit(speedlimit,xfer,&last); + } if (Pause) (void) mt_usleep(Pause); if (Finish == at) { @@ -1233,10 +1251,23 @@ infomsg("adjusting total buffer memory to %s",hBytes(Totalmem)); } } + if ((MaxReadSpeed != 0) && (MaxWriteSpeed != 0)) + fatal("Set either maximum read or maximum write speed.\n"); + if (0 != MinSpeed) { + if ((0 == MaxReadSpeed) && (0 == MaxWriteSpeed)) + fatal("Minimum speed needs also a maximum speed. Please use -R or -r to set it.\n"); + if ((1 == StartRead) && (0 == StartWrite)) { // defaults not changed + StartRead = 0.2; + StartWrite = 0.8; + debugmsg("minspeed is set, but -P/-p is at its defaults. Updated to -p %3.2g%%, -P %3.2g%%\n", StartRead, StartWrite); + } + if (StartRead >= StartWrite) + fatal("High watermark must be higher than low watermark (-p %f < -P %f).\n",StartRead,StartWrite); + } if (Numblocks < 5) fatal("Number of blocks must be at least 5.\n"); - if ((StartRead < 1) && (StartWrite > 0)) - fatal("setting both low watermark and high watermark doesn't make any sense...\n"); + if ((StartRead < 1) && (StartWrite > 0) && (0 == MinSpeed)) + fatal("Low watermark and high watermark are either mutual exclusive or need minimum speed set as well (-M).\n"); if ((NumSenders-Hashers > 0) && (Autoloader || OutVolsize)) fatal("multi-volume support is unsupported with multiple outputs\n"); if (Autoloader) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mbuffer-20251025/network.c new/mbuffer-20260301/network.c --- old/mbuffer-20251025/network.c 2025-10-27 21:14:45.000000000 +0100 +++ new/mbuffer-20260301/network.c 2026-03-01 16:47:32.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2025, Thomas Maier-Komor + * Copyright (C) 2000-2026, Thomas Maier-Komor * * This file is part of mbuffer's source code. * @@ -50,8 +50,12 @@ #define IPPROTO_TCP 6 #endif +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 64 +#endif + -static void openNetworkInput(const char *host, const char *portstr); +static void openNetworkInput(const char *host, const char *portstr, const char *ifstr); int32_t TCPBufSize = 0; @@ -115,7 +119,7 @@ void initNetworkInput(const char *addr) { - char *host, *portstr; + char *host, *portstr, *ifstr; int l; debugmsg("initNetworkInput(\"%s\")\n",addr); @@ -126,6 +130,11 @@ l = strlen(addr) + 1; host = alloca(l); memcpy(host,addr,l); + ifstr = strrchr(host,'@'); + if (ifstr) { + *ifstr = 0; + ++ifstr; + } portstr = strrchr(host,':'); if (portstr == 0) { portstr = host; @@ -141,7 +150,7 @@ *portstr = 0; ++portstr; } - openNetworkInput(host,portstr); + openNetworkInput(host,portstr,ifstr); } static const char *addrinfo2str(const struct addrinfo *ai, char *buf, size_t s) @@ -167,20 +176,29 @@ } -static void openNetworkInput(const char *host, const char *portstr) +static void openNetworkInput(const char *host, const char *portstr, const char *ifstr) { struct hostent *h = 0, *r = 0; const int reuse_addr = 1; int sock; uint16_t port = getServicePort(portstr); - debugmsg("openNetworkInput(\"%s\",%hu)\n",host?host:"<null>",port); + debugmsg("openNetworkInput(\"%s\",%hu,\"%s\")\n",host?host:"<any>",port,ifstr?ifstr:"<any>"); int family = AddrFam == AF_UNSPEC ? AF_INET6 : AddrFam; sock = socket(family, SOCK_STREAM, IPPROTO_TCP); if (0 > sock) fatal("could not create socket for network input: %s\n",strerror(errno)); if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr))) warningmsg("cannot set socket to reuse address: %s\n",strerror(errno)); +#ifdef SO_BINDTODEVICE + if (ifstr) { + if (-1 == setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifstr, strlen(ifstr))) + errormsg("cannot bind network input to network interface '%s'\n",ifstr); + } +#else + if (ifstr) + errormsg("bind to network interface not supported on this system.\n"); +#endif #ifdef IPV6_V6ONLY if (AF_INET6 == AddrFam) { const int ipv6_only = 1; @@ -208,9 +226,9 @@ h = gethostbyname(host); if (0 == h) #ifdef HAVE_HSTRERROR - fatal("could not resolve server hostname: %s\n",hstrerror(h_errno)); + fatal("could not resolve server hostname '%s': %s\n",host,hstrerror(h_errno)); #else - fatal("could not resolve server hostname: error code %d\n",h_errno); + fatal("could not resolve server hostname '%s': error code %d\n",host,h_errno); #endif } @@ -234,7 +252,6 @@ debugmsg("listening on socket...\n"); if (0 > listen(sock,1)) /* accept only 1 incoming connection */ fatal("could not listen on socket for network input: %s\n",strerror(errno)); - char peer[128]; for (;;) { char addrbuf[sizeof(struct sockaddr_in6)]; socklen_t clen = sizeof(addrbuf); @@ -258,6 +275,7 @@ } else { abort(); } + char peer[128]; inet_ntop(af,caddr,peer,sizeof(peer)); if (h == 0) { expected = 1; // any host is ok @@ -265,7 +283,7 @@ debugmsg("checking connection from %s\n",peer); char **p; for (p = h->h_addr_list; *p; ++p) { - char addrstr[64]; + char addrstr[INET6_ADDRSTRLEN]; inet_ntop(h->h_addrtype,*p,addrstr,sizeof(addrstr)); debugmsg("checking against %s\n",addrstr); if (0 == memcmp(caddr,*p,h->h_length)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mbuffer-20251025/settings.c new/mbuffer-20260301/settings.c --- old/mbuffer-20251025/settings.c 2025-10-27 21:14:45.000000000 +0100 +++ new/mbuffer-20260301/settings.c 2026-03-01 16:47:32.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2025, Thomas Maier-Komor + * Copyright (C) 2000-2026, Thomas Maier-Komor * * This file is part of mbuffer's source code. * @@ -77,6 +77,7 @@ Blocksize = 10240, // fundamental I/O block size MaxReadSpeed = 0, MaxWriteSpeed = 0, + MinSpeed = 0, Totalmem = 0, OutVolsize = 0, Pause = 0; @@ -431,6 +432,9 @@ } else if (strcasecmp(key,"maxreadspeed") == 0) { MaxReadSpeed = value; debugmsg("MaxReadSpeed = %lu\n",MaxReadSpeed); + } else if (strcasecmp(key,"minspeed") == 0) { + MinSpeed = value; + debugmsg("MinSpeed = %lu\n",MinSpeed); } else if (strcasecmp(key,"Totalmem") == 0) { if (value >= 100) { Totalmem = value; @@ -572,7 +576,7 @@ { (void) fprintf(stderr, "mbuffer version " VERSION "\n"\ - "Copyright 2001-2025 - T. Maier-Komor\n"\ + "Copyright 2001-2026 - T. Maier-Komor\n"\ "License: GPLv3 - see file LICENSE\n"\ "This program comes with ABSOLUTELY NO WARRANTY!!!\n" "Donations via PayPal to [email protected] are welcome and support this work!\n" @@ -622,6 +626,7 @@ "-u <num> : pause <num> microseconds after each write\n" "-r <rate> : limit read rate to <rate> B/s, where <rate> can be given in b,k,M,G\n" "-R <rate> : same as -r for writing; use either one, if your tape is too fast\n" + "-M <rate> : set lowest data rate for automatic speed scaling\n" "-f : overwrite existing files\n" "-a <time> : device is autoloader which needs <time> seconds to reload\n" "-A <cmd> : issue command <cmd> to request new volume from autoloader\n" @@ -805,6 +810,9 @@ } else if (!argcheck("-R",argv,&c,argc)) { MaxWriteSpeed = calcint(argv,c,0); debugmsg("MaxWriteSpeed = %lld\n",MaxWriteSpeed); + } else if (!argcheck("-M",argv,&c,argc)) { + MinSpeed = calcint(argv,c,0); + debugmsg("MinSpeed = %lld\n",MinSpeed); } else if (!argcheck("-n",argv,&c,argc)) { long nv = strtol(argv[c],0,0); if ((nv < 0) || ((nv == 0) && (errno == EINVAL))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mbuffer-20251025/settings.h new/mbuffer-20260301/settings.h --- old/mbuffer-20251025/settings.h 2025-10-27 21:14:45.000000000 +0100 +++ new/mbuffer-20260301/settings.h 2026-03-01 16:47:32.000000000 +0100 @@ -62,6 +62,7 @@ Blocksize, /* fundamental I/O block size */ MaxReadSpeed, MaxWriteSpeed, + MinSpeed, Totalmem, Pause, OutVolsize;
