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