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 for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200319150805.uaggnfue5xgaougx@fiona>
Date:   Thu, 19 Mar 2020 10:08:05 -0500
From:   Goldwyn Rodrigues <rgoldwyn@...e.de>
To:     linux-fsdevel@...r.kernel.org
Cc:     riteshh@...ux.ibm.com, linux-ext4@...r.kernel.org,
        hch@...radead.org, darrick.wong@...cle.com, willy@...radead.org
Subject: [PATCH v2] iomap: return partial I/O count on error in
 iomap_dio_bio_actor

Currently, I/Os that complete with an error indicate this by passing
written == 0 to the iomap_end function.  However, btrfs needs to know how
many bytes were written for its own accounting.  Change the convention
to pass the number of bytes which were actually written, and change the
only user (ext4) to check for a short write instead of a zero length
write.

For filesystems that do not define ->iomap_end(), check for
dio->error again after the iomap_apply() call to diagnose the error.

Changes since v1:
 - Considerate of iov_iter rollback functions
 - Double check errors for filesystems not implementing iomap_end()

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@...e.com>

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index fa0ff78..d52c70f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3475,7 +3475,7 @@ static int ext4_iomap_end(struct inode *inode, loff_t offset, loff_t length,
 	 * the I/O. Any blocks that may have been allocated in preparation for
 	 * the direct I/O will be reused during buffered I/O.
 	 */
-	if (flags & (IOMAP_WRITE | IOMAP_DIRECT) && written == 0)
+	if (flags & (IOMAP_WRITE | IOMAP_DIRECT) && written < length)
 		return -ENOTBLK;
 
 	return 0;
diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index 41c1e7c..b5f4d4a 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -264,7 +264,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 		size_t n;
 		if (dio->error) {
 			iov_iter_revert(dio->submit.iter, copied);
-			copied = ret = 0;
+			ret = dio->error;
 			goto out;
 		}
 
@@ -325,8 +325,17 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 			iomap_dio_zero(dio, iomap, pos, fs_block_size - pad);
 	}
 out:
-	/* Undo iter limitation to current extent */
-	iov_iter_reexpand(dio->submit.iter, orig_count - copied);
+	/*
+	 * Undo iter limitation to current extent
+	 * If there is an error, undo the entire extent. However, return the
+	 * bytes copied so far for filesystems such as btrfs to account for
+	 * submitted I/O.
+	 */
+	if (ret < 0)
+		iov_iter_reexpand(dio->submit.iter, orig_count);
+	else
+		iov_iter_reexpand(dio->submit.iter, orig_count - copied);
+
 	if (copied)
 		return copied;
 	return ret;
@@ -499,6 +508,10 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 	do {
 		ret = iomap_apply(inode, pos, count, flags, ops, dio,
 				iomap_dio_actor);
+
+		if (ret >= 0 && dio->error)
+			ret = dio->error;
+
 		if (ret <= 0) {
 			/* magic error code to fall back to buffered I/O */
 			if (ret == -ENOTBLK) {

-- 
Goldwyn

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ