Skip to content

Commit

Permalink
Btrfs: fix key checks and advance in the search ioctl
Browse files Browse the repository at this point in the history
The search ioctl was working well for finding tree roots, but using it for
generic searches requires a few changes to how the keys are advanced.
This treats the search control min fields for objectid, type and offset
more like a key, where we drop the offset to zero once we bump the type,
etc.

The downside of this is that we are changing the min_type and min_offset
fields during the search, and so the ioctl caller needs extra checks to make sure
the keys in the result are the ones it wanted.

This also changes key_in_sk to use btrfs_comp_cpu_keys, just to make
things more readable.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason committed Mar 18, 2010
1 parent 7fde62b commit abc6e13
Showing 1 changed file with 25 additions and 14 deletions.
39 changes: 25 additions & 14 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,17 +914,23 @@ static noinline int may_destroy_subvol(struct btrfs_root *root)
static noinline int key_in_sk(struct btrfs_key *key,
struct btrfs_ioctl_search_key *sk)
{
if (key->objectid < sk->min_objectid)
return 0;
if (key->offset < sk->min_offset)
return 0;
if (key->type < sk->min_type)
return 0;
if (key->objectid > sk->max_objectid)
return 0;
if (key->type > sk->max_type)
struct btrfs_key test;
int ret;

test.objectid = sk->min_objectid;
test.type = sk->min_type;
test.offset = sk->min_offset;

ret = btrfs_comp_cpu_keys(key, &test);
if (ret < 0)
return 0;
if (key->offset > sk->max_offset)

test.objectid = sk->max_objectid;
test.type = sk->max_type;
test.offset = sk->max_offset;

ret = btrfs_comp_cpu_keys(key, &test);
if (ret > 0)
return 0;
return 1;
}
Expand Down Expand Up @@ -998,13 +1004,18 @@ static noinline int copy_to_sk(struct btrfs_root *root,
break;
}
advance_key:
if (key->offset < (u64)-1)
ret = 0;
if (key->offset < (u64)-1 && key->offset < sk->max_offset)
key->offset++;
else if (key->type < (u8)-1)
else if (key->type < (u8)-1 && key->type < sk->max_type) {
key->offset = 0;
key->type++;
else if (key->objectid < (u64)-1)
} else if (key->objectid < (u64)-1 && key->objectid < sk->max_objectid) {
key->offset = 0;
key->type = 0;
key->objectid++;
ret = 0;
} else
ret = 1;
overflow:
*num_found += found;
return ret;
Expand Down

0 comments on commit abc6e13

Please sign in to comment.