]> Git Repo - linux.git/blobdiff - fs/iomap.c
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux.git] / fs / iomap.c
index 64ce240217a18985dd0510fd968b257dce214cd4..3ffb776fbebe33492be0c05c5dee41f5f166b753 100644 (file)
@@ -142,13 +142,14 @@ static void
 iomap_adjust_read_range(struct inode *inode, struct iomap_page *iop,
                loff_t *pos, loff_t length, unsigned *offp, unsigned *lenp)
 {
+       loff_t orig_pos = *pos;
+       loff_t isize = i_size_read(inode);
        unsigned block_bits = inode->i_blkbits;
        unsigned block_size = (1 << block_bits);
        unsigned poff = offset_in_page(*pos);
        unsigned plen = min_t(loff_t, PAGE_SIZE - poff, length);
        unsigned first = poff >> block_bits;
        unsigned last = (poff + plen - 1) >> block_bits;
-       unsigned end = offset_in_page(i_size_read(inode)) >> block_bits;
 
        /*
         * If the block size is smaller than the page size we need to check the
@@ -183,8 +184,12 @@ iomap_adjust_read_range(struct inode *inode, struct iomap_page *iop,
         * handle both halves separately so that we properly zero data in the
         * page cache for blocks that are entirely outside of i_size.
         */
-       if (first <= end && last > end)
-               plen -= (last - end) * block_size;
+       if (orig_pos <= isize && orig_pos + length > isize) {
+               unsigned end = offset_in_page(isize - 1) >> block_bits;
+
+               if (first <= end && last > end)
+                       plen -= (last - end) * block_size;
+       }
 
        *offp = poff;
        *lenp = plen;
@@ -1580,7 +1585,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
        struct bio *bio;
        bool need_zeroout = false;
        bool use_fua = false;
-       int nr_pages, ret;
+       int nr_pages, ret = 0;
        size_t copied = 0;
 
        if ((pos | length | align) & ((1 << blkbits) - 1))
@@ -1596,12 +1601,13 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 
        if (iomap->flags & IOMAP_F_NEW) {
                need_zeroout = true;
-       } else {
+       } else if (iomap->type == IOMAP_MAPPED) {
                /*
-                * Use a FUA write if we need datasync semantics, this
-                * is a pure data IO that doesn't require any metadata
-                * updates and the underlying device supports FUA. This
-                * allows us to avoid cache flushes on IO completion.
+                * Use a FUA write if we need datasync semantics, this is a pure
+                * data IO that doesn't require any metadata updates (including
+                * after IO completion such as unwritten extent conversion) and
+                * the underlying device supports FUA. This allows us to avoid
+                * cache flushes on IO completion.
                 */
                if (!(iomap->flags & (IOMAP_F_SHARED|IOMAP_F_DIRTY)) &&
                    (dio->flags & IOMAP_DIO_WRITE_FUA) &&
@@ -1644,8 +1650,14 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 
                ret = bio_iov_iter_get_pages(bio, &iter);
                if (unlikely(ret)) {
+                       /*
+                        * We have to stop part way through an IO. We must fall
+                        * through to the sub-block tail zeroing here, otherwise
+                        * this short IO may expose stale data in the tail of
+                        * the block we haven't written data to.
+                        */
                        bio_put(bio);
-                       return copied ? copied : ret;
+                       goto zero_tail;
                }
 
                n = bio->bi_iter.bi_size;
@@ -1676,13 +1688,21 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
                dio->submit.cookie = submit_bio(bio);
        } while (nr_pages);
 
-       if (need_zeroout) {
+       /*
+        * We need to zeroout the tail of a sub-block write if the extent type
+        * requires zeroing or the write extends beyond EOF. If we don't zero
+        * the block tail in the latter case, we can expose stale data via mmap
+        * reads of the EOF block.
+        */
+zero_tail:
+       if (need_zeroout ||
+           ((dio->flags & IOMAP_DIO_WRITE) && pos >= i_size_read(inode))) {
                /* zero out from the end of the write to the end of the block */
                pad = pos & (fs_block_size - 1);
                if (pad)
                        iomap_dio_zero(dio, iomap, pos, fs_block_size - pad);
        }
-       return copied;
+       return copied ? copied : ret;
 }
 
 static loff_t
@@ -1857,6 +1877,15 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                                dio->wait_for_completion = true;
                                ret = 0;
                        }
+
+                       /*
+                        * Splicing to pipes can fail on a full pipe. We have to
+                        * swallow this to make it look like a short IO
+                        * otherwise the higher splice layers will completely
+                        * mishandle the error and stop moving data.
+                        */
+                       if (ret == -EFAULT)
+                               ret = 0;
                        break;
                }
                pos += ret;
This page took 0.034097 seconds and 4 git commands to generate.