From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
To: Jan Stancek <jstancek@redhat.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] fat: fix corruption in fat_alloc_new_dir()
Date: Sun, 08 Sep 2019 19:20:49 +0900 [thread overview]
Message-ID: <87v9u3xf5q.fsf@mail.parknet.co.jp> (raw)
In-Reply-To: <fc8878aeefea128c105c49671b2a1ac4694e1f48.1567468225.git.jstancek@redhat.com> (Jan Stancek's message of "Tue, 3 Sep 2019 01:59:36 +0200")
Jan Stancek <jstancek@redhat.com> writes:
> sb_getblk does not guarantee that buffer_head is uptodate. If there is
> async read running in parallel for same buffer_head, it can overwrite
> just initialized msdos_dir_entry, leading to corruption:
> FAT-fs (loop0): error, corrupted directory (invalid entries)
> FAT-fs (loop0): Filesystem has been set read-only
>
> This can happen for example during LTP statx04, which creates loop
> device, formats it (mkfs.vfat), mounts it and immediately creates
> a new directory. In parallel, systemd-udevd is probing new block
> device, which leads to async read.
>
> do_mkdirat ksys_read
> vfs_mkdir vfs_read
> vfat_mkdir __vfs_read
> fat_alloc_new_dir new_sync_read
> /* init de[0], de[1] */ blkdev_read_iter
> generic_file_read_iter
> generic_file_buffered_read
> blkdev_readpage
> block_read_full_page
>
> Faster reproducer (based on LTP statx04):
>
> int main(void)
> {
> int i, j, ret, fd, loop_fd, ctrl_fd;
> int loop_num;
> char loopdev[256], tmp[256], testfile[256];
>
> mkdir("/tmp/mntpoint", 0777);
> for (i = 0; ; i++) {
> printf("Iteration: %d\n", i);
> sprintf(testfile, "/tmp/test.img.%d", getpid());
>
> ctrl_fd = open("/dev/loop-control", O_RDWR);
> loop_num = ioctl(ctrl_fd, LOOP_CTL_GET_FREE);
> close(ctrl_fd);
> sprintf(loopdev, "/dev/loop%d", loop_num);
>
> fd = open(testfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
> fallocate(fd, 0, 0, 256*1024*1024);
> close(fd);
>
> fd = open(testfile, O_RDWR);
> loop_fd = open(loopdev, O_RDWR);
> ioctl(loop_fd, LOOP_SET_FD, fd);
> close(loop_fd);
> close(fd);
>
> sprintf(tmp, "mkfs.vfat %s", loopdev);
> system(tmp);
> mount(loopdev, "/tmp/mntpoint", "vfat", 0, NULL);
>
> for (j = 0; j < 200; j++) {
> sprintf(tmp, "/tmp/mntpoint/testdir%d", j);
> ret = mkdir(tmp, 0777);
> if (ret) {
> perror("mkdir");
> break;
> }
> }
>
> umount("/tmp/mntpoint");
> loop_fd = open(loopdev, O_RDWR);
> ioctl(loop_fd, LOOP_CLR_FD, fd);
> close(loop_fd);
> unlink(testfile);
>
> if (ret)
> break;
> }
>
> return 0;
> }
>
> Issue triggers within minute on HPE Apollo 70 (arm64, 64GB RAM, 224 CPUs).
Using the device while mounting same device doesn't work reliably like
this race. (getblk() is intentionally used to get the buffer to write
new data.)
mount(2) internally opens the device by EXCL mode, so I guess udev opens
without EXCL (I dont know if it is intent or not).
Thanks.
--
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
next prev parent reply other threads:[~2019-09-08 10:20 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-02 23:59 [PATCH] fat: fix corruption in fat_alloc_new_dir() Jan Stancek
2019-09-08 10:20 ` OGAWA Hirofumi [this message]
2019-09-08 19:06 ` Jan Stancek
2019-09-10 3:53 ` OGAWA Hirofumi
2019-09-10 16:27 ` Jan Stancek
2019-09-11 6:55 ` [PATCH] fat: Workaround the race with userspace's read via blockdev while mounting OGAWA Hirofumi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87v9u3xf5q.fsf@mail.parknet.co.jp \
--to=hirofumi@mail.parknet.co.jp \
--cc=jstancek@redhat.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox