Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jan 2001 15:03:42 +0100 (CET)
From:      Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/24223: "tail -f file" is a CPU hog when file is on an NFS volume
Message-ID:  <200101101403.f0AE3gc13210@curry.mchp.siemens.de>

next in thread | raw e-mail | index | archive | help

>Number:         24223
>Category:       kern
>Synopsis:       "tail -f file" is a CPU hog when file is on an NFS volume
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jan 10 06:10:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Andre Albsmeier
>Release:        FreeBSD 4.2-STABLE i386
>Organization:
>Environment:

FreeBSD 4.2-STABLE with a nfs mounted volume from another FreeBSD 4.2-STABLE
server.

>Description:

If "tail -f file" is executed for a file which resides on an NFS mounted
volume it consumes all CPU time.

>How-To-Repeat:

mount some-server:/filesystem /mnt
cat blah > /mnt/file
tail -f /mnt/file

run top in another window

>Fix:

unknown. tail spins around in the code segment below (forward.c).
The switch statement is called repeatedly with action == USE_KQUEUE.


	for (;;) {
		while ((ch = getc(fp)) != EOF)
			if (putchar(ch) == EOF)
				oerr();
		if (ferror(fp)) {
			ierr();
			return;
		}
		(void)fflush(stdout);
		if (! fflag)
			break;
		clearerr(fp);

		switch (action) {
		case ADD_EVENTS: {
			int n = 0;
			struct timespec ts = { 0, 0 };

			if (Fflag && fileno(fp) != STDIN_FILENO) {
				ev[n].ident = fileno(fp);
				ev[n].filter = EVFILT_VNODE;
				ev[n].flags = EV_ADD | EV_ENABLE | EV_CLEAR;
				ev[n].fflags = NOTE_DELETE | NOTE_RENAME;
				n++;
			}
			ev[n].ident = fileno(fp);
			ev[n].filter = EVFILT_READ;
			ev[n].flags = EV_ADD | EV_ENABLE;
			n++;

			if (kevent(kq, ev, n, NULL, 0, &ts) < 0) {
				close(kq);
				kq = -1;
				action = USE_SLEEP;
			} else {
				action = USE_KQUEUE;
			}
			break;
		}

		case USE_KQUEUE:
			if (kevent(kq, NULL, 0, ev, 1, NULL) < 0)
				err(1, "kevent");

			if (ev->filter == EVFILT_VNODE) {
				/* file was rotated, wait until it reappears */
				action = USE_SLEEP;
			} else if (ev->data < 0) {
				/* file shrank, reposition to end */
				if (fseek(fp, 0L, SEEK_END) == -1) {
					ierr();
					return;
				}
			}
			break;

		case USE_SLEEP:
                	(void) usleep(250000);
	                clearerr(fp);

			if (Fflag && fileno(fp) != STDIN_FILENO &&
			    stat(fname, &sb2) != -1) {
				if (sb2.st_ino != sbp->st_ino ||
				    sb2.st_dev != sbp->st_dev ||
				    sb2.st_rdev != sbp->st_rdev ||
				    sb2.st_nlink == 0) {
					fp = freopen(fname, "r", fp);
					if (fp == NULL) {
						ierr();
						break;
					}
					*sbp = sb2;
					if (kq != -1)
						action = ADD_EVENTS;
				}
			}
			break;
		}
	}
}

/*
 * rlines -- display the last offset lines of the file.
 */
static void
rlines(fp, off, sbp)
	FILE *fp;
	long off;
	struct stat *sbp;
{
	register off_t size;
	register char *p;
	char *start;

	if (!(size = sbp->st_size))
		return;

	if (size > SIZE_T_MAX) {
		errno = EFBIG;
		ierr();
		return;
	}

	if ((start = mmap(NULL, (size_t)size,
	    PROT_READ, MAP_SHARED, fileno(fp), (off_t)0)) == MAP_FAILED) {
		ierr();
		return;
	}

	/* Last char is special, ignore whether newline or not. */
	for (p = start + size - 1; --size;)
		if (*--p == '\n' && !--off) {
			++p;
			break;
		}

	/* Set the file pointer to reflect the length displayed. */
	size = sbp->st_size - size;
	WR(p, size);
	if (fseek(fp, (long)sbp->st_size, SEEK_SET) == -1) {
		ierr();
		return;
	}
	if (munmap(start, (size_t)sbp->st_size)) {
		ierr();
		return;
	}
}

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200101101403.f0AE3gc13210>