Subject: ata ioctl call (and atactl(8)) causes system hangs
To: None <current-users@NetBSD.org>
From: Efstathios Kamperis <ekamperi@auth.gr>
List: current-users
Date: 08/22/2007 18:08:08
This message is in MIME format.

--=_72wakrr65paw
Content-Type: text/plain;
	charset=ISO-8859-7;
	DelSp="Yes";
	format="flowed"
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hello netbsders of the Globe (and of the ISS ;))

I was studying the atactl(8) code and came up with a code snippet that =20
would read the model of my hard disk. The program works fine, but =20
sometimes,
_especially_ under heavy load, it causes my system to hang.

First it (my program) goes into the 'vinvalbu' state:
618 root      -5    0    88K 1016K vinvalbu   0:00  0.00%  0.00% a.out

Then syslogd occupies a significant amount of my CPU:
    144 root       2    0   192K  944K kqread     0:11 18.07% 18.07% syslogd

And my system message buffer fills in with:
buffer still DELWRI

I mean a _lot_ of them:
[stathis@netbsd ~]$ dmesg | grep DELWRI | wc -l
       819

Then my processes go into the vnlock state one after another. In the =20
meantime the system is still 'usable' depending on what processes have =20
locked. From that point on, it is only a matter of seconds, until all =20
processes have locked and I have to hard reset my pc.

As I've said before, this offending behaviour is exhibited only some =20
times, and under heavy load. To reproduce it, I run the following =20
script, and during it's execution, I start for example firefox.

#!/bin/sh
for i in `seq 1 1000`
do
     echo $i
     sudo ./a.out /dev/wd0a
done

I' ve noticed that running atactl /dev/wd0a identyfy in a tight loop =20
as above, also causes my system hang, but it does it instantaneously, =20
and I am unable to gather any further informationj (such as examine =20
the state of the process or the dmesg buffer).

I am running 4.99.29/i386, but I had the exact problems with =20
4.99.20/i386 as wel.

I attach you my code.

Best regards,
Stathis K


--=_72wakrr65paw
Content-Type: text/x-csrc;
	charset=UTF-8;
	name="readwd.c"
Content-Disposition: attachment;
	filename="readwd.c"
Content-Transfer-Encoding: quoted-printable

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dev/ata/atareg.h>
#include <sys/ataio.h>
#include <sys/ioctl.h>
#include <sys/param.h>

int main(int argc, char *argv[])
{
    int fd;
    unsigned int i;
    struct atareq req;
    union {
        unsigned char inbuf[DEV_BSIZE];
        struct ataparams inqbuf;
    } inbuf;
    u_int16_t *p;

    /* check argument count */
    if (argc !=3D 2) {
        fprintf(stderr, "usage: %s /dev/file\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* open device file descriptor */
    if ((fd =3D open(argv[1], O_RDONLY)) =3D=3D -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    /* construct an ata request */
    memset(&req, 0, sizeof req);
    req.flags =3D ATACMD_READ;
    req.command =3D WDCC_IDENTIFY;
    req.databuf =3D (caddr_t) &inbuf;
    req.datalen =3D sizeof inbuf;
    req.timeout =3D 1000;    /* 1 sec */

    /* make the ioctl call */
    if (ioctl(fd, ATAIOCCOMMAND, &req) =3D=3D -1) {
        perror("ioctl");
        close(fd);
        exit(EXIT_FAILURE);
    }

    /* close file descriptor */
    close(fd);

    return EXIT_SUCCESS;
}

--=_72wakrr65paw--