blob: 30e5bc2d6bcd4c61ff01a1d72102680279ee5778 [file] [log] [blame]
/*
* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* These tests verify that sync works correctly.
*
* Each test is written in two phases. The first sets up the test,
* writes the data, calls sync and then crashes the system.
*
* After the system reboots, the second phase of the test verifies
* the results and cleans up.
*
* Current phases:
* writer - writes to the given file, calls fsync, then crashes.
* mapper - uses memory mapped file to write data, calls msync,
* then crashes.
* verifier - verifies that all the data that was synced is there.
*
* Uses a 64 bit counter for the data.
*/
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <debug.h>
#include <eprintf.h>
#include <esys.h>
#include <puny.h>
#include <style.h>
#include <util.h>
enum {
CHUNK_SIZE = (1<<13),
NUM_U64_PER_CHUNK = CHUNK_SIZE / sizeof(u64)
};
static char *PhaseName;
typedef void (*phasefn_t)(void);
struct phase {
char *name;
phasefn_t fn;
};
u64 Buf[NUM_U64_PER_CHUNK];
u64 Value;
static void fill(void)
{
int i;
for (i = 0; i < NUM_U64_PER_CHUNK; i++)
Buf[i] = Value++;
}
static void verify(void)
{
int i;
for (i = 0; i < NUM_U64_PER_CHUNK; i++) {
if (Buf[i] != Value)
fatal("Expected %lld is %lld", Value, Buf[i]);
Value++;
}
}
static void writer(void)
{
u64 size = Option.file_size;
u64 chunks = size / sizeof(Buf);
u64 i;
int fd = eopen(Option.file, O_WRONLY | O_CREAT | O_TRUNC);
Value = 0;
for (i = 0; i < chunks; i++) {
fill();
ewrite(fd, Buf, sizeof(Buf));
}
efsync(fd);
crash();
}
static void mapper(void)
{
u64 size = Option.file_size;
u64 chunks = size / sizeof(Buf);
u64 i;
u8 *map;
u8 *m;
int fd = eopen(Option.file, O_RDWR | O_CREAT | O_TRUNC);
Value = 0;
epwrite(fd, "", 1, size - 1);
map = emmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
for (m = map, i = 0; i < chunks; i++, m += sizeof(Buf)) {
fill();
memcpy(m, Buf, sizeof(Buf));
}
emsync(map, size, MS_SYNC);
crash();
}
static void verifier(void)
{
u64 size = Option.file_size;
u64 blocks = size / sizeof(Buf);
u64 i;
int fd = eopen(Option.file, O_RDONLY);
Value = 0;
for (i = 0; i < blocks; i++) {
eread(fd, Buf, sizeof(Buf));
verify();
}
eclose(fd);
}
static struct phase Phase[] = {
{ "writer", writer },
{ "mapper", mapper },
{ "verifier", verifier }
};
static phasefn_t find_phase(char *name)
{
int n = sizeof(Phase) / sizeof(struct phase);
int i;
for (i = 0; i < n; i++)
if (strcmp(name, Phase[i].name) == 0)
return Phase[i].fn;
fatal("Phase %s: not found", name);
return NULL;
}
static bool myopt(int c)
{
switch (c) {
case 'p':
PhaseName = strdup(optarg);
break;
default:
return FALSE;
}
return TRUE;
}
void usage (void)
{
pr_usage("-f <file> -p <test phase name>\n"
"\tf - file to write");
}
int main(int argc, char *argv[])
{
phasefn_t fn;
punyopt(argc, argv, myopt, "p:");
fn = find_phase(PhaseName);
if (fn)
fn();
return 0;
}