From owner-freebsd-hackers Wed Aug 29 11:27:30 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from wall.polstra.com (rtrwan160.accessone.com [206.213.115.74]) by hub.freebsd.org (Postfix) with ESMTP id 293DF37B405 for ; Wed, 29 Aug 2001 11:27:21 -0700 (PDT) (envelope-from jdp@polstra.com) Received: from vashon.polstra.com (vashon.polstra.com [206.213.73.13]) by wall.polstra.com (8.11.3/8.11.3) with ESMTP id f7TIRKX85042 for ; Wed, 29 Aug 2001 11:27:20 -0700 (PDT) (envelope-from jdp@polstra.com) Message-ID: X-Mailer: XFMail 1.3 [p0] on FreeBSD X-Priority: 3 (Normal) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="_=XFMail.1.3.p0.FreeBSD:010829112720:295=_" Date: Wed, 29 Aug 2001 11:27:20 -0700 (PDT) Organization: Polstra & Co., Inc. From: John Polstra To: hackers@freebsd.org Subject: PLEASE REVIEW: loader fix for gzipped kernels Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG This message is in MIME format --_=XFMail.1.3.p0.FreeBSD:010829112720:295=_ Content-Type: text/plain; charset=us-ascii I would appreciate another pair of eyes on the attached patch before I commit it. I have been working with gzipped kernels a lot lately, and have noticed that when the loader tries to load certain kernels, it fails with the message "elf_loadexec: cannot seek". I tracked this down to a bug in "src/lib/libstand/lseek.c", which is fixed by this patch. Here is the bug that it fixed. Libstand maintains a read-ahead buffer for each open file, so that it can read in chunks of 512 bytes for greater efficiency. When the loader tries to lseek forward in a file by a small amount, it sometimes happens that the target file offset is already in the read-ahead buffer. But the existing code in lseek.c simply discards the contents of that buffer and does a seek directly on the underlying file. This results in an attempt to seek backwards in the file, since some of the data has already been read into the read-ahead buffer. Gzipped data streams cannot seek backwards, so an error is returned. The code added by the patch checks to see if the desired file offset is already in the read-ahead buffer. If it is, the code simply adjusts the buffer pointer and length, thereby avoiding a reverse seek on the gzipped data stream. The bug is present in both -current and -stable. This patch is relative to -stable, but it applies cleanly to -current too. John -- John Polstra jdp@polstra.com John D. Polstra & Co., Inc. Seattle, Washington USA "Disappointment is a good sign of basic intelligence." -- Chögyam Trungpa --_=XFMail.1.3.p0.FreeBSD:010829112720:295=_ Content-Disposition: attachment; filename="libstand.patch" Content-Type: text/plain; charset=us-ascii; name=libstand.patch; SizeOnDisk=1410 Content-Transfer-Encoding: 7bit Index: lseek.c =================================================================== RCS file: /home/ncvs/src/lib/libstand/lseek.c,v retrieving revision 1.1.1.1.6.1 diff -u -r1.1.1.1.6.1 lseek.c --- lseek.c 2000/09/10 01:32:06 1.1.1.1.6.1 +++ lseek.c 2001/08/29 17:45:21 @@ -70,6 +70,8 @@ off_t lseek(int fd, off_t offset, int where) { + struct stat sb; + off_t bufpos, filepos, target; struct open_file *f = &files[fd]; if ((unsigned)fd >= SOPEN_MAX || f->f_flags == 0) { @@ -94,6 +96,39 @@ return (-1); } return (f->f_offset); + } + + /* + * If there is some unconsumed data in the readahead buffer and it + * contains the desired offset, simply adjust the buffer pointers. + */ + if (f->f_ralen != 0) { + if ((filepos = (f->f_ops->fo_seek)(f, (off_t)0, SEEK_CUR)) == -1) + return (-1); + bufpos = filepos - f->f_ralen; + switch (where) { + case SEEK_SET: + target = offset; + break; + case SEEK_CUR: + target = bufpos + offset; + break; + case SEEK_END: + if ((f->f_ops->fo_stat)(f, &sb) == -1 || sb.st_size == -1) { + errno = EOFFSET; + return (-1); + } + target = sb.st_size + offset; + break; + default: + errno = EINVAL; + return (-1); + } + if (bufpos <= target && target < filepos) { + f->f_raoffset += target - bufpos; + f->f_ralen -= target - bufpos; + return (target); + } } /* --_=XFMail.1.3.p0.FreeBSD:010829112720:295=_-- End of MIME message To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message