2 * Copyright (C) 2014 Fujitsu. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
23 #include "transaction.h"
24 #include "kerncompat.h"
27 * Get the first file extent that covers (part of) the given range
28 * Unlike kernel using extent_map to handle hole even no-hole is enabled,
29 * progs don't have such infrastructure, so caller should do extra care
32 * return 0 for found, and path points to the file extent.
33 * return >0 for not found, and path points to the insert position.
34 * return <0 for error.
36 int btrfs_get_extent(struct btrfs_trans_handle
*trans
,
37 struct btrfs_root
*root
,
38 struct btrfs_path
*path
,
39 u64 ino
, u64 offset
, u64 len
, int ins_len
)
42 struct btrfs_key found_key
;
43 struct btrfs_file_extent_item
*fi_item
;
49 key
.type
= BTRFS_EXTENT_DATA_KEY
;
52 ret
= btrfs_search_slot(trans
, root
, &key
, path
, ins_len
,
57 /* Check previous file extent */
58 ret
= btrfs_previous_item(root
, path
, ino
,
59 BTRFS_EXTENT_DATA_KEY
);
65 btrfs_item_key_to_cpu(path
->nodes
[0], &found_key
, path
->slots
[0]);
66 if (found_key
.objectid
!= ino
||
67 found_key
.type
!= BTRFS_EXTENT_DATA_KEY
)
70 fi_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
71 struct btrfs_file_extent_item
);
72 end
= found_key
.offset
+
73 btrfs_file_extent_ram_bytes(path
->nodes
[0], fi_item
);
75 * existing file extent
88 ret
= btrfs_next_item(root
, path
);
92 btrfs_item_key_to_cpu(path
->nodes
[0], &found_key
, path
->slots
[0]);
93 if (found_key
.objectid
!= ino
||
94 found_key
.type
!= BTRFS_EXTENT_DATA_KEY
) {
98 if (found_key
.offset
< offset
+ len
)
100 * existing file extent
108 * existing file extent
116 * To keep the search behavior consistent with search_slot(),
117 * we need to go back to the prev leaf's nritem slot if
118 * we are at the first slot of the leaf.
120 if (path
->slots
[0] == 0) {
121 ret
= btrfs_prev_leaf(root
, path
);
125 path
->slots
[0] = btrfs_header_nritems(path
->nodes
[0]);
135 * Punch hole ranged [offset,len) for the file given by ino and root.
137 * Unlink kernel punch_hole, which will not zero/free existing extent,
138 * instead it will return -EEXIST if there is any extents in the hole
141 int btrfs_punch_hole(struct btrfs_trans_handle
*trans
,
142 struct btrfs_root
*root
,
143 u64 ino
, u64 offset
, u64 len
)
145 struct btrfs_path
*path
;
148 path
= btrfs_alloc_path();
152 ret
= btrfs_get_extent(NULL
, root
, path
, ino
, offset
, len
, 0);
160 ret
= btrfs_insert_file_extent(trans
, root
, ino
, offset
, 0, 0, len
);
162 btrfs_free_path(path
);
167 * Read out content of one inode.
169 * @root: fs/subvolume root containing the inode
171 * @start: offset inside the file, aligned to sectorsize
172 * @len: length to read, aligned to sectorisize
173 * @dest: where data will be stored
176 * 1) compression data is not supported yet
177 * 2) @start and @len must be aligned to sectorsize
178 * 3) data read out is also aligned to sectorsize, not truncated to inode size
180 * Return < 0 for fatal error during read.
181 * Otherwise return the number of succesfully read data in bytes.
183 int btrfs_read_file(struct btrfs_root
*root
, u64 ino
, u64 start
, int len
,
186 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
187 struct btrfs_key key
;
188 struct btrfs_path path
;
189 struct extent_buffer
*leaf
;
190 struct btrfs_inode_item
*ii
;
192 int no_holes
= btrfs_fs_incompat(fs_info
, NO_HOLES
);
197 if (!IS_ALIGNED(start
, fs_info
->sectorsize
) ||
198 !IS_ALIGNED(len
, fs_info
->sectorsize
)) {
199 warning("@start and @len must be aligned to %u for function %s",
200 fs_info
->sectorsize
, __func__
);
204 btrfs_init_path(&path
);
207 key
.type
= BTRFS_EXTENT_DATA_KEY
;
209 ret
= btrfs_search_slot(NULL
, root
, &key
, &path
, 0, 0);
214 ret
= btrfs_previous_item(root
, &path
, ino
, BTRFS_EXTENT_DATA_KEY
);
222 * Reset @dest to all 0, so we don't need to care about holes in
223 * no_hole mode, but focus on reading non-hole part.
225 memset(dest
, 0, len
);
227 struct btrfs_file_extent_item
*fi
;
235 leaf
= path
.nodes
[0];
236 slot
= path
.slots
[0];
238 btrfs_item_key_to_cpu(leaf
, &key
, slot
);
239 if (key
.objectid
> ino
)
241 if (key
.type
!= BTRFS_EXTENT_DATA_KEY
|| key
.objectid
!= ino
)
244 extent_start
= key
.offset
;
245 if (extent_start
>= start
+ len
)
248 fi
= btrfs_item_ptr(leaf
, slot
, struct btrfs_file_extent_item
);
249 if (btrfs_file_extent_compression(leaf
, fi
) !=
250 BTRFS_COMPRESS_NONE
) {
255 /* Inline extent, one inode should only one inline extent */
256 if (btrfs_file_extent_type(leaf
, fi
) ==
257 BTRFS_FILE_EXTENT_INLINE
) {
258 extent_len
= btrfs_file_extent_inline_len(leaf
, slot
,
260 if (extent_start
+ extent_len
<= start
)
262 read_extent_buffer(leaf
, dest
,
263 btrfs_file_extent_inline_start(fi
), extent_len
);
264 read
+= round_up(extent_len
, fs_info
->sectorsize
);
268 extent_len
= btrfs_file_extent_num_bytes(leaf
, fi
);
269 if (extent_start
+ extent_len
<= start
)
272 read_start
= max(start
, extent_start
);
273 read_len
= min(start
+ len
, extent_start
+ extent_len
) -
276 /* We have already zeroed @dest, nothing to do */
277 if (btrfs_file_extent_type(leaf
, fi
) ==
278 BTRFS_FILE_EXTENT_PREALLOC
||
279 btrfs_file_extent_disk_num_bytes(leaf
, fi
) == 0) {
284 disk_bytenr
= btrfs_file_extent_disk_bytenr(leaf
, fi
) +
285 btrfs_file_extent_offset(leaf
, fi
);
286 read_len_ret
= read_len
;
287 ret
= read_extent_data(fs_info
, dest
+ read_start
- start
, disk_bytenr
,
291 /* Short read, something went wrong */
292 if (read_len_ret
!= read_len
)
296 ret
= btrfs_next_item(root
, &path
);
304 * Special trick for no_holes, since for no_holes we don't have good
305 * method to account skipped and tailling holes, we used
306 * min(inode size, len) as return value
309 btrfs_release_path(&path
);
312 key
.type
= BTRFS_INODE_ITEM_KEY
;
313 ret
= btrfs_lookup_inode(NULL
, root
, &path
, &key
, 0);
320 ii
= btrfs_item_ptr(path
.nodes
[0], path
.slots
[0],
321 struct btrfs_inode_item
);
322 isize
= round_up(btrfs_inode_size(path
.nodes
[0], ii
),
323 fs_info
->sectorsize
);
324 read
= min_t(u64
, isize
- start
, len
);
327 btrfs_release_path(&path
);