root/fs/iomap/fiemap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iomap_to_fiemap
  2. iomap_fiemap_actor
  3. iomap_fiemap
  4. iomap_bmap_actor
  5. iomap_bmap

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2016-2018 Christoph Hellwig.
   4  */
   5 #include <linux/module.h>
   6 #include <linux/compiler.h>
   7 #include <linux/fs.h>
   8 #include <linux/iomap.h>
   9 
  10 struct fiemap_ctx {
  11         struct fiemap_extent_info *fi;
  12         struct iomap prev;
  13 };
  14 
  15 static int iomap_to_fiemap(struct fiemap_extent_info *fi,
  16                 struct iomap *iomap, u32 flags)
  17 {
  18         switch (iomap->type) {
  19         case IOMAP_HOLE:
  20                 /* skip holes */
  21                 return 0;
  22         case IOMAP_DELALLOC:
  23                 flags |= FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN;
  24                 break;
  25         case IOMAP_MAPPED:
  26                 break;
  27         case IOMAP_UNWRITTEN:
  28                 flags |= FIEMAP_EXTENT_UNWRITTEN;
  29                 break;
  30         case IOMAP_INLINE:
  31                 flags |= FIEMAP_EXTENT_DATA_INLINE;
  32                 break;
  33         }
  34 
  35         if (iomap->flags & IOMAP_F_MERGED)
  36                 flags |= FIEMAP_EXTENT_MERGED;
  37         if (iomap->flags & IOMAP_F_SHARED)
  38                 flags |= FIEMAP_EXTENT_SHARED;
  39 
  40         return fiemap_fill_next_extent(fi, iomap->offset,
  41                         iomap->addr != IOMAP_NULL_ADDR ? iomap->addr : 0,
  42                         iomap->length, flags);
  43 }
  44 
  45 static loff_t
  46 iomap_fiemap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
  47                 struct iomap *iomap)
  48 {
  49         struct fiemap_ctx *ctx = data;
  50         loff_t ret = length;
  51 
  52         if (iomap->type == IOMAP_HOLE)
  53                 return length;
  54 
  55         ret = iomap_to_fiemap(ctx->fi, &ctx->prev, 0);
  56         ctx->prev = *iomap;
  57         switch (ret) {
  58         case 0:         /* success */
  59                 return length;
  60         case 1:         /* extent array full */
  61                 return 0;
  62         default:
  63                 return ret;
  64         }
  65 }
  66 
  67 int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi,
  68                 loff_t start, loff_t len, const struct iomap_ops *ops)
  69 {
  70         struct fiemap_ctx ctx;
  71         loff_t ret;
  72 
  73         memset(&ctx, 0, sizeof(ctx));
  74         ctx.fi = fi;
  75         ctx.prev.type = IOMAP_HOLE;
  76 
  77         ret = fiemap_check_flags(fi, FIEMAP_FLAG_SYNC);
  78         if (ret)
  79                 return ret;
  80 
  81         if (fi->fi_flags & FIEMAP_FLAG_SYNC) {
  82                 ret = filemap_write_and_wait(inode->i_mapping);
  83                 if (ret)
  84                         return ret;
  85         }
  86 
  87         while (len > 0) {
  88                 ret = iomap_apply(inode, start, len, IOMAP_REPORT, ops, &ctx,
  89                                 iomap_fiemap_actor);
  90                 /* inode with no (attribute) mapping will give ENOENT */
  91                 if (ret == -ENOENT)
  92                         break;
  93                 if (ret < 0)
  94                         return ret;
  95                 if (ret == 0)
  96                         break;
  97 
  98                 start += ret;
  99                 len -= ret;
 100         }
 101 
 102         if (ctx.prev.type != IOMAP_HOLE) {
 103                 ret = iomap_to_fiemap(fi, &ctx.prev, FIEMAP_EXTENT_LAST);
 104                 if (ret < 0)
 105                         return ret;
 106         }
 107 
 108         return 0;
 109 }
 110 EXPORT_SYMBOL_GPL(iomap_fiemap);
 111 
 112 static loff_t
 113 iomap_bmap_actor(struct inode *inode, loff_t pos, loff_t length,
 114                 void *data, struct iomap *iomap)
 115 {
 116         sector_t *bno = data, addr;
 117 
 118         if (iomap->type == IOMAP_MAPPED) {
 119                 addr = (pos - iomap->offset + iomap->addr) >> inode->i_blkbits;
 120                 if (addr > INT_MAX)
 121                         WARN(1, "would truncate bmap result\n");
 122                 else
 123                         *bno = addr;
 124         }
 125         return 0;
 126 }
 127 
 128 /* legacy ->bmap interface.  0 is the error return (!) */
 129 sector_t
 130 iomap_bmap(struct address_space *mapping, sector_t bno,
 131                 const struct iomap_ops *ops)
 132 {
 133         struct inode *inode = mapping->host;
 134         loff_t pos = bno << inode->i_blkbits;
 135         unsigned blocksize = i_blocksize(inode);
 136 
 137         if (filemap_write_and_wait(mapping))
 138                 return 0;
 139 
 140         bno = 0;
 141         iomap_apply(inode, pos, blocksize, 0, ops, &bno, iomap_bmap_actor);
 142         return bno;
 143 }
 144 EXPORT_SYMBOL_GPL(iomap_bmap);

/* [<][>][^][v][top][bottom][index][help] */