diff options
author | Liu Bo <liub.liubo@gmail.com> | 2012-09-07 22:01:28 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-10-01 15:19:18 -0400 |
commit | 69917e431210f8712fe050f47b7561e7dae89521 (patch) | |
tree | 52a81d3c70d3a768d2d7756984dd16898ce12e50 | |
parent | dea7d76ecbfb53cda6aadd9bed33e87d255c5b02 (diff) |
Btrfs: fix a bug in parsing return value in logical resolve
In logical resolve, we parse extent_from_logical()'s 'ret' as a kind of flag.
It is possible to lose our errors because
(-EXXXX & BTRFS_EXTENT_FLAG_TREE_BLOCK) is true.
I'm not sure if it is on purpose, it just looks too hacky if it is.
I'd rather use a real flag and a 'ret' to catch errors.
Acked-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Signed-off-by: Liu Bo <liub.liubo@gmail.com>
-rw-r--r-- | fs/btrfs/backref.c | 24 | ||||
-rw-r--r-- | fs/btrfs/backref.h | 3 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 6 | ||||
-rw-r--r-- | fs/btrfs/scrub.c | 14 | ||||
-rw-r--r-- | fs/btrfs/send.c | 7 |
5 files changed, 34 insertions, 20 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index e600857d3ca4..ab286e5bfe33 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -1193,7 +1193,8 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | |||
1193 | * tree blocks and <0 on error. | 1193 | * tree blocks and <0 on error. |
1194 | */ | 1194 | */ |
1195 | int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, | 1195 | int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, |
1196 | struct btrfs_path *path, struct btrfs_key *found_key) | 1196 | struct btrfs_path *path, struct btrfs_key *found_key, |
1197 | u64 *flags_ret) | ||
1197 | { | 1198 | { |
1198 | int ret; | 1199 | int ret; |
1199 | u64 flags; | 1200 | u64 flags; |
@@ -1237,10 +1238,17 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, | |||
1237 | (unsigned long long)found_key->objectid, | 1238 | (unsigned long long)found_key->objectid, |
1238 | (unsigned long long)found_key->offset, | 1239 | (unsigned long long)found_key->offset, |
1239 | (unsigned long long)flags, item_size); | 1240 | (unsigned long long)flags, item_size); |
1240 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) | 1241 | |
1241 | return BTRFS_EXTENT_FLAG_TREE_BLOCK; | 1242 | WARN_ON(!flags_ret); |
1242 | if (flags & BTRFS_EXTENT_FLAG_DATA) | 1243 | if (flags_ret) { |
1243 | return BTRFS_EXTENT_FLAG_DATA; | 1244 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) |
1245 | *flags_ret = BTRFS_EXTENT_FLAG_TREE_BLOCK; | ||
1246 | else if (flags & BTRFS_EXTENT_FLAG_DATA) | ||
1247 | *flags_ret = BTRFS_EXTENT_FLAG_DATA; | ||
1248 | else | ||
1249 | BUG_ON(1); | ||
1250 | return 0; | ||
1251 | } | ||
1244 | 1252 | ||
1245 | return -EIO; | 1253 | return -EIO; |
1246 | } | 1254 | } |
@@ -1433,15 +1441,15 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, | |||
1433 | { | 1441 | { |
1434 | int ret; | 1442 | int ret; |
1435 | u64 extent_item_pos; | 1443 | u64 extent_item_pos; |
1444 | u64 flags = 0; | ||
1436 | struct btrfs_key found_key; | 1445 | struct btrfs_key found_key; |
1437 | int search_commit_root = path->search_commit_root; | 1446 | int search_commit_root = path->search_commit_root; |
1438 | 1447 | ||
1439 | ret = extent_from_logical(fs_info, logical, path, | 1448 | ret = extent_from_logical(fs_info, logical, path, &found_key, &flags); |
1440 | &found_key); | ||
1441 | btrfs_release_path(path); | 1449 | btrfs_release_path(path); |
1442 | if (ret < 0) | 1450 | if (ret < 0) |
1443 | return ret; | 1451 | return ret; |
1444 | if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) | 1452 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) |
1445 | return -EINVAL; | 1453 | return -EINVAL; |
1446 | 1454 | ||
1447 | extent_item_pos = logical - found_key.objectid; | 1455 | extent_item_pos = logical - found_key.objectid; |
diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index 032f4dc7eab8..4fda5d8029a7 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h | |||
@@ -40,7 +40,8 @@ int inode_item_info(u64 inum, u64 ioff, struct btrfs_root *fs_root, | |||
40 | struct btrfs_path *path); | 40 | struct btrfs_path *path); |
41 | 41 | ||
42 | int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, | 42 | int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, |
43 | struct btrfs_path *path, struct btrfs_key *found_key); | 43 | struct btrfs_path *path, struct btrfs_key *found_key, |
44 | u64 *flags); | ||
44 | 45 | ||
45 | int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, | 46 | int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, |
46 | struct btrfs_extent_item *ei, u32 item_size, | 47 | struct btrfs_extent_item *ei, u32 item_size, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index de886ac7ba0f..48ff3f7317b0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -3211,6 +3211,7 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, | |||
3211 | int ret = 0; | 3211 | int ret = 0; |
3212 | int size; | 3212 | int size; |
3213 | u64 extent_item_pos; | 3213 | u64 extent_item_pos; |
3214 | u64 flags = 0; | ||
3214 | struct btrfs_ioctl_logical_ino_args *loi; | 3215 | struct btrfs_ioctl_logical_ino_args *loi; |
3215 | struct btrfs_data_container *inodes = NULL; | 3216 | struct btrfs_data_container *inodes = NULL; |
3216 | struct btrfs_path *path = NULL; | 3217 | struct btrfs_path *path = NULL; |
@@ -3240,10 +3241,11 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, | |||
3240 | goto out; | 3241 | goto out; |
3241 | } | 3242 | } |
3242 | 3243 | ||
3243 | ret = extent_from_logical(root->fs_info, loi->logical, path, &key); | 3244 | ret = extent_from_logical(root->fs_info, loi->logical, path, &key, |
3245 | &flags); | ||
3244 | btrfs_release_path(path); | 3246 | btrfs_release_path(path); |
3245 | 3247 | ||
3246 | if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) | 3248 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) |
3247 | ret = -ENOENT; | 3249 | ret = -ENOENT; |
3248 | if (ret < 0) | 3250 | if (ret < 0) |
3249 | goto out; | 3251 | goto out; |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 4e9eafe01c55..d3bb901ade42 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -352,13 +352,14 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock) | |||
352 | struct extent_buffer *eb; | 352 | struct extent_buffer *eb; |
353 | struct btrfs_extent_item *ei; | 353 | struct btrfs_extent_item *ei; |
354 | struct scrub_warning swarn; | 354 | struct scrub_warning swarn; |
355 | u32 item_size; | 355 | unsigned long ptr = 0; |
356 | int ret; | 356 | u64 extent_item_pos; |
357 | u64 flags = 0; | ||
357 | u64 ref_root; | 358 | u64 ref_root; |
359 | u32 item_size; | ||
358 | u8 ref_level; | 360 | u8 ref_level; |
359 | unsigned long ptr = 0; | ||
360 | const int bufsize = 4096; | 361 | const int bufsize = 4096; |
361 | u64 extent_item_pos; | 362 | int ret; |
362 | 363 | ||
363 | path = btrfs_alloc_path(); | 364 | path = btrfs_alloc_path(); |
364 | 365 | ||
@@ -375,7 +376,8 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock) | |||
375 | if (!path || !swarn.scratch_buf || !swarn.msg_buf) | 376 | if (!path || !swarn.scratch_buf || !swarn.msg_buf) |
376 | goto out; | 377 | goto out; |
377 | 378 | ||
378 | ret = extent_from_logical(fs_info, swarn.logical, path, &found_key); | 379 | ret = extent_from_logical(fs_info, swarn.logical, path, &found_key, |
380 | &flags); | ||
379 | if (ret < 0) | 381 | if (ret < 0) |
380 | goto out; | 382 | goto out; |
381 | 383 | ||
@@ -387,7 +389,7 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock) | |||
387 | item_size = btrfs_item_size_nr(eb, path->slots[0]); | 389 | item_size = btrfs_item_size_nr(eb, path->slots[0]); |
388 | btrfs_release_path(path); | 390 | btrfs_release_path(path); |
389 | 391 | ||
390 | if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) { | 392 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { |
391 | do { | 393 | do { |
392 | ret = tree_backref_for_extent(&ptr, eb, ei, item_size, | 394 | ret = tree_backref_for_extent(&ptr, eb, ei, item_size, |
393 | &ref_root, &ref_level); | 395 | &ref_root, &ref_level); |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index e5c867996aa0..c6ef070a8dca 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -1152,6 +1152,7 @@ static int find_extent_clone(struct send_ctx *sctx, | |||
1152 | u64 disk_byte; | 1152 | u64 disk_byte; |
1153 | u64 num_bytes; | 1153 | u64 num_bytes; |
1154 | u64 extent_item_pos; | 1154 | u64 extent_item_pos; |
1155 | u64 flags = 0; | ||
1155 | struct btrfs_file_extent_item *fi; | 1156 | struct btrfs_file_extent_item *fi; |
1156 | struct extent_buffer *eb = path->nodes[0]; | 1157 | struct extent_buffer *eb = path->nodes[0]; |
1157 | struct backref_ctx *backref_ctx = NULL; | 1158 | struct backref_ctx *backref_ctx = NULL; |
@@ -1198,13 +1199,13 @@ static int find_extent_clone(struct send_ctx *sctx, | |||
1198 | } | 1199 | } |
1199 | logical = disk_byte + btrfs_file_extent_offset(eb, fi); | 1200 | logical = disk_byte + btrfs_file_extent_offset(eb, fi); |
1200 | 1201 | ||
1201 | ret = extent_from_logical(sctx->send_root->fs_info, | 1202 | ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path, |
1202 | disk_byte, tmp_path, &found_key); | 1203 | &found_key, &flags); |
1203 | btrfs_release_path(tmp_path); | 1204 | btrfs_release_path(tmp_path); |
1204 | 1205 | ||
1205 | if (ret < 0) | 1206 | if (ret < 0) |
1206 | goto out; | 1207 | goto out; |
1207 | if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) { | 1208 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { |
1208 | ret = -EIO; | 1209 | ret = -EIO; |
1209 | goto out; | 1210 | goto out; |
1210 | } | 1211 | } |