397 Star 1.4K Fork 1.3K

GVPopenEuler / kernel

 / 详情

【openEuler 21.09】dio read到pagecache的时候低概率触发ext4 writepage的BUG_ON

已完成
缺陷
创建于  
2021-11-26 10:47

如下方式可以毕现。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>

int fd1, fd2;
char *addr;

void *thr_fn(void *arg)
{
int ret;
printf("Submit read IO\n");
ret = read(fd2, addr, 4096);
printf("Read IO done %d\n", ret);
return ((void *)0);
}

int main(int argc, char *argv[])
{
pthread_t tid;
int err;
void *tret;

    fd1 = open(argv[1], O_RDWR);
    if (fd1 < 0) {
            printf("Failed to open %s\n", argv[1]);
            return -1; 
    }   
    fd2 = open(argv[2], O_RDWR | O_DIRECT);
    if (fd2 < 0) {
            printf("Failed to open %s\n", argv[2]);
            return -1; 
    }   

    /* Map page from fileA */
    addr = mmap(NULL, 4096, PROT_WRITE | PROT_READ, MAP_SHARED, fd1, 0); 
    if (addr == MAP_FAILED) {
            printf("Failed to mmap\n");
            return -1; 
    }   

    /* Write something, make sure the page is been created */
    addr[0] = 'a';
    fsync(fd1);

    /* Thread direct read the fileB through the page of fileA */
    err = pthread_create(&tid, NULL, thr_fn, NULL);
    if (err != 0) {
            printf("Failed to create thread\n");
            return -1;
    }

    /* unmap the page and call fsync to make sure page is !dirty and !mapped */
    sleep(1);
    munmap(addr, 4096);
    fsync(fd1);
    system("echo 3 > /proc/sys/vm/drop_caches");

    getchar();

    pthread_join(tid, &tret);
    close(fd1);
    close(fd2);
    return 0;

}

diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index 933f234d5bec..d1098b64dede 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -10,6 +10,7 @@
#include <linux/backing-dev.h>
#include <linux/uio.h>
#include <linux/task_io_accounting_ops.h>
+#include <linux/delay.h>
#include "trace.h"

#include "../internal.h"
@@ -290,6 +291,12 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
bio_put(bio);
goto zero_tail;
}

  •           if (iov_iter_rw(dio->submit.iter) == READ &&
    
  •                           !strncmp(inode->i_sb->s_type->name, "ext4", 4)) {
    
  •                   printk("[%s] submit direct read io, start to wait 10s\n", __func__);
    
  •                   msleep(10 * 1000);
    
  •           }
    
            n = bio->bi_iter.bi_size;
            if (dio->flags & IOMAP_DIO_WRITE) {

gcc a.c -lpthread
mkfs.ext4 /dev/sda
mount /dev/sda /mnt
dd if=/dev/zero of=/mnt/fileA bs=4K count=1
dd if=/dev/zero of=/mnt/fileB bs=4K count=1
./a.out /mnt/fileA /mnt/fileB
即会出现BUG。

注意,必须用dd,用fallocate的话触发不了:

评论 (2)

Yang Erkun 创建了缺陷

Hi yang-erkun, welcome to the openEuler Community.
I'm the Bot here serving you. You can find the instructions on how to interact with me at
https://gitee.com/openeuler/community/blob/master/en/sig-infrastructure/command.md.
If you have any questions, please contact the SIG: Kernel, and any of the maintainers: @Xie XiuQi, @YangYingliang, @成坚 (CHENG Jian).

openeuler-ci-bot 添加了
 
sig/Kernel
标签
Yang Erkun 任务状态待办的 修改为已完成

诚邀Issue的创建人,负责人,协作人以及评论人对此次Issue解决过程给予评价:

   0   1   2   3   4   5   6   7   8   9   10  

 不满意                        非常满意

登录 后才可以发表评论

状态
负责人
项目
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
预计工期 (小时)
参与者(3)
5329419 openeuler ci bot 1632792936 9968373 openeuler survey bot 1637036855
C
1
https://gitee.com/openeuler/kernel.git
git@gitee.com:openeuler/kernel.git
openeuler
kernel
kernel

搜索帮助