btrfs-fix.patch 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. From 548386049cd41e887079cdb904d3954365eb28f3 Mon Sep 17 00:00:00 2001
  2. From: Paulo Alcantara <pcacjr@zytor.com>
  3. Date: Thu, 24 Dec 2015 01:48:13 -0200
  4. Subject: [PATCH 1/1] btrfs: Fix logical to physical block address mapping
  5. The current btrfs support did not handled multiple stripes stored in
  6. chunk items, hence skipping the physical addresses that were needed to
  7. do the mapping.
  8. Besides, the chunk tree may contain DEV_ITEM keys which store
  9. information on all of the underlying block devices, so we must skip them
  10. instead of finishing lookup.
  11. The bug was reproduced with btrfs-progs v4.2.2.
  12. Cc: Gene Cumm <gene.cumm@gmail.com>
  13. Cc: H. Peter Anvin <hpa@zytor.com>
  14. Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
  15. ---
  16. v1 -> v2:
  17. * Do not set ignore_key multiple times. Set it before parsing chunk
  18. tree.
  19. v2 -> v3:
  20. * Replace an unnecessary goto with a continue statement.
  21. ---
  22. core/fs/btrfs/btrfs.c | 49 +++++++++++++++++++++++++++++++++----------------
  23. core/fs/btrfs/btrfs.h | 2 ++
  24. 2 files changed, 35 insertions(+), 16 deletions(-)
  25. diff --git a/core/fs/btrfs/btrfs.c b/core/fs/btrfs/btrfs.c
  26. index 53e1105..58e1fe6 100644
  27. --- a/core/fs/btrfs/btrfs.c
  28. +++ b/core/fs/btrfs/btrfs.c
  29. @@ -81,7 +81,8 @@ static int btrfs_comp_chunk_map(struct btrfs_chunk_map_item *m1,
  30. }
  31. /* insert a new chunk mapping item */
  32. -static void insert_map(struct fs_info *fs, struct btrfs_chunk_map_item *item)
  33. +static void insert_chunk_item(struct fs_info *fs,
  34. + struct btrfs_chunk_map_item *item)
  35. {
  36. struct btrfs_info * const bfs = fs->fs_info;
  37. struct btrfs_chunk_map *chunk_map = &bfs->chunk_map;
  38. @@ -113,6 +114,22 @@ static void insert_map(struct fs_info *fs, struct btrfs_chunk_map_item *item)
  39. chunk_map->cur_length++;
  40. }
  41. +static inline void insert_map(struct fs_info *fs, struct btrfs_disk_key *key,
  42. + struct btrfs_chunk *chunk)
  43. +{
  44. + struct btrfs_stripe *stripe = &chunk->stripe;
  45. + struct btrfs_stripe *stripe_end = stripe + chunk->num_stripes;
  46. + struct btrfs_chunk_map_item item;
  47. +
  48. + item.logical = key->offset;
  49. + item.length = chunk->length;
  50. + for ( ; stripe < stripe_end; stripe++) {
  51. + item.devid = stripe->devid;
  52. + item.physical = stripe->offset;
  53. + insert_chunk_item(fs, &item);
  54. + }
  55. +}
  56. +
  57. /*
  58. * from sys_chunk_array or chunk_tree, we can convert a logical address to
  59. * a physical address we can not support multi device case yet
  60. @@ -330,7 +347,6 @@ static int next_slot(struct fs_info *fs, struct btrfs_disk_key *key,
  61. static void btrfs_read_sys_chunk_array(struct fs_info *fs)
  62. {
  63. struct btrfs_info * const bfs = fs->fs_info;
  64. - struct btrfs_chunk_map_item item;
  65. struct btrfs_disk_key *key;
  66. struct btrfs_chunk *chunk;
  67. int cur;
  68. @@ -342,12 +358,7 @@ static void btrfs_read_sys_chunk_array(struct fs_info *fs)
  69. cur += sizeof(*key);
  70. chunk = (struct btrfs_chunk *)(bfs->sb.sys_chunk_array + cur);
  71. cur += btrfs_chunk_item_size(chunk->num_stripes);
  72. - /* insert to mapping table, ignore multi stripes */
  73. - item.logical = key->offset;
  74. - item.length = chunk->length;
  75. - item.devid = chunk->stripe.devid;
  76. - item.physical = chunk->stripe.offset;/*ignore other stripes */
  77. - insert_map(fs, &item);
  78. + insert_map(fs, key, chunk);
  79. }
  80. }
  81. @@ -355,14 +366,18 @@ static void btrfs_read_sys_chunk_array(struct fs_info *fs)
  82. static void btrfs_read_chunk_tree(struct fs_info *fs)
  83. {
  84. struct btrfs_info * const bfs = fs->fs_info;
  85. + struct btrfs_disk_key ignore_key;
  86. struct btrfs_disk_key search_key;
  87. struct btrfs_chunk *chunk;
  88. - struct btrfs_chunk_map_item item;
  89. struct btrfs_path path;
  90. if (!(bfs->sb.flags & BTRFS_SUPER_FLAG_METADUMP)) {
  91. if (bfs->sb.num_devices > 1)
  92. printf("warning: only support single device btrfs\n");
  93. +
  94. + ignore_key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
  95. + ignore_key.type = BTRFS_DEV_ITEM_KEY;
  96. +
  97. /* read chunk from chunk_tree */
  98. search_key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
  99. search_key.type = BTRFS_CHUNK_ITEM_KEY;
  100. @@ -371,16 +386,18 @@ static void btrfs_read_chunk_tree(struct fs_info *fs)
  101. search_tree(fs, bfs->sb.chunk_root, &search_key, &path);
  102. do {
  103. do {
  104. + /* skip information about underlying block
  105. + * devices.
  106. + */
  107. + if (!btrfs_comp_keys_type(&ignore_key,
  108. + &path.item.key))
  109. + continue;
  110. if (btrfs_comp_keys_type(&search_key,
  111. - &path.item.key))
  112. + &path.item.key))
  113. break;
  114. +
  115. chunk = (struct btrfs_chunk *)(path.data);
  116. - /* insert to mapping table, ignore stripes */
  117. - item.logical = path.item.key.offset;
  118. - item.length = chunk->length;
  119. - item.devid = chunk->stripe.devid;
  120. - item.physical = chunk->stripe.offset;
  121. - insert_map(fs, &item);
  122. + insert_map(fs, &path.item.key, chunk);
  123. } while (!next_slot(fs, &search_key, &path));
  124. if (btrfs_comp_keys_type(&search_key, &path.item.key))
  125. break;
  126. diff --git a/core/fs/btrfs/btrfs.h b/core/fs/btrfs/btrfs.h
  127. index 8f519a9..32e7c70 100644
  128. --- a/core/fs/btrfs/btrfs.h
  129. +++ b/core/fs/btrfs/btrfs.h
  130. @@ -56,6 +56,8 @@ typedef u64 __le64;
  131. #define BTRFS_MAX_LEVEL 8
  132. #define BTRFS_MAX_CHUNK_ENTRIES 256
  133. +#define BTRFS_DEV_ITEMS_OBJECTID 1ULL
  134. +
  135. #define BTRFS_FT_REG_FILE 1
  136. #define BTRFS_FT_DIR 2
  137. #define BTRFS_FT_SYMLINK 7
  138. --
  139. 2.5.5.GIT