<div dir="ltr"><div><div><div><div><div>Hi Dietmar, hi Alexandre, hi all,<br><br>I had to learn basics of C and POSIX Threads to create a reproducible test case for out of sync blocks. And now I am back with both good and bad results. The good result is a reliable way to reproduce the problem and the bad one is the fact that the problem exists.<br><br></div><div>Bellow you find a C-program which runs two threads, where:<br></div><div>- the first thread writes data from buffer (x) to a block device 10 000 times<br></div><div>- the second thread changes data in buffer at the same time<br><br></div><div>Results:<br></div><div>- if block device is open without O_DIRECT - the issue never happen<br>- if block device is open with O_DIRECT - the oos bocks appear almost every run<br><br></div><div>What this means? This means that kvm  process does the same thing: it does not wait until "write" system call is finished and all data from buffer reaches block device. Instead it changes buffer somwhere in between. I am not sure if behaviour of DRBD can be changed so it does not produce out of sync with O_DIRECT. This behaviour can be related to kernel code itself and not just DRBD. At the same time changing buffer in KVM while not all data reached block device does not seem right.<br></div><div><br><br><br><br>1. Prerequisites:<br>- installed gcc<br>- drbd block device with data-integrity-alg enabled (generally this is not necessary however it would help to catch the problem right away and not wasting time doing "drbdadm verify")<br><br>2. Here is the code:<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">-------------------------------------------------------------------<br></span>#define _GNU_SOURCE<br><br>#include <fcntl.h>      // O_DIRECT<br>#include <malloc.h>     // free<br>#include <string.h>     // memset, atoi<br>#include <pthread.h>    // pthread_create<br>#include <stdio.h>      // printf<br><br>#define BUFFER_SIZE 4096<br>#define ALIGN 512<br>#define DELAY 10000<br><br>char *x;<br><br>void *write_to_blkdev(void *arg)<br>{<br>    int fd = open((char*) arg, O_RDWR | O_CREAT | O_DIRECT, 0660);<br>    //int fd = open((char*) arg, O_RDWR | O_CREAT, 0660);<br>    if (fd > 0) {<br>        memset(x, 55, BUFFER_SIZE);<br>        int i;<br>        for(i=0; i<10000; i++) {<br>            write(fd, x, BUFFER_SIZE);<br>        }<br>    }<br>    close(fd);<br>}<br><br>void *change_buffer(void *arg)<br>{<br>    int i;<br>    for(i=0; i<100; i++) {<br>        memset(x, i, BUFFER_SIZE);<br>        usleep(DELAY);<br>    }<br>}<br><br>int main(int argc, char *argv[])<br>{<br>    int ret = posix_memalign(&x, ALIGN, BUFFER_SIZE);<br>    if (ret < 0) { return -1; }<br><br>    pthread_t pth1, pth2;<br><br>    pthread_create(&pth1, NULL, write_to_blkdev, argv[1]);<br>    pthread_create(&pth2, NULL, change_buffer, "");<br><br>    printf("Waiting for change_buffer thread\n");<br>    pthread_join(pth2, NULL);<br>    printf("Waiting for write_to_blkdev thread\n");<br>    pthread_join(pth1, NULL);<br><br>    free(x);<br>}<br>-------------------------------------------------------------------<br><br></span></div><span style="font-family:monospace,monospace">3. Building<br></span></div><div><span style="font-family:monospace,monospace"><br>gcc -pthread drbd_oos_test.c<br><br></span></div><span style="font-family:monospace,monospace">4. Using<br><br></span></div><span style="font-family:monospace,monospace">./a.out /dev/drbd0<br><br></span></div><div><span style="font-family:monospace,monospace">PS: This test was done on a virtual machine thus on a physical one you would probably need to play with DELAY.<br></span></div><div><span style="font-family:monospace,monospace"><br></span></div><span style="font-family:monospace,monospace">Best regards,<br></span></div><span style="font-family:monospace,monospace">Stanislav German-Evtushenko<br></span></div>