fiemap.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. #include <linux/fiemap.h>
  10. struct fiemap_ctx {
  11. struct fiemap_extent_info *fi;
  12. struct iomap prev;
  13. };
  14. static int iomap_to_fiemap(struct fiemap_extent_info *fi,
  15. struct iomap *iomap, u32 flags)
  16. {
  17. switch (iomap->type) {
  18. case IOMAP_HOLE:
  19. /* skip holes */
  20. return 0;
  21. case IOMAP_DELALLOC:
  22. flags |= FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN;
  23. break;
  24. case IOMAP_MAPPED:
  25. break;
  26. case IOMAP_UNWRITTEN:
  27. flags |= FIEMAP_EXTENT_UNWRITTEN;
  28. break;
  29. case IOMAP_INLINE:
  30. flags |= FIEMAP_EXTENT_DATA_INLINE;
  31. break;
  32. }
  33. if (iomap->flags & IOMAP_F_MERGED)
  34. flags |= FIEMAP_EXTENT_MERGED;
  35. if (iomap->flags & IOMAP_F_SHARED)
  36. flags |= FIEMAP_EXTENT_SHARED;
  37. return fiemap_fill_next_extent(fi, iomap->offset,
  38. iomap->addr != IOMAP_NULL_ADDR ? iomap->addr : 0,
  39. iomap->length, flags);
  40. }
  41. static loff_t
  42. iomap_fiemap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
  43. struct iomap *iomap, struct iomap *srcmap)
  44. {
  45. struct fiemap_ctx *ctx = data;
  46. loff_t ret = length;
  47. if (iomap->type == IOMAP_HOLE)
  48. return length;
  49. ret = iomap_to_fiemap(ctx->fi, &ctx->prev, 0);
  50. ctx->prev = *iomap;
  51. switch (ret) {
  52. case 0: /* success */
  53. return length;
  54. case 1: /* extent array full */
  55. return 0;
  56. default:
  57. return ret;
  58. }
  59. }
  60. int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi,
  61. u64 start, u64 len, const struct iomap_ops *ops)
  62. {
  63. struct fiemap_ctx ctx;
  64. loff_t ret;
  65. memset(&ctx, 0, sizeof(ctx));
  66. ctx.fi = fi;
  67. ctx.prev.type = IOMAP_HOLE;
  68. ret = fiemap_prep(inode, fi, start, &len, 0);
  69. if (ret)
  70. return ret;
  71. while (len > 0) {
  72. ret = iomap_apply(inode, start, len, IOMAP_REPORT, ops, &ctx,
  73. iomap_fiemap_actor);
  74. /* inode with no (attribute) mapping will give ENOENT */
  75. if (ret == -ENOENT)
  76. break;
  77. if (ret < 0)
  78. return ret;
  79. if (ret == 0)
  80. break;
  81. start += ret;
  82. len -= ret;
  83. }
  84. if (ctx.prev.type != IOMAP_HOLE) {
  85. ret = iomap_to_fiemap(fi, &ctx.prev, FIEMAP_EXTENT_LAST);
  86. if (ret < 0)
  87. return ret;
  88. }
  89. return 0;
  90. }
  91. EXPORT_SYMBOL_GPL(iomap_fiemap);
  92. static loff_t
  93. iomap_bmap_actor(struct inode *inode, loff_t pos, loff_t length,
  94. void *data, struct iomap *iomap, struct iomap *srcmap)
  95. {
  96. sector_t *bno = data, addr;
  97. if (iomap->type == IOMAP_MAPPED) {
  98. addr = (pos - iomap->offset + iomap->addr) >> inode->i_blkbits;
  99. *bno = addr;
  100. }
  101. return 0;
  102. }
  103. /* legacy ->bmap interface. 0 is the error return (!) */
  104. sector_t
  105. iomap_bmap(struct address_space *mapping, sector_t bno,
  106. const struct iomap_ops *ops)
  107. {
  108. struct inode *inode = mapping->host;
  109. loff_t pos = bno << inode->i_blkbits;
  110. unsigned blocksize = i_blocksize(inode);
  111. int ret;
  112. if (filemap_write_and_wait(mapping))
  113. return 0;
  114. bno = 0;
  115. ret = iomap_apply(inode, pos, blocksize, 0, ops, &bno,
  116. iomap_bmap_actor);
  117. if (ret)
  118. return 0;
  119. return bno;
  120. }
  121. EXPORT_SYMBOL_GPL(iomap_bmap);