Skip to content
Permalink
Browse files

Fix: ioctl search: actually use nr_items

Until now, nr_items was put in the search header for the first and each
consecutive search.

Instead, treat it as "I want to get at most this amount of results in
total", and stop returning search results when this amount of objects is
seen.

This also eliminates unnecessary searches:

For example, the block group lookup in the FileSystem object does a
search between (vaddr BLOCK_GROUP_ITEM 0) and (vaddr BLOCK_GROUP_ITEM
ULLONG_MAX) now when searching using only the vaddr. The first result
comes in very quickly (afaics as quickly as when specifying the exact
length in the offset field and searching for the exact key), but even
with nr_items=1 set, it would do another search, starting at offset
length+1 (because of incrementing the search key). This search would
deliver no results, (there's no additional block group on the same
objectid (vaddr). But... that additional search takes much longer. On a
very large (tm) filesystem I have here (>35000 1G data chunks), the
second search takes a minute to return, and reads more than 1 GiB from
disk for some reason.
  • Loading branch information
knorrie committed Jun 21, 2016
1 parent dcf0ef5 commit 5a69d9cf0477515ce2d6e50f1741276a49b33af8
Showing with 6 additions and 2 deletions.
  1. +6 −2 btrfs/ioctl.py
@@ -162,15 +162,16 @@ def search(fd, tree, min_key, max_key=None,
nr_items=ULONG_MAX):
if max_key is None:
max_key = btrfs.ctree.Key(ULLONG_MAX, 255, ULLONG_MAX)
wanted_nr_items = nr_items
result_nr_items = -1
buf = create_buf(4096)
while min_key <= max_key and result_nr_items != 0:
while min_key <= max_key and result_nr_items != 0 and wanted_nr_items > 0:
ioctl_search_key.pack_into(buf, 0, tree,
min_key.objectid, max_key.objectid,
min_key.offset, max_key.offset,
transid_min, transid_max,
min_key.type, max_key.type,
nr_items)
wanted_nr_items)
fcntl.ioctl(fd, IOC_TREE_SEARCH, buf)
result_nr_items = ioctl_search_key.unpack_from(buf, 0)[9]
if result_nr_items > 0:
@@ -181,5 +182,8 @@ def search(fd, tree, min_key, max_key=None,
data = buf[pos:pos+header.len]
yield((header, data))
pos += header.len
wanted_nr_items -= 1
if wanted_nr_items == 0:
break
min_key = btrfs.ctree.Key(header.objectid, header.type, header.offset)
min_key += 1

0 comments on commit 5a69d9c

Please sign in to comment.
You can’t perform that action at this time.