Re: SG_BIG_BUFF woes on Linux

Gerald Turner (gturner@retina.net)
Mon, 25 Jan 1999 11:05:47 -0800 (PST)

On Mon, 25 Jan 1999, Petter Reinholdtsen wrote:

> [Gerald Turner]
> > Hmm, I thought I read somewhere in the kernel source that reading
> > /proc would be better, maybe having something to do with sysctl
> > interface/values changing. However, I went looking for this and
> > can't seem to find it.
>
> man sysctl(2) informs that this is a non-portable way to extract this
> value.

Yes that's right, the man page! Especially the bit under BUGS: "The
object names vary between kernel versions. THIS MAKES THIS SYSTEM CALL
WORTHLESS FOR APPLICATIONS. Use the /proc/sys interface instead."

> > Excuse me, the suggestion was by mistake. Use sysctl(). I just had a
> > look through <confname.h>, sysconf() doesn't support anything beyond
> > the POSIX definitions, no SG_BIG_BUFF.
>
> OK. I beleave it should be extractable for sysconf(), but until that
> happends, we will just have to make without it.

Hmm, the use of SG_BIG_BUFF in sane is Linux-specific, as far as
portabliity is concerned, this value is not used on other OS's.
sanei_scsi.c redefines the low-level sane scsi functions for each OS's
scsi implementation. It looks like we should use /proc/sys, not use
sysctl or sysconf at all, and resort to the hard sg.h in case 1) the
kernel version doesnt do /proc/sys/kernel/sg-big-buff, or 2) the /proc is
not compiled/mounted/loaded.

> > Anyway is this doable? I can't be the only one using a distribution
> > and modifying SG_BIG_BUFF (I do it to also improve cdda audio
> > ripping performance)...
>
> I beleave it is the correct way. If the function returning the value
> is written to try lots of ways to extract this value, the result
> should be quite portable. Example:

This function would indeed be nice, but the value is only used once to
create this structure:

static struct req
{
int fd;
u_int running:1, done:1;
SANE_Status status;
size_t *dst_len;
void *dst;
struct
{
struct sg_header hdr;
u_int8_t data[SG_BIG_BUFF];
}
cdb;
struct req *next;
}

My difficulty here is that with my limited C experience, I can't think of
a good way to change the data element to be dynamic.

> /*
> * return max size of file buffers(?), or -1 if not able to find the
> * current value.
> */
> int
> get_sg_big_buff_value(void)
> {
> int value = -1;
> FILE *procfile = NULL;
>
> procfile = fopen("/proc/sys/kernel/sg-big-buff", "r");
> if (NULL != procfile)
> {
> fscanf(procfile, "%d", &value);
> fclose(procfile);
> return value;
> }
>
> #if defined(HAVE_LINUX_SYSCTL_H) && defined(HAVE_SYSCTL)
> {
> int name[] = { CTL_KERN, KERN_SG_BIG_BUFF };
> int namesize = sizeof(name)/sizeof(name[0]);
> if (0 == sysctl(name, namesize, &value, sizeof(value), 0, 0))
> return value;
> }
> #endif
>
> /* ... More ways to find it ... */
>
> return value;
> }
>
> This code is not tested. I'm not even sure if it compiles. You have
> been warned. :-)

The code prior to the first return works good, I have even tested this on
my own before writing to the sane-devel list. But as for the sysctl(),
the argument sizeof(value), needs to be an address that sysctl can write
the size of the old value (&valuesize)).


> BTW: '/proc/sys/kernel/sg-big-buff' is missing on Linux 2.0.32, but
> present on 2.2.0-pre5.

Been present at least since 2.1.1XX here...

I figured this would be a problem, AFAIK the only good way would be to
fall back on the #define'd SG_BIG_BUFF if the fopen() fails.

Before jumping on this list, I was looking through the source of
cdparanoia, there they define a function quite like yours above only it is
very linux specific (non-portable) and reads a couple of sectors off the
cdrom to calculate how big the buffer is (doesn't use /proc, sysctl, or
SG_BIG_BUFF at all!). I don't think reading some data from the scanner
would be good in this case though.

Gerald Turner
http://www.retina.net/~gturner/

--
Source code, list archive, and docs: http://www.mostang.com/sane/
To unsubscribe: echo unsubscribe sane-devel | mail majordomo@mostang.com