diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2011-03-22 22:43:58 -0400 |
---|---|---|
committer | Li Zefan <lizf@cn.fujitsu.com> | 2011-04-13 02:25:31 -0400 |
commit | b9e03af0bcc11310f6be4a3951c9ee2c26465011 (patch) | |
tree | f7a89518879e38ae460f6b3c2e6cc9a32c7243bc /fs | |
parent | 2e6a00356a066d34cd00872b067589549169ad48 (diff) |
Btrfs: Check if btrfs_next_leaf() returns error in btrfs_real_readdir()
btrfs_next_leaf() can return -errno, and we should propagate
it to userspace.
This also simplifies how we walk the btree path.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/inode.c | 28 |
1 files changed, 10 insertions, 18 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 55a6a0b416d7..b9f7f5258343 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4221,10 +4221,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4221 | struct btrfs_key found_key; | 4221 | struct btrfs_key found_key; |
4222 | struct btrfs_path *path; | 4222 | struct btrfs_path *path; |
4223 | int ret; | 4223 | int ret; |
4224 | u32 nritems; | ||
4225 | struct extent_buffer *leaf; | 4224 | struct extent_buffer *leaf; |
4226 | int slot; | 4225 | int slot; |
4227 | int advance; | ||
4228 | unsigned char d_type; | 4226 | unsigned char d_type; |
4229 | int over = 0; | 4227 | int over = 0; |
4230 | u32 di_cur; | 4228 | u32 di_cur; |
@@ -4267,27 +4265,19 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4267 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 4265 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
4268 | if (ret < 0) | 4266 | if (ret < 0) |
4269 | goto err; | 4267 | goto err; |
4270 | advance = 0; | ||
4271 | 4268 | ||
4272 | while (1) { | 4269 | while (1) { |
4273 | leaf = path->nodes[0]; | 4270 | leaf = path->nodes[0]; |
4274 | nritems = btrfs_header_nritems(leaf); | ||
4275 | slot = path->slots[0]; | 4271 | slot = path->slots[0]; |
4276 | if (advance || slot >= nritems) { | 4272 | if (slot >= btrfs_header_nritems(leaf)) { |
4277 | if (slot >= nritems - 1) { | 4273 | ret = btrfs_next_leaf(root, path); |
4278 | ret = btrfs_next_leaf(root, path); | 4274 | if (ret < 0) |
4279 | if (ret) | 4275 | goto err; |
4280 | break; | 4276 | else if (ret > 0) |
4281 | leaf = path->nodes[0]; | 4277 | break; |
4282 | nritems = btrfs_header_nritems(leaf); | 4278 | continue; |
4283 | slot = path->slots[0]; | ||
4284 | } else { | ||
4285 | slot++; | ||
4286 | path->slots[0]++; | ||
4287 | } | ||
4288 | } | 4279 | } |
4289 | 4280 | ||
4290 | advance = 1; | ||
4291 | item = btrfs_item_nr(leaf, slot); | 4281 | item = btrfs_item_nr(leaf, slot); |
4292 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | 4282 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
4293 | 4283 | ||
@@ -4296,7 +4286,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4296 | if (btrfs_key_type(&found_key) != key_type) | 4286 | if (btrfs_key_type(&found_key) != key_type) |
4297 | break; | 4287 | break; |
4298 | if (found_key.offset < filp->f_pos) | 4288 | if (found_key.offset < filp->f_pos) |
4299 | continue; | 4289 | goto next; |
4300 | 4290 | ||
4301 | filp->f_pos = found_key.offset; | 4291 | filp->f_pos = found_key.offset; |
4302 | 4292 | ||
@@ -4349,6 +4339,8 @@ skip: | |||
4349 | di_cur += di_len; | 4339 | di_cur += di_len; |
4350 | di = (struct btrfs_dir_item *)((char *)di + di_len); | 4340 | di = (struct btrfs_dir_item *)((char *)di + di_len); |
4351 | } | 4341 | } |
4342 | next: | ||
4343 | path->slots[0]++; | ||
4352 | } | 4344 | } |
4353 | 4345 | ||
4354 | /* Reached end of directory/root. Bump pos past the last item. */ | 4346 | /* Reached end of directory/root. Bump pos past the last item. */ |