Тест:
- Запись на целевое устройство - проверяемый шаблон, размер записи 512b.
- синхронизировать целевое устройство каждые n итераций.
- Пишите в лог-устройство о вышеописанной записи.
- fsync регистрирует каждую итерацию.
- Перейти к шагу 1.
Шаг # 2 может переключаться между вызовами syncfs () и fsync (). Целевое устройство является необработанным блочным устройством.
Запустите тест, подождите несколько минут, сбросьте питание. После перезапуска тест считывает файл журнала, чтобы выяснить последнюю действительную запись, и ищет ее на целевом устройстве. Ошибка чтения для записи на целевом устройстве считается ошибкой.
Результат:
Тест проходит каждый раз при использовании fsync () на целевом устройстве, но периодически дает сбой при использовании syncfs (). Есть идеи, почему это так?
Некоторые соответствующие фрагменты кода. Я могу опубликовать полный файл, если это необходимо.
static char recordbuff[RECORD_SIZE] __attribute__ ((aligned(RECORD_SIZE)));
static inline
void writerecord(int fd, struct msg *m, int dosync) {
int rc;
memcpy(recordbuff, m, sizeof(*m));
rc = write(fd, recordbuff, sizeof(recordbuff));
assert(rc == sizeof(recordbuff));
if (dosync) {
if (use_syncfs) {
rc = syncfs(fd);
} else {
rc = fsync(fd);
}
assert (rc == 0);
}
}
static inline
void writelog(int logfd, unsigned int iter) {
int rc;
rc=lseek(logfd, 0, SEEK_SET);
assert(rc==0);
rc = write(logfd, &iter, sizeof(iter));
assert (rc == sizeof(iter));
rc = fsync(logfd);
assert (rc == 0);
}
static void main()
{
...
while (1) {
// create new record
next_msg(&m, &n);
dump_msg("new msg", &n);
if ((n.iteration % MAX_ITERATIONS) == 0) {
/* wrap over */
rc = lseek(fd, 0, SEEK_SET);
assert (rc == 0);
}
// write new record
if ((n.iteration % SYNC_ITERATION) == 0) {
writerecord(fd, &n, !(mode & O_SYNC));
writelog(logfd, n.iteration);
} else {
writerecord(fd, &n, 0);
}
memcpy(&m, &n, sizeof(m));
}
}