We have encountered some kind of sg regression with kernel 2.6.16-rc5
relative to 2.6.15. We have a small program that demonstrates the
failure. On 2.6.15 it produces the output:
Alloced dataptr 0 -> 0xb7d07008
IOS: 0
ios 100
indicating that it did 100 operations successfully. On 2.6.16-rc5, it
produces the output:
Alloced dataptr 0 -> 0xa7d10008
SG_IO ioctl error 12 Cannot allocate memory
ios 0
indicating that it did 0 operations successfully. This program is
attempting to do 1MB reads on a SCSI device. We get the failure both
on an aic79xx parallel SCSI and on aic94xx SAS. With both types of
devices, it works fine on the 2.6.15 kernel. We have also seen this
problem on the 2.6.16-rc4 kernel. In all cases we were running on an
Intel Xeon-based system.
Below is the source for the program that was used to demonstrate this
problem:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <error.h>
#include <errno.h>
#include <string.h>
#include <scsi/sg.h>
#include <scsi/scsi.h>
#include <sys/ioctl.h>
#include <sys/epoll.h>
#include <ctype.h>
void dispsns(unsigned char cdb0, unsigned char *sense_buffer, int len)
{
int i;
unsigned int *dwptr;
printf("sense: cdb0 : %02hhX",cdb0);
dwptr = (unsigned int *) &sense_buffer;
for (i = 0; i < len ; i++) {
if (!(i % 16)) {
printf("\n%02hhX", sense_buffer[i]);
continue;
}
if (!(i % 4))
printf(" ");
printf("%02hhX", sense_buffer[i]);
}
printf(" KEY: %02hhX ", sense_buffer[2] & 0x0f);
printf("ASC: %02hhX ", sense_buffer[12]);
printf("ASCQ: %02hhX\n", sense_buffer[13]);
}
/*
sends the given io to the sg layer if there is only 1 SGL
element first IO
will be attmpeted. Otherwise the SGL is sent
*/
int do_scsi_io(int sg_fd, unsigned char *cdb,int cdblen, sg_iovec_t
*iovec,
int dir, int datalen,int sglcount)
{
unsigned char sense_buffer[32];
sg_io_hdr_t io_hdr;
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = cdblen;
io_hdr.mx_sb_len = 32;
io_hdr.dxfer_direction = dir;
io_hdr.dxfer_len = datalen;
if (sglcount > 1) {
io_hdr.dxferp = iovec;
io_hdr.iovec_count = sglcount;
} else {
io_hdr.flags |= SG_FLAG_DIRECT_IO;
io_hdr.dxferp = iovec[0].iov_base;
io_hdr.iovec_count = 0;
}
io_hdr.cmdp = cdb;
io_hdr.sbp = sense_buffer;
io_hdr.timeout = 10000; /* 10000 millisecs == 10 seconds */
memset(&sense_buffer, 0, 32);
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
printf("SG_IO ioctl error %d %s\n", errno, strerror(errno));
return -1;
}
if ((io_hdr.info & SG_INFO_OK_MASK) == SG_INFO_OK) {
return datalen - io_hdr.resid;
} else {
dispsns(cdb[0], sense_buffer, io_hdr.sb_len_wr);
return -1;
}
}
unsigned int IOLEN = 0x100000;
unsigned int SGLCOUNT = 1;
unsigned int LOOPCOUNT = 100;
int main(int argc, char *argv[])
{
char devpath[80];
int i;
int handle;
int ret;
unsigned char readCmdBlk[10] = {0x28, 0, 0, 0, 0x00, 0, 0, 0 ,0,
0};
unsigned int blkcount;
sg_iovec_t iovectable[SGLCOUNT];
void *dataptr[SGLCOUNT];
void *dataptr2[SGLCOUNT];
if (argc < 2) {
printf("Error: no input parms\n");
printf(" Usage: iotest /dev/sg<n>\n");
return -1;
}
for (i = 0; i < SGLCOUNT; i++) {
dataptr[i] = malloc((IOLEN/SGLCOUNT) + 0x2000);
dataptr2[i] = dataptr[i];
printf("Alloced dataptr %d -> %p \n", i, dataptr[i]);
}
for (i = 0; i < SGLCOUNT; i++)
if (dataptr[i] == NULL) {
printf("Unable to alloc memory \n");
return -1;
}
for (i = 0; i < SGLCOUNT; i++) {
iovectable[i].iov_base = dataptr2[i];
iovectable[i].iov_len = IOLEN/SGLCOUNT;
}
strcpy(devpath, argv[1]);
handle = open(devpath, O_RDWR);
if (handle == -1) {
printf(" Open of %s failed \n",devpath);
for (i = 0; i < SGLCOUNT; i++)
free(dataptr[i]);
return -1;
}
blkcount = IOLEN /0x200;
readCmdBlk[2] = 0; /*lba*/
readCmdBlk[3] = 0; /*lba*/
readCmdBlk[4] = 0; /*lba*/
readCmdBlk[5] = 0; /*lba*/
readCmdBlk[7] = (blkcount & 0xff00) >> 8; /*len*/
readCmdBlk[8] = blkcount & 0xff; /*len*/
for (i = 0; i < LOOPCOUNT; i++) {
ret = do_scsi_io(handle, readCmdBlk, 10, iovectable,
SG_DXFER_FROM_DEV, IOLEN,SGLCOUNT);
if (ret == -1)
break;
if ((i & 0xFF) == 0)
printf(" IOS: %d \n", i);
}
printf("ios %d \n", i);
for (i = 0; i < SGLCOUNT; i++)
free(dataptr[i]);
return 0;
}
--
Mark Rustad, MRustad@xxxxxxx
-
: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html