inode.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * BTRFS filesystem implementation for U-Boot
  4. *
  5. * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
  6. */
  7. #include <linux/kernel.h>
  8. #include <malloc.h>
  9. #include <memalign.h>
  10. #include "btrfs.h"
  11. #include "disk-io.h"
  12. #include "volumes.h"
  13. /*
  14. * Read the content of symlink inode @ino of @root, into @target.
  15. * NOTE: @target will not be \0 termiated, caller should handle it properly.
  16. *
  17. * Return the number of read data.
  18. * Return <0 for error.
  19. */
  20. int btrfs_readlink(struct btrfs_root *root, u64 ino, char *target)
  21. {
  22. struct btrfs_path path;
  23. struct btrfs_key key;
  24. struct btrfs_file_extent_item *fi;
  25. int ret;
  26. key.objectid = ino;
  27. key.type = BTRFS_EXTENT_DATA_KEY;
  28. key.offset = 0;
  29. btrfs_init_path(&path);
  30. ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
  31. if (ret < 0)
  32. return ret;
  33. if (ret > 0) {
  34. ret = -ENOENT;
  35. goto out;
  36. }
  37. fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
  38. struct btrfs_file_extent_item);
  39. if (btrfs_file_extent_type(path.nodes[0], fi) !=
  40. BTRFS_FILE_EXTENT_INLINE) {
  41. ret = -EUCLEAN;
  42. error("Extent for symlink %llu must be INLINE type!", ino);
  43. goto out;
  44. }
  45. if (btrfs_file_extent_compression(path.nodes[0], fi) !=
  46. BTRFS_COMPRESS_NONE) {
  47. ret = -EUCLEAN;
  48. error("Extent for symlink %llu must not be compressed!", ino);
  49. goto out;
  50. }
  51. if (btrfs_file_extent_ram_bytes(path.nodes[0], fi) >=
  52. root->fs_info->sectorsize) {
  53. ret = -EUCLEAN;
  54. error("Symlink %llu extent data too large (%llu)!\n",
  55. ino, btrfs_file_extent_ram_bytes(path.nodes[0], fi));
  56. goto out;
  57. }
  58. read_extent_buffer(path.nodes[0], target,
  59. btrfs_file_extent_inline_start(fi),
  60. btrfs_file_extent_ram_bytes(path.nodes[0], fi));
  61. ret = btrfs_file_extent_ram_bytes(path.nodes[0], fi);
  62. out:
  63. btrfs_release_path(&path);
  64. return ret;
  65. }
  66. static int lookup_root_ref(struct btrfs_fs_info *fs_info,
  67. u64 rootid, u64 *root_ret, u64 *dir_ret)
  68. {
  69. struct btrfs_root *root = fs_info->tree_root;
  70. struct btrfs_root_ref *root_ref;
  71. struct btrfs_path path;
  72. struct btrfs_key key;
  73. int ret;
  74. btrfs_init_path(&path);
  75. key.objectid = rootid;
  76. key.type = BTRFS_ROOT_BACKREF_KEY;
  77. key.offset = (u64)-1;
  78. ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
  79. if (ret < 0)
  80. return ret;
  81. /* Should not happen */
  82. if (ret == 0) {
  83. ret = -EUCLEAN;
  84. goto out;
  85. }
  86. ret = btrfs_previous_item(root, &path, rootid, BTRFS_ROOT_BACKREF_KEY);
  87. if (ret < 0)
  88. goto out;
  89. if (ret > 0) {
  90. ret = -ENOENT;
  91. goto out;
  92. }
  93. btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
  94. root_ref = btrfs_item_ptr(path.nodes[0], path.slots[0],
  95. struct btrfs_root_ref);
  96. *root_ret = key.offset;
  97. *dir_ret = btrfs_root_ref_dirid(path.nodes[0], root_ref);
  98. out:
  99. btrfs_release_path(&path);
  100. return ret;
  101. }
  102. /*
  103. * To get the parent inode of @ino of @root.
  104. *
  105. * @root_ret and @ino_ret will be filled.
  106. *
  107. * NOTE: This function is not reliable. It can only get one parent inode.
  108. * The get the proper parent inode, we need a full VFS inodes stack to
  109. * resolve properly.
  110. */
  111. static int get_parent_inode(struct btrfs_root *root, u64 ino,
  112. struct btrfs_root **root_ret, u64 *ino_ret)
  113. {
  114. struct btrfs_fs_info *fs_info = root->fs_info;
  115. struct btrfs_path path;
  116. struct btrfs_key key;
  117. int ret;
  118. if (ino == BTRFS_FIRST_FREE_OBJECTID) {
  119. u64 parent_root = -1;
  120. /* It's top level already, no more parent */
  121. if (root->root_key.objectid == BTRFS_FS_TREE_OBJECTID) {
  122. *root_ret = fs_info->fs_root;
  123. *ino_ret = BTRFS_FIRST_FREE_OBJECTID;
  124. return 0;
  125. }
  126. ret = lookup_root_ref(fs_info, root->root_key.objectid,
  127. &parent_root, ino_ret);
  128. if (ret < 0)
  129. return ret;
  130. key.objectid = parent_root;
  131. key.type = BTRFS_ROOT_ITEM_KEY;
  132. key.offset = (u64)-1;
  133. *root_ret = btrfs_read_fs_root(fs_info, &key);
  134. if (IS_ERR(*root_ret))
  135. return PTR_ERR(*root_ret);
  136. return 0;
  137. }
  138. btrfs_init_path(&path);
  139. key.objectid = ino;
  140. key.type = BTRFS_INODE_REF_KEY;
  141. key.offset = (u64)-1;
  142. ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
  143. if (ret < 0)
  144. return ret;
  145. /* Should not happen */
  146. if (ret == 0) {
  147. ret = -EUCLEAN;
  148. goto out;
  149. }
  150. ret = btrfs_previous_item(root, &path, ino, BTRFS_INODE_REF_KEY);
  151. if (ret < 0)
  152. goto out;
  153. if (ret > 0) {
  154. ret = -ENOENT;
  155. goto out;
  156. }
  157. btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
  158. *root_ret = root;
  159. *ino_ret = key.offset;
  160. out:
  161. btrfs_release_path(&path);
  162. return ret;
  163. }
  164. static inline int next_length(const char *path)
  165. {
  166. int res = 0;
  167. while (*path != '\0' && *path != '/') {
  168. ++res;
  169. ++path;
  170. if (res > BTRFS_NAME_LEN)
  171. break;
  172. }
  173. return res;
  174. }
  175. static inline const char *skip_current_directories(const char *cur)
  176. {
  177. while (1) {
  178. if (cur[0] == '/')
  179. ++cur;
  180. else if (cur[0] == '.' && cur[1] == '/')
  181. cur += 2;
  182. else
  183. break;
  184. }
  185. return cur;
  186. }
  187. /*
  188. * Resolve one filename of @ino of @root.
  189. *
  190. * key_ret: The child key (either INODE_ITEM or ROOT_ITEM type)
  191. * type_ret: BTRFS_FT_* of the child inode.
  192. *
  193. * Return 0 with above members filled.
  194. * Return <0 for error.
  195. */
  196. static int resolve_one_filename(struct btrfs_root *root, u64 ino,
  197. const char *name, int namelen,
  198. struct btrfs_key *key_ret, u8 *type_ret)
  199. {
  200. struct btrfs_dir_item *dir_item;
  201. struct btrfs_path path;
  202. int ret = 0;
  203. btrfs_init_path(&path);
  204. dir_item = btrfs_lookup_dir_item(NULL, root, &path, ino, name,
  205. namelen, 0);
  206. if (IS_ERR(dir_item)) {
  207. ret = PTR_ERR(dir_item);
  208. goto out;
  209. }
  210. btrfs_dir_item_key_to_cpu(path.nodes[0], dir_item, key_ret);
  211. *type_ret = btrfs_dir_type(path.nodes[0], dir_item);
  212. out:
  213. btrfs_release_path(&path);
  214. return ret;
  215. }
  216. /*
  217. * Resolve a full path @filename. The start point is @ino of @root.
  218. *
  219. * The result will be filled into @root_ret, @ino_ret and @type_ret.
  220. */
  221. int btrfs_lookup_path(struct btrfs_root *root, u64 ino, const char *filename,
  222. struct btrfs_root **root_ret, u64 *ino_ret,
  223. u8 *type_ret, int symlink_limit)
  224. {
  225. struct btrfs_fs_info *fs_info = root->fs_info;
  226. struct btrfs_root *next_root;
  227. struct btrfs_key key;
  228. const char *cur = filename;
  229. u64 next_ino;
  230. u8 next_type;
  231. u8 type;
  232. int len;
  233. int ret = 0;
  234. /* If the path is absolute path, also search from fs root */
  235. if (*cur == '/') {
  236. root = fs_info->fs_root;
  237. ino = btrfs_root_dirid(&root->root_item);
  238. type = BTRFS_FT_DIR;
  239. }
  240. while (*cur != '\0') {
  241. cur = skip_current_directories(cur);
  242. len = next_length(cur);
  243. if (len > BTRFS_NAME_LEN) {
  244. error("%s: Name too long at \"%.*s\"", __func__,
  245. BTRFS_NAME_LEN, cur);
  246. return -ENAMETOOLONG;
  247. }
  248. if (len == 1 && cur[0] == '.')
  249. break;
  250. if (len == 2 && cur[0] == '.' && cur[1] == '.') {
  251. /* Go one level up */
  252. ret = get_parent_inode(root, ino, &next_root, &next_ino);
  253. if (ret < 0)
  254. return ret;
  255. root = next_root;
  256. ino = next_ino;
  257. goto next;
  258. }
  259. if (!*cur)
  260. break;
  261. ret = resolve_one_filename(root, ino, cur, len, &key, &type);
  262. if (ret < 0)
  263. return ret;
  264. if (key.type == BTRFS_ROOT_ITEM_KEY) {
  265. /* Child inode is a subvolume */
  266. next_root = btrfs_read_fs_root(fs_info, &key);
  267. if (IS_ERR(next_root))
  268. return PTR_ERR(next_root);
  269. root = next_root;
  270. ino = btrfs_root_dirid(&root->root_item);
  271. } else if (type == BTRFS_FT_SYMLINK && symlink_limit >= 0) {
  272. /* Child inode is a symlink */
  273. char *target;
  274. if (symlink_limit == 0) {
  275. error("%s: Too much symlinks!", __func__);
  276. return -EMLINK;
  277. }
  278. target = malloc(fs_info->sectorsize);
  279. if (!target)
  280. return -ENOMEM;
  281. ret = btrfs_readlink(root, key.objectid, target);
  282. if (ret < 0) {
  283. free(target);
  284. return ret;
  285. }
  286. target[ret] = '\0';
  287. ret = btrfs_lookup_path(root, ino, target, &next_root,
  288. &next_ino, &next_type,
  289. symlink_limit);
  290. if (ret < 0)
  291. return ret;
  292. root = next_root;
  293. ino = next_ino;
  294. type = next_type;
  295. } else {
  296. /* Child inode is an inode */
  297. ino = key.objectid;
  298. }
  299. next:
  300. cur += len;
  301. }
  302. if (!ret) {
  303. *root_ret = root;
  304. *ino_ret = ino;
  305. *type_ret = type;
  306. }
  307. return ret;
  308. }
  309. /*
  310. * Read out inline extent.
  311. *
  312. * Since inline extent should only exist for offset 0, no need for extra
  313. * parameters.
  314. * Truncating should be handled by the caller.
  315. *
  316. * Return the number of bytes read.
  317. * Return <0 for error.
  318. */
  319. int btrfs_read_extent_inline(struct btrfs_path *path,
  320. struct btrfs_file_extent_item *fi, char *dest)
  321. {
  322. struct extent_buffer *leaf = path->nodes[0];
  323. int slot = path->slots[0];
  324. char *cbuf = NULL;
  325. char *dbuf = NULL;
  326. u32 csize;
  327. u32 dsize;
  328. int ret;
  329. csize = btrfs_file_extent_inline_item_len(leaf, btrfs_item_nr(slot));
  330. if (btrfs_file_extent_compression(leaf, fi) == BTRFS_COMPRESS_NONE) {
  331. /* Uncompressed, just read it out */
  332. read_extent_buffer(leaf, dest,
  333. btrfs_file_extent_inline_start(fi),
  334. csize);
  335. return csize;
  336. }
  337. /* Compressed extent, prepare the compressed and data buffer */
  338. dsize = btrfs_file_extent_ram_bytes(leaf, fi);
  339. cbuf = malloc(csize);
  340. dbuf = malloc(dsize);
  341. if (!cbuf || !dbuf) {
  342. ret = -ENOMEM;
  343. goto out;
  344. }
  345. read_extent_buffer(leaf, cbuf, btrfs_file_extent_inline_start(fi),
  346. csize);
  347. ret = btrfs_decompress(btrfs_file_extent_compression(leaf, fi),
  348. cbuf, csize, dbuf, dsize);
  349. if (ret < 0 || ret != dsize) {
  350. ret = -EIO;
  351. goto out;
  352. }
  353. memcpy(dest, dbuf, dsize);
  354. ret = dsize;
  355. out:
  356. free(cbuf);
  357. free(dbuf);
  358. return ret;
  359. }
  360. /*
  361. * Read out regular extent.
  362. *
  363. * Truncating should be handled by the caller.
  364. *
  365. * @offset and @len should not cross the extent boundary.
  366. * Return the number of bytes read.
  367. * Return <0 for error.
  368. */
  369. int btrfs_read_extent_reg(struct btrfs_path *path,
  370. struct btrfs_file_extent_item *fi, u64 offset,
  371. int len, char *dest)
  372. {
  373. struct extent_buffer *leaf = path->nodes[0];
  374. struct btrfs_fs_info *fs_info = leaf->fs_info;
  375. struct btrfs_key key;
  376. u64 extent_num_bytes;
  377. u64 disk_bytenr;
  378. u64 read;
  379. char *cbuf = NULL;
  380. char *dbuf = NULL;
  381. u32 csize;
  382. u32 dsize;
  383. bool finished = false;
  384. int num_copies;
  385. int i;
  386. int slot = path->slots[0];
  387. int ret;
  388. btrfs_item_key_to_cpu(leaf, &key, slot);
  389. extent_num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
  390. ASSERT(IS_ALIGNED(offset, fs_info->sectorsize) &&
  391. IS_ALIGNED(len, fs_info->sectorsize));
  392. ASSERT(offset >= key.offset &&
  393. offset + len <= key.offset + extent_num_bytes);
  394. /* Preallocated or hole , fill @dest with zero */
  395. if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_PREALLOC ||
  396. btrfs_file_extent_disk_bytenr(leaf, fi) == 0) {
  397. memset(dest, 0, len);
  398. return len;
  399. }
  400. if (btrfs_file_extent_compression(leaf, fi) == BTRFS_COMPRESS_NONE) {
  401. u64 logical;
  402. logical = btrfs_file_extent_disk_bytenr(leaf, fi) +
  403. btrfs_file_extent_offset(leaf, fi) +
  404. offset - key.offset;
  405. read = len;
  406. num_copies = btrfs_num_copies(fs_info, logical, len);
  407. for (i = 1; i <= num_copies; i++) {
  408. ret = read_extent_data(fs_info, dest, logical, &read, i);
  409. if (ret < 0 || read != len)
  410. continue;
  411. finished = true;
  412. break;
  413. }
  414. if (!finished)
  415. return -EIO;
  416. return len;
  417. }
  418. csize = btrfs_file_extent_disk_num_bytes(leaf, fi);
  419. dsize = btrfs_file_extent_ram_bytes(leaf, fi);
  420. disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
  421. num_copies = btrfs_num_copies(fs_info, disk_bytenr, csize);
  422. cbuf = malloc_cache_aligned(csize);
  423. dbuf = malloc_cache_aligned(dsize);
  424. if (!cbuf || !dbuf) {
  425. ret = -ENOMEM;
  426. goto out;
  427. }
  428. /* For compressed extent, we must read the whole on-disk extent */
  429. for (i = 1; i <= num_copies; i++) {
  430. read = csize;
  431. ret = read_extent_data(fs_info, cbuf, disk_bytenr,
  432. &read, i);
  433. if (ret < 0 || read != csize)
  434. continue;
  435. finished = true;
  436. break;
  437. }
  438. if (!finished) {
  439. ret = -EIO;
  440. goto out;
  441. }
  442. ret = btrfs_decompress(btrfs_file_extent_compression(leaf, fi), cbuf,
  443. csize, dbuf, dsize);
  444. if (ret != dsize) {
  445. ret = -EIO;
  446. goto out;
  447. }
  448. /* Then copy the needed part */
  449. memcpy(dest, dbuf + btrfs_file_extent_offset(leaf, fi), len);
  450. ret = len;
  451. out:
  452. free(cbuf);
  453. free(dbuf);
  454. return ret;
  455. }
  456. /*
  457. * Get the first file extent that covers bytenr @file_offset.
  458. *
  459. * @file_offset must be aligned to sectorsize.
  460. *
  461. * return 0 for found, and path points to the file extent.
  462. * return >0 for not found, and fill @next_offset.
  463. * @next_offset can be 0 if there is no next file extent.
  464. * return <0 for error.
  465. */
  466. static int lookup_data_extent(struct btrfs_root *root, struct btrfs_path *path,
  467. u64 ino, u64 file_offset, u64 *next_offset)
  468. {
  469. struct btrfs_key key;
  470. struct btrfs_file_extent_item *fi;
  471. u8 extent_type;
  472. int ret = 0;
  473. ASSERT(IS_ALIGNED(file_offset, root->fs_info->sectorsize));
  474. key.objectid = ino;
  475. key.type = BTRFS_EXTENT_DATA_KEY;
  476. key.offset = file_offset;
  477. ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  478. /* Error or we're already at the file extent */
  479. if (ret <= 0)
  480. return ret;
  481. if (ret > 0) {
  482. /* Check previous file extent */
  483. ret = btrfs_previous_item(root, path, ino,
  484. BTRFS_EXTENT_DATA_KEY);
  485. if (ret < 0)
  486. return ret;
  487. if (ret > 0)
  488. goto check_next;
  489. }
  490. /* Now the key.offset must be smaller than @file_offset */
  491. btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
  492. if (key.objectid != ino ||
  493. key.type != BTRFS_EXTENT_DATA_KEY)
  494. goto check_next;
  495. fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
  496. struct btrfs_file_extent_item);
  497. extent_type = btrfs_file_extent_type(path->nodes[0], fi);
  498. if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
  499. if (file_offset == 0)
  500. return 0;
  501. /* Inline extent should be the only extent, no next extent. */
  502. *next_offset = 0;
  503. return 1;
  504. }
  505. /* This file extent covers @file_offset */
  506. if (key.offset <= file_offset && key.offset +
  507. btrfs_file_extent_num_bytes(path->nodes[0], fi) > file_offset)
  508. return 0;
  509. check_next:
  510. ret = btrfs_next_item(root, path);
  511. if (ret < 0)
  512. return ret;
  513. if (ret > 0) {
  514. *next_offset = 0;
  515. return 1;
  516. }
  517. btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
  518. fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
  519. struct btrfs_file_extent_item);
  520. /* Next next data extent */
  521. if (key.objectid != ino ||
  522. key.type != BTRFS_EXTENT_DATA_KEY) {
  523. *next_offset = 0;
  524. return 1;
  525. }
  526. /* Current file extent already beyond @file_offset */
  527. if (key.offset > file_offset) {
  528. *next_offset = key.offset;
  529. return 1;
  530. }
  531. /* This file extent covers @file_offset */
  532. if (key.offset <= file_offset && key.offset +
  533. btrfs_file_extent_num_bytes(path->nodes[0], fi) > file_offset)
  534. return 0;
  535. /* This file extent ends before @file_offset, check next */
  536. ret = btrfs_next_item(root, path);
  537. if (ret < 0)
  538. return ret;
  539. if (ret > 0) {
  540. *next_offset = 0;
  541. return 1;
  542. }
  543. btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
  544. if (key.type != BTRFS_EXTENT_DATA_KEY || key.objectid != ino) {
  545. *next_offset = 0;
  546. return 1;
  547. }
  548. *next_offset = key.offset;
  549. return 1;
  550. }
  551. static int read_and_truncate_page(struct btrfs_path *path,
  552. struct btrfs_file_extent_item *fi,
  553. int start, int len, char *dest)
  554. {
  555. struct extent_buffer *leaf = path->nodes[0];
  556. struct btrfs_fs_info *fs_info = leaf->fs_info;
  557. u64 aligned_start = round_down(start, fs_info->sectorsize);
  558. u8 extent_type;
  559. char *buf;
  560. int page_off = start - aligned_start;
  561. int page_len = fs_info->sectorsize - page_off;
  562. int ret;
  563. ASSERT(start + len <= aligned_start + fs_info->sectorsize);
  564. buf = malloc_cache_aligned(fs_info->sectorsize);
  565. if (!buf)
  566. return -ENOMEM;
  567. extent_type = btrfs_file_extent_type(leaf, fi);
  568. if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
  569. ret = btrfs_read_extent_inline(path, fi, buf);
  570. memcpy(dest, buf + page_off, min(page_len, ret));
  571. free(buf);
  572. return len;
  573. }
  574. ret = btrfs_read_extent_reg(path, fi,
  575. round_down(start, fs_info->sectorsize),
  576. fs_info->sectorsize, buf);
  577. if (ret < 0) {
  578. free(buf);
  579. return ret;
  580. }
  581. memcpy(dest, buf + page_off, page_len);
  582. free(buf);
  583. return len;
  584. }
  585. int btrfs_file_read(struct btrfs_root *root, u64 ino, u64 file_offset, u64 len,
  586. char *dest)
  587. {
  588. struct btrfs_fs_info *fs_info = root->fs_info;
  589. struct btrfs_file_extent_item *fi;
  590. struct btrfs_path path;
  591. struct btrfs_key key;
  592. u64 aligned_start = round_down(file_offset, fs_info->sectorsize);
  593. u64 aligned_end = round_down(file_offset + len, fs_info->sectorsize);
  594. u64 next_offset;
  595. u64 cur = aligned_start;
  596. int ret = 0;
  597. btrfs_init_path(&path);
  598. /* Set the whole dest all zero, so we won't need to bother holes */
  599. memset(dest, 0, len);
  600. /* Read out the leading unaligned part */
  601. if (aligned_start != file_offset) {
  602. ret = lookup_data_extent(root, &path, ino, aligned_start,
  603. &next_offset);
  604. if (ret < 0)
  605. goto out;
  606. if (ret == 0) {
  607. /* Read the unaligned part out*/
  608. fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
  609. struct btrfs_file_extent_item);
  610. ret = read_and_truncate_page(&path, fi, file_offset,
  611. round_up(file_offset, fs_info->sectorsize) -
  612. file_offset, dest);
  613. if (ret < 0)
  614. goto out;
  615. cur += fs_info->sectorsize;
  616. } else {
  617. /* The whole file is a hole */
  618. if (!next_offset) {
  619. memset(dest, 0, len);
  620. return len;
  621. }
  622. cur = next_offset;
  623. }
  624. }
  625. /* Read the aligned part */
  626. while (cur < aligned_end) {
  627. u64 extent_num_bytes;
  628. u8 type;
  629. btrfs_release_path(&path);
  630. ret = lookup_data_extent(root, &path, ino, cur, &next_offset);
  631. if (ret < 0)
  632. goto out;
  633. if (ret > 0) {
  634. /* No next, direct exit */
  635. if (!next_offset) {
  636. ret = 0;
  637. goto out;
  638. }
  639. }
  640. fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
  641. struct btrfs_file_extent_item);
  642. btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
  643. type = btrfs_file_extent_type(path.nodes[0], fi);
  644. if (type == BTRFS_FILE_EXTENT_INLINE) {
  645. ret = btrfs_read_extent_inline(&path, fi, dest);
  646. goto out;
  647. }
  648. /* Skip holes, as we have zeroed the dest */
  649. if (type == BTRFS_FILE_EXTENT_PREALLOC ||
  650. btrfs_file_extent_disk_bytenr(path.nodes[0], fi) == 0) {
  651. cur = key.offset + btrfs_file_extent_num_bytes(
  652. path.nodes[0], fi);
  653. continue;
  654. }
  655. /* Read the remaining part of the extent */
  656. extent_num_bytes = btrfs_file_extent_num_bytes(path.nodes[0],
  657. fi);
  658. ret = btrfs_read_extent_reg(&path, fi, cur,
  659. min(extent_num_bytes, aligned_end - cur),
  660. dest + cur - file_offset);
  661. if (ret < 0)
  662. goto out;
  663. cur += min(extent_num_bytes, aligned_end - cur);
  664. }
  665. /* Read the tailing unaligned part*/
  666. if (file_offset + len != aligned_end) {
  667. btrfs_release_path(&path);
  668. ret = lookup_data_extent(root, &path, ino, aligned_end,
  669. &next_offset);
  670. /* <0 is error, >0 means no extent */
  671. if (ret)
  672. goto out;
  673. fi = btrfs_item_ptr(path.nodes[0], path.slots[0],
  674. struct btrfs_file_extent_item);
  675. ret = read_and_truncate_page(&path, fi, aligned_end,
  676. file_offset + len - aligned_end,
  677. dest + aligned_end - file_offset);
  678. }
  679. out:
  680. btrfs_release_path(&path);
  681. if (ret < 0)
  682. return ret;
  683. return len;
  684. }