[Btrfs-devel] Some queries about map_extent_buffer()

Peter Teoh htmldeveloper at gmail.com
Sun Mar 16 16:47:13 PDT 2008


In many parts of code map_extent_buffer() return value is not handled.
  What is this function doing?   Essentially calling kmap_atomic()
using the KM_USER1 memory, right?   This memory is only one page in
size, and so it may failed easily?

                        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);

Personally, I don't think this API is wise to use kmap_atomic(), as in
many parts of kernel codes, in between kmap_ and kunmap_ it is just a
few instructions from each other.   But here I can see like this:

ctree.c:

                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;

                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;
                }
                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);

So problems like leakage can easily occurred.   For example, after the
map_extent_buffer(), followed by the "continue", the
unmap_extent_buffer() will not be called, a problem???? I am not sure,
as I don't fully understand the code yet :-).   (And the
map_extent_buffer will be called again, using KM_USER1, without the
previous one being unmap?).



-- 
Regards,
Peter Teoh



More information about the Btrfs-devel mailing list