[prev in list] [next in list] [prev in thread] [next in thread] 

List:       netbsd-tech-net
Subject:    ftp and ftpd should use a monotonic clock
From:       Roy Marples <roy () marples ! name>
Date:       2008-10-30 11:32:49
Message-ID: 49099B61.9040300 () marples ! name
[Download RAW message or body]

Hi List

ftp and ftpd both use gettimeofday to work out how long an action took.
If the system time changes this the time deltas reported will be wrong.
References for this happening are here [1].

Attached are patches to ftp and ftpd which change the relevant parts 
from timeval + gettimeofday to timespec + clock_gettime using a 
MONOTONIC clock so that deltas are more accurately reported.

Please consider applying :)

Thanks

Roy

[1] http://mail-index.netbsd.org/current-users/2008/07/17/msg003559.html

["ftp-monotonic.diff" (text/plain)]

? .gdbinit
? .progressbar.c.swp
? ftp
? ftp.cat1
Index: progressbar.c
===================================================================
RCS file: /cvsroot/src/usr.bin/ftp/progressbar.c,v
retrieving revision 1.20
diff -u -p -r1.20 progressbar.c
--- progressbar.c	30 Sep 2008 03:41:53 -0000	1.20
+++ progressbar.c	30 Oct 2008 10:51:03 -0000
@@ -112,8 +112,8 @@ static const char * const suffixes[] = {
  *   with flag = 0
  * - After the transfer, call with flag = 1
  */
-static struct timeval start;
-static struct timeval lastupdate;
+static struct timespec start;
+static struct timespec lastupdate;
 
 #define	BUFLEFT	(sizeof(buf) - len)
 
@@ -122,9 +122,9 @@ progressmeter(int flag)
 {
 	static off_t lastsize;
 	off_t cursize;
-	struct timeval now, wait;
+	struct timespec now, wait;
 #ifndef NO_PROGRESS
-	struct timeval td;
+	struct timespec td;
 	off_t abbrevsize, bytespersec;
 	double elapsed;
 	int ratio, i, remaining, barlength;
@@ -154,14 +154,14 @@ progressmeter(int flag)
 #endif
 
 	if (flag == -1) {
-		(void)gettimeofday(&start, NULL);
+		(void)clock_gettime(CLOCK_MONOTONIC, &start);
 		lastupdate = start;
 		lastsize = restart_point;
 	}
 
-	(void)gettimeofday(&now, NULL);
+	(void)clock_gettime(CLOCK_MONOTONIC, &now);
 	cursize = bytes + restart_point;
-	timersub(&now, &lastupdate, &wait);
+	timespecsub(&now, &lastupdate, &wait);
 	if (cursize > lastsize) {
 		lastupdate = now;
 		lastsize = cursize;
@@ -238,8 +238,8 @@ progressmeter(int flag)
 	    (LLT)abbrevsize,
 	    suffixes[i]);
 
-	timersub(&now, &start, &td);
-	elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
+	timespecsub(&now, &start, &td);
+	elapsed = td.tv_sec + (td.tv_nsec / 1000000000.0);
 
 	bytespersec = 0;
 	if (bytes > 0) {
@@ -300,7 +300,7 @@ progressmeter(int flag)
 void
 ptransfer(int siginfo)
 {
-	struct timeval now, td, wait;
+	struct timespec now, td, wait;
 	double elapsed;
 	off_t bytespersec;
 	int remaining, hh, i;
@@ -311,9 +311,9 @@ ptransfer(int siginfo)
 	if (!verbose && !progress && !siginfo)
 		return;
 
-	(void)gettimeofday(&now, NULL);
-	timersub(&now, &start, &td);
-	elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
+	(void)clock_gettime(CLOCK_MONOTONIC, &now);
+	timespecsub(&now, &start, &td);
+	elapsed = td.tv_sec + (td.tv_nsec / 1000000000.0);
 	bytespersec = 0;
 	if (bytes > 0) {
 		bytespersec = bytes;
@@ -359,7 +359,7 @@ ptransfer(int siginfo)
 			len += snprintf(buf + len, BUFLEFT, "%2d:", hh);
 		len += snprintf(buf + len, BUFLEFT, "%02d:%02d",
 		    remaining / 60, remaining % 60);
-		timersub(&now, &lastupdate, &wait);
+		timespecsub(&now, &lastupdate, &wait);
 		if (wait.tv_sec >= STALLTIME)
 			len += snprintf(buf + len, BUFLEFT, "  (stalled)");
 	}

["ftpd-monotonic.diff" (text/plain)]

? ftpcmd.c
? ftpd.cat8
? ftpd.conf.cat5
? ftpusers.cat5
Index: extern.h
===================================================================
RCS file: /cvsroot/src/libexec/ftpd/extern.h,v
retrieving revision 1.58
diff -u -p -r1.58 extern.h
--- extern.h	13 Sep 2008 03:30:35 -0000	1.58
+++ extern.h	30 Oct 2008 11:20:22 -0000
@@ -135,7 +135,7 @@ FILE   *ftpd_popen(char *[], const char 
 int	getline(char *, int, FILE *);
 void	init_curclass(void);
 void	logxfer(const char *, off_t, const char *, const char *,
-	    const struct timeval *, const char *);
+	    const struct timespec *, const char *);
 struct tab *lookup(struct tab *, const char *);
 void	makedir(const char *);
 void	mlsd(const char *);
Index: ftpd.c
===================================================================
RCS file: /cvsroot/src/libexec/ftpd/ftpd.c,v
retrieving revision 1.188
diff -u -p -r1.188 ftpd.c
--- ftpd.c	16 Sep 2008 12:30:38 -0000	1.188
+++ ftpd.c	30 Oct 2008 11:20:23 -0000
@@ -1682,7 +1682,7 @@ retrieve(char *argv[], const char *name)
 	struct stat st;
 	int (*closefunc)(FILE *) = NULL;
 	int dolog, sendrv, closerv, stderrfd, isconversion, isdata, isls;
-	struct timeval start, finish, td, *tdp;
+	struct timespec start, finish, td, *tdp;
 	struct rusage rusage_before, rusage_after;
 	const char *dispname;
 	char *error;
@@ -1765,12 +1765,12 @@ retrieve(char *argv[], const char *name)
 		goto done;
 
 	(void)getrusage(RUSAGE_SELF, &rusage_before);
-	(void)gettimeofday(&start, NULL);
+	(void)clock_gettime(CLOCK_MONOTONIC, &start);
 	sendrv = send_data(fin, dout, &st, isdata);
-	(void)gettimeofday(&finish, NULL);
+	(void)clock_gettime(CLOCK_MONOTONIC, &finish);
 	(void)getrusage(RUSAGE_SELF, &rusage_after);
 	closedataconn(dout);		/* close now to affect timing stats */
-	timersub(&finish, &start, &td);
+	timespecsub(&finish, &start, &td);
 	tdp = &td;
  done:
 	if (dolog) {
@@ -1823,7 +1823,7 @@ store(const char *name, const char *fmod
 	FILE *fout, *din;
 	struct stat st;
 	int (*closefunc)(FILE *);
-	struct timeval start, finish, td, *tdp;
+	struct timespec start, finish, td, *tdp;
 	char *desc, *error;
 
 	din = NULL;
@@ -1880,7 +1880,7 @@ store(const char *name, const char *fmod
 	din = dataconn(name, (off_t)-1, "r");
 	if (din == NULL)
 		goto done;
-	(void)gettimeofday(&start, NULL);
+	(void)clock_gettime(CLOCK_MONOTONIC, &start);
 	if (receive_data(din, fout) == 0) {
 		if (unique)
 			reply(226, "Transfer complete (unique file name:%s).",
@@ -1888,9 +1888,9 @@ store(const char *name, const char *fmod
 		else
 			reply(226, "Transfer complete.");
 	}
-	(void)gettimeofday(&finish, NULL);
+	(void)clock_gettime(CLOCK_MONOTONIC, &finish);
 	closedataconn(din);		/* close now to affect timing stats */
-	timersub(&finish, &start, &td);
+	timespecsub(&finish, &start, &td);
 	tdp = &td;
  done:
 	logxfer(desc, byte_count, name, NULL, tdp, error);
@@ -3544,7 +3544,7 @@ conffilename(const char *s)
  */
 void
 logxfer(const char *command, off_t bytes, const char *file1, const char *file2,
-    const struct timeval *elapsed, const char *error)
+    const struct timespec *elapsed, const char *error)
 {
 	char		 buf[MAXPATHLEN * 2 + 100];
 	char		 realfile1[MAXPATHLEN], realfile2[MAXPATHLEN];
@@ -3576,8 +3576,8 @@ logxfer(const char *command, off_t bytes
 			    " %s", r2);
 		if (elapsed != NULL)
 			len += snprintf(buf + len, sizeof(buf) - len,
-			    " in %ld.%.03d seconds", elapsed->tv_sec,
-			    (int)(elapsed->tv_usec / 1000));
+			    " in %ld.%.03d seconds", (long int)elapsed->tv_sec,
+			    (int)(elapsed->tv_nsec / 1000000));
 		if (error != NULL)
 			len += snprintf(buf + len, sizeof(buf) - len,
 			    ": %s", error);
@@ -3607,7 +3607,7 @@ logxfer(const char *command, off_t bytes
  *	given that syslog messages don't contain the full date.
  */
 	    ctime(&now),
-	    elapsed == NULL ? 0 : elapsed->tv_sec + (elapsed->tv_usec > 0),
+	    elapsed == NULL ? 0 : (long int)elapsed->tv_sec + (elapsed->tv_nsec > 0),
 	    remotehost,
 	    (LLT) bytes,
 	    r1,


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic