Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 27 Jun 1998 14:04:38 -0700 (PDT)
From:      Jason Evans <jasone@canonware.com>
To:        freebsd-hackers@FreeBSD.ORG
Subject:   Re: raw devices (min transfer size, detection)
Message-ID:  <Pine.BSF.3.96.980627124807.265E-100000@orkan.canonware.com>
In-Reply-To: <199806270645.XAA21564@usr08.primenet.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.980627124807.265E-100000>