[Btrfs-devel] Some queries about map_extent_buffer()

Peter Teoh htmldeveloper at gmail.com
Mon Mar 17 04:00:36 PDT 2008


Thanks for the explanation.   But my point is the C statement "continue":

        for (i = start_slot; i < end_slot; i++) {============> start
of loop, "continue" therefore will come here.
                int close = 1;

                if (!parent->map_token) {
                        map_extent_buffer(parent,
                                        btrfs_node_key_ptr_offset(i),
                                        sizeof(struct btrfs_key_ptr),
                                        &parent->map_token, &parent->kaddr,
                                        &parent->map_start, &parent->map_len,
                                        KM_USER1);
                }
                btrfs_node_key(parent, &disk_key, i);
                if (!progress_passed && comp_keys(&disk_key, progress) < 0)
                        continue;==================>for example, this
is executed

                progress_passed = 1;
                blocknr = btrfs_node_blockptr(parent, i);
                if (last_block == 0)
                        last_block = blocknr;

                if (i > 0) {
                        other = btrfs_node_blockptr(parent, i - 1);
                        close = close_blocks(blocknr, other, blocksize);
                }
                if (close && i < end_slot - 2) {
                        other = btrfs_node_blockptr(parent, i + 1);
                        close = close_blocks(blocknr, other, blocksize);
                }
                if (close) {
                        last_block = blocknr;
                        continue;==================>or for example,
this is executed
                }
                if (parent->map_token) {
                        unmap_extent_buffer(parent, parent->map_token,
                                            KM_USER1);
                        parent->map_token = NULL;
                }

                cur = btrfs_find_tree_block(root, blocknr, blocksize);

When the statement "continue" is executed, the next loop will call
map_extent_buffer() again, in addition to the previously called
map_extent_buffer(), with NO unmap_extent_buffer() called in between.

So the result is effectively kmap_atomic() is called twice, without
kunmap_atomic() called.   Is this execution path possible?   Will it
lead to a problem?   I am not sure.


>
>  First, at the end of all of these (that is to say, the end of function
>  btrfs_realloc_node), there is:
>
>
>       if (parent->map_token) {
>           unmap_extent_buffer(parent, parent->map_token,KM_USER1);
>           parent->map_token = NULL;
>       }
>       return err;
>
>  It can make sure that we can call unmap_extent_buffer anyway when we
>  get out of the function (of course, if parent->map_token != NULL).
>
>  Also, at the very beginning of map_extent_buffer, there is :
>
>  if (eb->map_token) {
>         unmap_extent_buffer(eb, eb->map_token, km);
>         eb->map_token = NULL;
>         save = 1;
>  }
>
>  So if we feed a mapped extent buffer into the function, it will unmap
>  it at first, and then call map_private_extent_buffer to map it.
>
>
>  Regards,
>  ZYH
>
>
>
>
>  --
>  - Zhu Yanhai
>



-- 
Regards,
Peter Teoh



More information about the Btrfs-devel mailing list