/* Copyright (C) 2005,2006 David Decotigny This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include "fstest_utils.h" /** * @file blktest.c * * Block devices tests */ static int test_device(char const* path, char magic) { char wrbuff[32767]; char rdbuff[32767]; int fd, fdcheck, i; char * mem; fd = open(path, O_RDWR); if (fd < 0) { bochs_printf("Cannot open %s: error %d\n", path, fd); return -1; } bochs_printf("Testing %s...\n", path); /* Basic seek tests */ TEST_EXPECT_CONDITION(lseek(fd, 2*512, SEEK_SET), RETVAL == 2*512); TEST_EXPECT_CONDITION(write(fd, wrbuff, 1), RETVAL == 1); TEST_EXPECT_CONDITION(lseek(fd, 4*512, SEEK_SET), RETVAL == 4*512); TEST_EXPECT_CONDITION(read(fd, rdbuff, 1), RETVAL == 1); /* Prepare to write a large chunk */ for (i = 0 ; i < sizeof(wrbuff) ; i ++) wrbuff[i] = magic + i; memset(rdbuff, 0xaa, sizeof(wrbuff)); TEST_EXPECT_CONDITION(lseek(fd, 3*512 + 43, SEEK_SET), RETVAL == 3*512 + 43); TEST_EXPECT_CONDITION(write(fd, wrbuff, sizeof(wrbuff)), RETVAL == sizeof(wrbuff)); TEST_EXPECT_CONDITION(write(fd, rdbuff, sizeof(rdbuff)), RETVAL == sizeof(rdbuff)); memset(rdbuff, 0xbb, sizeof(rdbuff)); TEST_EXPECT_CONDITION(lseek(fd, 3*512 + 47, SEEK_SET), RETVAL == 3*512 + 47); TEST_EXPECT_CONDITION(read(fd, rdbuff, sizeof(wrbuff)), RETVAL == sizeof(wrbuff)); TEST_EXPECT_CONDITION(memcmp(rdbuff, wrbuff+4, sizeof(wrbuff)-4), RETVAL == 0); fdcheck = open(path, O_RDONLY); #define MAPOFFS (50*4096) /* Test mmap private mappings */ TEST_EXPECT_CONDITION(mem = mmap(NULL, sizeof(wrbuff), PROT_READ, MAP_PRIVATE, fd, MAPOFFS + 3), (void*)RETVAL == NULL); TEST_EXPECT_CONDITION(mem = mmap(NULL, sizeof(wrbuff), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, MAPOFFS), (void*)RETVAL != NULL); for (i = 0 ; i < sizeof(wrbuff) ; i ++) wrbuff[i] = magic + i; TEST_EXPECT_CONDITION(1, 1); /* Print a debug line */ memset(rdbuff, 0xaa, sizeof(wrbuff)); TEST_EXPECT_CONDITION(lseek(fd, MAPOFFS, SEEK_SET), RETVAL == MAPOFFS); TEST_EXPECT_CONDITION(write(fd, wrbuff, sizeof(wrbuff)), RETVAL == sizeof(wrbuff)); TEST_EXPECT_CONDITION(memcmp(wrbuff, mem, sizeof(wrbuff)), RETVAL == 0); for (i = 0 ; i < sizeof(wrbuff) ; i ++) mem[i] = wrbuff[i]*i; TEST_EXPECT_CONDITION(1, 1); /* Print a debug line */ memset(rdbuff, 0xaa, sizeof(rdbuff)); TEST_EXPECT_CONDITION(lseek(fdcheck, MAPOFFS, SEEK_SET), RETVAL == MAPOFFS); TEST_EXPECT_CONDITION(read(fdcheck, rdbuff, sizeof(wrbuff)), RETVAL == sizeof(wrbuff)); TEST_EXPECT_CONDITION(memcmp(wrbuff, rdbuff, sizeof(wrbuff)), RETVAL == 0); TEST_EXPECT_CONDITION(msync(mem, sizeof(wrbuff), MS_SYNC), RETVAL == 0); TEST_EXPECT_CONDITION(munmap(mem, sizeof(wrbuff)), RETVAL == 0); /* Test mmap shared mappings */ TEST_EXPECT_CONDITION(mem = mmap(mem, sizeof(wrbuff), PROT_READ, MAP_SHARED, fd, MAPOFFS + 3), (void*)RETVAL == NULL); TEST_EXPECT_CONDITION(mem = mmap(mem, sizeof(wrbuff), PROT_READ | PROT_WRITE, MAP_SHARED, fd, MAPOFFS), (void*)RETVAL != NULL); for (i = 0 ; i < sizeof(wrbuff) ; i ++) wrbuff[i] = magic + i; memset(rdbuff, 0xaa, sizeof(rdbuff)); TEST_EXPECT_CONDITION(lseek(fd, MAPOFFS, SEEK_SET), RETVAL == MAPOFFS); TEST_EXPECT_CONDITION(write(fd, wrbuff, sizeof(wrbuff)), RETVAL == sizeof(wrbuff)); TEST_EXPECT_CONDITION(memcmp(wrbuff, mem, sizeof(wrbuff)), RETVAL == 0); for (i = 0 ; i < sizeof(wrbuff) ; i ++) mem[i] = wrbuff[i]*i; memset(rdbuff, 0xaa, sizeof(rdbuff)); TEST_EXPECT_CONDITION(lseek(fdcheck, MAPOFFS, SEEK_SET), RETVAL == MAPOFFS); TEST_EXPECT_CONDITION(read(fdcheck, rdbuff, sizeof(wrbuff)), RETVAL == sizeof(wrbuff)); TEST_EXPECT_CONDITION(memcmp(wrbuff, rdbuff, sizeof(wrbuff)), RETVAL != 0); TEST_EXPECT_CONDITION(memcmp(mem, rdbuff, sizeof(wrbuff)), RETVAL == 0); TEST_EXPECT_CONDITION(msync(mem, sizeof(wrbuff), MS_SYNC), RETVAL == 0); TEST_EXPECT_CONDITION(munmap(mem, sizeof(wrbuff)), RETVAL == 0); #define STARTOFFS (3*512 + 43 + sizeof(wrbuff) + sizeof(rdbuff)) TEST_EXPECT_CONDITION(lseek(fd, STARTOFFS, SEEK_SET), RETVAL == STARTOFFS); TEST_EXPECT_CONDITION(lseek(fdcheck, STARTOFFS, SEEK_SET), RETVAL == STARTOFFS); int wrlen = 0; while (1) { int sz; for (i = 0 ; i < sizeof(wrbuff) ; i ++) wrbuff[i] = magic*magic*i + wrlen*wrlen + i; TEST_EXPECT_CONDITION(sz = write(fd, wrbuff, sizeof(wrbuff)), (RETVAL >= 0) && (RETVAL <= sizeof(wrbuff))); if (sz <= 0) break; wrlen += sz; memset(rdbuff, 0xcc, sizeof(wrbuff)); TEST_EXPECT_CONDITION(read(fdcheck, rdbuff, sizeof(wrbuff)), RETVAL == sz); TEST_EXPECT_CONDITION(memcmp(rdbuff, wrbuff, sz), RETVAL == 0); } /* Check the data was correctly written */ TEST_EXPECT_CONDITION(lseek(fd, STARTOFFS, SEEK_SET), RETVAL == STARTOFFS); int rdlen = 0; while (1) { int sz; for (i = 0 ; i < sizeof(wrbuff) ; i ++) wrbuff[i] = magic*magic*i + rdlen*rdlen + i; memset(rdbuff, 0xdd, sizeof(wrbuff)); TEST_EXPECT_CONDITION(sz = read(fd, rdbuff, sizeof(wrbuff)), (RETVAL >= 0) && (RETVAL <= sizeof(wrbuff))); if (sz <= 0) break; rdlen += sz; TEST_EXPECT_CONDITION(memcmp(rdbuff, wrbuff, sz), RETVAL == 0); } TEST_EXPECT_CONDITION(rdlen, wrlen == rdlen); bochs_printf("Synching %s...\n", path); ioctl(fd, SOS_IOCTL_BLOCKDEV_SYNC, 0); close(fd); bochs_printf("End of test for %s.\n", path); return 0; } int main(void) { int i; bochs_printf("Hi from blktest\n"); /* Test partitions access */ for (i = 1 ; i <= 15 ; i ++) { char path[64]; snprintf(path, sizeof(path), "/dev/hda%d", i); if (fork() == 0) { test_device(path, i); return 0; } } bochs_printf("Bye from blktest\n"); return 0; }