LCOV - code coverage report
Current view: top level - fs/iomap - apply.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 21 28 75.0 %
Date: 2021-04-22 12:43:58 Functions: 1 1 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2010 Red Hat, Inc.
       4             :  * Copyright (c) 2016-2018 Christoph Hellwig.
       5             :  */
       6             : #include <linux/module.h>
       7             : #include <linux/compiler.h>
       8             : #include <linux/fs.h>
       9             : #include <linux/iomap.h>
      10             : #include "trace.h"
      11             : 
      12             : /*
      13             :  * Execute a iomap write on a segment of the mapping that spans a
      14             :  * contiguous range of pages that have identical block mapping state.
      15             :  *
      16             :  * This avoids the need to map pages individually, do individual allocations
      17             :  * for each page and most importantly avoid the need for filesystem specific
      18             :  * locking per page. Instead, all the operations are amortised over the entire
      19             :  * range of pages. It is assumed that the filesystems will lock whatever
      20             :  * resources they require in the iomap_begin call, and release them in the
      21             :  * iomap_end call.
      22             :  */
      23             : loff_t
      24        1948 : iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags,
      25             :                 const struct iomap_ops *ops, void *data, iomap_actor_t actor)
      26             : {
      27        1948 :         struct iomap iomap = { .type = IOMAP_HOLE };
      28        1948 :         struct iomap srcmap = { .type = IOMAP_HOLE };
      29        1948 :         loff_t written = 0, ret;
      30        1948 :         u64 end;
      31             : 
      32        1948 :         trace_iomap_apply(inode, pos, length, flags, ops, actor, _RET_IP_);
      33             : 
      34             :         /*
      35             :          * Need to map a range from start position for length bytes. This can
      36             :          * span multiple pages - it is only guaranteed to return a range of a
      37             :          * single type of pages (e.g. all into a hole, all mapped or all
      38             :          * unwritten). Failure at this point has nothing to undo.
      39             :          *
      40             :          * If allocation is required for this range, reserve the space now so
      41             :          * that the allocation is guaranteed to succeed later on. Once we copy
      42             :          * the data into the page cache pages, then we cannot fail otherwise we
      43             :          * expose transient stale data. If the reserve fails, we can safely
      44             :          * back out at this point as there is nothing to undo.
      45             :          */
      46        1948 :         ret = ops->iomap_begin(inode, pos, length, flags, &iomap, &srcmap);
      47        1948 :         if (ret)
      48             :                 return ret;
      49        1948 :         if (WARN_ON(iomap.offset > pos)) {
      50           0 :                 written = -EIO;
      51           0 :                 goto out;
      52             :         }
      53        1948 :         if (WARN_ON(iomap.length == 0)) {
      54           0 :                 written = -EIO;
      55           0 :                 goto out;
      56             :         }
      57             : 
      58        1948 :         trace_iomap_apply_dstmap(inode, &iomap);
      59        1948 :         if (srcmap.type != IOMAP_HOLE)
      60           0 :                 trace_iomap_apply_srcmap(inode, &srcmap);
      61             : 
      62             :         /*
      63             :          * Cut down the length to the one actually provided by the filesystem,
      64             :          * as it might not be able to give us the whole size that we requested.
      65             :          */
      66        1948 :         end = iomap.offset + iomap.length;
      67        1948 :         if (srcmap.type != IOMAP_HOLE)
      68           0 :                 end = min(end, srcmap.offset + srcmap.length);
      69        1948 :         if (pos + length > end)
      70           0 :                 length = end - pos;
      71             : 
      72             :         /*
      73             :          * Now that we have guaranteed that the space allocation will succeed,
      74             :          * we can do the copy-in page by page without having to worry about
      75             :          * failures exposing transient data.
      76             :          *
      77             :          * To support COW operations, we read in data for partially blocks from
      78             :          * the srcmap if the file system filled it in.  In that case we the
      79             :          * length needs to be limited to the earlier of the ends of the iomaps.
      80             :          * If the file system did not provide a srcmap we pass in the normal
      81             :          * iomap into the actors so that they don't need to have special
      82             :          * handling for the two cases.
      83             :          */
      84        3896 :         written = actor(inode, pos, length, data, &iomap,
      85             :                         srcmap.type != IOMAP_HOLE ? &srcmap : &iomap);
      86             : 
      87        1948 : out:
      88             :         /*
      89             :          * Now the data has been copied, commit the range we've copied.  This
      90             :          * should not fail unless the filesystem has had a fatal error.
      91             :          */
      92        1948 :         if (ops->iomap_end) {
      93        1948 :                 ret = ops->iomap_end(inode, pos, length,
      94        1948 :                                      written > 0 ? written : 0,
      95             :                                      flags, &iomap);
      96             :         }
      97             : 
      98        1948 :         return written ? written : ret;
      99             : }

Generated by: LCOV version 1.14