From owner-freebsd-stable@FreeBSD.ORG Sat Sep 6 10:38:10 2003 Return-Path: Delivered-To: freebsd-stable@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id EBC0316A4BF for ; Sat, 6 Sep 2003 10:38:10 -0700 (PDT) Received: from mail.dt.e-technik.uni-dortmund.de (mail.dt.e-technik.Uni-Dortmund.DE [129.217.163.1]) by mx1.FreeBSD.org (Postfix) with ESMTP id D28C943FE3 for ; Sat, 6 Sep 2003 10:38:09 -0700 (PDT) (envelope-from ma@dt.e-technik.uni-dortmund.de) Received: from m2a2.dyndns.org (krusty.dt.e-technik.uni-dortmund.de [129.217.163.1])6CD6FAD3F for ; Sat, 6 Sep 2003 19:38:08 +0200 (CEST) Received: by merlin.emma.line.org (Postfix, from userid 500) id 506279555E; Sat, 6 Sep 2003 19:38:04 +0200 (CEST) To: freebsd-stable@freebsd.org From: Matthias Andree Date: Sat, 06 Sep 2003 19:38:04 +0200 Message-ID: User-Agent: Gnus/5.1003 (Gnus v5.10.3) Emacs/21.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Subject: KERNEL BUG: lseek() broken on raw devices X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 06 Sep 2003 17:38:11 -0000 Hi, I just figured FreeBSD will happily write data (disk blocks) from byte #0 even after successful lseek(fd, 17, SEEK_SET) returned 17, at least on da(4) partitions such as rda0s1f. Tested on 4.9-PRERELEASE checked out early Sep 5th. I'd suggest that lseek to a non-sector boundary returns either (off_t)-1 and EINVAL (preferred) or at least returns the actual position (though few applications will handle that properly), or that write() returns -1 and EINVAL when writing to such a non-aligned location. Try this DESTRUCTIVE test on a scratch or spare partition that may lose all its data. Note that some devices are halfway fine; vn0c lets the seek succeed but returns EINVAL for the subsequent write, so make sure to try this on a da partition (comment out your swap partition, reboot, and use your freshly-deactivated swap partition if need be). NIT PICK: write(2) EINVAL means "The pointer associated with d was negative." (d is the file descriptor) Expected behaviour: either abort with "Invalid argument" on lseek bs/2 or on write or print "OK". #include #include #include #include #include #include #include void barf(const char *t) __attribute__((noreturn)); void barf(const char *t) { perror(t); exit(EXIT_FAILURE); } int main(int argc, char **argv) { int bs, fd = open(argc > 1 ? argv[1] : "/dev/rda0s1f", O_RDWR); int want = 0x66, t; struct disklabel dl; char *x; if (fd < 0) barf("open"); if (0 == ioctl(fd, DIOCGDINFO, &dl)) { printf("sector size: %lu\n", (unsigned long)(bs = dl.d_secsize)) ; } else barf("ioctl DIOCGDINFO"); /* this writes bs = blocksize times the byte 0x66 at offset #0 * then seeks to offset #bs/2 then writes bs times the byte 0x33. */ if (!(x = malloc(bs))) barf("malloc"); memset(x, want, bs); if (lseek(fd, 0, SEEK_SET) == (off_t)-1) barf("lseek 0"); if (write(fd, x, bs) < bs) barf("write"); memset(x, 0x33, bs); t = lseek(fd, bs >> 1, SEEK_SET); if (t == -1) barf("lseek bs/2"); printf("seeked to byte #%d\n", t); if (write(fd, x, bs) < bs) barf("write"); if (lseek(fd, 0, SEEK_SET) == (off_t)-1) barf("lseek 0"); if (read(fd, x, bs) < bs) barf("read"); if (x[0] == want) puts("OK"); else printf("KERNEL BUG: byte #0 is %x, should be %x\n", x[0], want); free(x); return 0; } -- Matthias Andree Encrypt your mail: my GnuPG key ID is 0x052E7D95