lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <5f6701dacc79$33afa870$9b0ef950$@samsung.com>
Date: Tue, 2 Jul 2024 21:13:09 +0900
From: "Sunmin Jeong" <s_min.jeong@...sung.com>
To: "'Chao Yu'" <chao@...nel.org>, <jaegeuk@...nel.org>
Cc: <linux-kernel@...r.kernel.org>, <linux-f2fs-devel@...ts.sourceforge.net>
Subject: RE: [f2fs-dev] [PATCH 4/4] f2fs: atomic: fix to forbid dio in
 atomic_file

Hello

I also have been thinking about the GC of the atomic file these days. I
read your patches for atomic write, but I think there are some corner
cases that can't be resolved with them.

First is when the GC of the atomic file occurs right after the writeback
of newly updated page. Since the atomic page flag is cleared at the end
of f2fs_do_write_data_page, the GC thread will set the page dirty and
let it be written to the atomic file, which will cause the data
corruption of the original inode.

Second is the foreground GC of atomic file. Although your patch can
distinguish whether pages should be written to the original inode or cow
inode, it can't handle the case when the atomic page needs to be
migrated but updated page already exists in the page cache as below.

// atomic file's 1st old block is a and new block is b.
// b is in the page cache
GC thread(FG_GC)
  - select A as a victim segment
  do_garbage_collect
    - iget atomic file's inode for block a
    move_data_page
      f2fs_do_write_data_page
        - use dn of cow inode since b has atomic flag
    - seg_freed is 0 since block a is still valid
    - goto gc_more and A is selected as victim again

Third is a race condition between GC of cow file and writeback thread of
atomic file. Since there are two page caches for one dnode, I think we
need to consider the race condition between them such as the case
between the file inode and the meta inode.

I submitted a patch set for atomic write, so could you review it?
The patch links are as below.
https://sourceforge.net/p/linux-f2fs/mailman/message/58790988/
https://sourceforge.net/p/linux-f2fs/mailman/message/58790989/

Thanks



> atomic write can only be used via buffered IO, let's fail direct IO on
> atomic_file and return -EOPNOTSUPP.
> 
> Signed-off-by: Chao Yu <chao@...nel.org>
> ---
>  fs/f2fs/file.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index
> 0355cb054521..a527de1e7a2f 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -2150,6 +2150,7 @@ static int f2fs_ioc_start_atomic_write(struct file
> *filp, bool truncate)
>  		goto out;
> 
>  	f2fs_down_write(&fi->i_gc_rwsem[WRITE]);
> +	f2fs_down_write(&fi->i_gc_rwsem[READ]);
> 
>  	/*
>  	 * Should wait end_io to count F2FS_WB_CP_DATA correctly by @@ -
> 2209,6 +2210,7 @@ static int f2fs_ioc_start_atomic_write(struct file
*filp,
> bool truncate)
>  	}
>  	f2fs_i_size_write(fi->cow_inode, isize);
> 
> +	f2fs_up_write(&fi->i_gc_rwsem[READ]);
>  	f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
> 
>  	f2fs_update_time(sbi, REQ_TIME);
> @@ -4537,6 +4539,13 @@ static ssize_t f2fs_dio_read_iter(struct kiocb
> *iocb, struct iov_iter *to)
>  		f2fs_down_read(&fi->i_gc_rwsem[READ]);
>  	}
> 
> +	/* dio is not compatible w/ atomic file */
> +	if (f2fs_is_atomic_file(inode)) {
> +		f2fs_up_read(&fi->i_gc_rwsem[READ]);
> +		ret = -EOPNOTSUPP;
> +		goto out;
> +	}
> +
>  	/*
>  	 * We have to use __iomap_dio_rw() and iomap_dio_complete() instead
> of
>  	 * the higher-level function iomap_dio_rw() in order to ensure that
> the @@ -4948,6 +4957,12 @@ static ssize_t f2fs_file_write_iter(struct
> kiocb *iocb, struct iov_iter *from)
>  	/* Determine whether we will do a direct write or a buffered write.
> */
>  	dio = f2fs_should_use_dio(inode, iocb, from);
> 
> +	/* dio is not compatible w/ atomic write */
> +	if (dio && f2fs_is_atomic_file(inode)) {
> +		ret = -EOPNOTSUPP;
> +		goto out_unlock;
> +	}
> +
>  	/* Possibly preallocate the blocks for the write. */
>  	target_size = iocb->ki_pos + iov_iter_count(from);
>  	preallocated = f2fs_preallocate_blocks(iocb, from, dio);
> --
> 2.40.1
> 
> 
> 
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@...ts.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ