From owner-freebsd-hackers Sat Jun 27 14:02:58 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id OAA29229 for freebsd-hackers-outgoing; Sat, 27 Jun 1998 14:02:58 -0700 (PDT) (envelope-from owner-freebsd-hackers@FreeBSD.ORG) Received: from orkan.canonware.com (canonware.com [206.184.206.112]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id OAA29223 for ; Sat, 27 Jun 1998 14:02:54 -0700 (PDT) (envelope-from jasone@canonware.com) Received: from localhost (jasone@localhost) by orkan.canonware.com (8.8.8/8.8.7) with SMTP id OAA22654 for ; Sat, 27 Jun 1998 14:04:38 -0700 (PDT) (envelope-from jasone@canonware.com) Date: Sat, 27 Jun 1998 14:04:38 -0700 (PDT) From: Jason Evans Reply-To: Jason Evans To: freebsd-hackers@FreeBSD.ORG Subject: Re: raw devices (min transfer size, detection) In-Reply-To: <199806270645.XAA21564@usr08.primenet.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG A number of people gave me useful suggestions on how to solve the problems I had, so here's a summary of what I found out along the way. Thanks everyone for your help. > 1) I need to know the minimum transfer size for the underlying device so > that I can intelligently write only the physical blocks that need > written, rather than an entire "logical" block as my code sees the > data. I've looked through physio() and friends, and it appears that > this information is deriveable from the buf struct that is passed in to > physio(). The problem is that this is all done behind the scenes. Can > I directly get at this info? It turns out that the st_blksize field of the stat structure is bogus (why, I don't know). The following code told me that the optimal transfer size is 64kB blocks. Yeah, whatever. =) { struct stat sb; if (-1 == fstat(fd, &sb)) { fprintf(stderr, "fstat() error: %s\n", strerror(errno)); } else { printf("optimal block size: %lu\n", sb.st_blksize); } } So, Julian Elischer suggested reading the disklabel via an ioctl(). That made sense to me, but the documentation on how to do so is apparently nonexistant. After reading system headers and the disklabel(8) source code, I found the appropriate ioctl(). { struct disklabel dlp; a_brbs_o->sect_size = 0; /* In case we don't manage to get the sector * size. */ if (ioctl(a_brbs_o->fd, DIOCGDINFO, &dlp) < 0) { fprintf(stderr, "ioctl() error: %s\n", strerror(errno)); /* Try to find the sector size the gross way. */ { #define _CW_BUF_POWER 13 cw_uint8_t buf[1 << _CW_BUF_POWER]; int i; for (i = 1; (i <= _CW_BUF_POWER); i++) #undef _CW_BUF_POWER { if (read(a_brbs_o->fd, &buf, 1 << (i - 1)) >= 0) { a_brbs_o->sect_size = 1 << (i - 1); break; } } } else { a_brbs_o->sect_size = dlp.d_secsize; } } } > 2) How can I programmatically (in C) know that a file is a device, and > more specifically a raw device? I've browsed a large number of > manpages, but I still haven't found the answer. I'll eventually find > it, but perhaps someone can point me in the right direction? =) This is the best I've been able to do in figuring out whether a file is a raw device. This isn't totally satisfactory though, since I think this test would show a tty (for example) as a raw device as well. Once again, I had to read system headers, because the S_ISCHR() macro wasn't mentioned in the stat manpage. Terry Lambert came the closest to pointing me directly at this one. void brbs_p_get_is_raw(cw_brbs_t * a_brbs_o) { struct stat sb; if (-1 == fstat(a_brbs_o->fd, &sb)) { fprintf(stderr, "fstat() error: %s\n", strerror(errno)); } else { if (S_ISCHR(sb.st_mode)) { a_brbs_o->is_raw = TRUE; /* Figure out how big the device is. */ a_brbs_o->max_size = lseek(a_brbs_o->fd, 0, SEEK_END); _cw_assert(a_brbs_o->max_size != -1); } else { a_brbs_o->is_raw = FALSE; } } } Jason Jason Evans Email: [jasone@canonware.com] Web: [http://www.canonware.com/~jasone] Home phone: [(650) 856-8204] Work phone: [(408) 774-8007] Quote: ["Invention is 1% inspiration and 99% perspiration" - Thomas Edison] To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message