aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2010-03-18 12:10:08 -0400
committerChris Mason <chris.mason@oracle.com>2010-03-18 12:10:08 -0400
commitabc6e1341bda974e2d0eddb75f57a20ac18e9b33 (patch)
tree399e587e8e94dd4ec2894f52f377a189a21ece2a /fs/btrfs
parent7fde62bffb576d384ea49a3aed3403d5609ee5bc (diff)
Btrfs: fix key checks and advance in the search ioctl
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>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ioctl.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 4329610b141b..291aa51ff420 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -914,17 +914,23 @@ out:
914static noinline int key_in_sk(struct btrfs_key *key, 914static noinline int key_in_sk(struct btrfs_key *key,
915 struct btrfs_ioctl_search_key *sk) 915 struct btrfs_ioctl_search_key *sk)
916{ 916{
917 if (key->objectid < sk->min_objectid) 917 struct btrfs_key test;
918 return 0; 918 int ret;
919 if (key->offset < sk->min_offset) 919
920 return 0; 920 test.objectid = sk->min_objectid;
921 if (key->type < sk->min_type) 921 test.type = sk->min_type;
922 return 0; 922 test.offset = sk->min_offset;
923 if (key->objectid > sk->max_objectid) 923
924 return 0; 924 ret = btrfs_comp_cpu_keys(key, &test);
925 if (key->type > sk->max_type) 925 if (ret < 0)
926 return 0; 926 return 0;
927 if (key->offset > sk->max_offset) 927
928 test.objectid = sk->max_objectid;
929 test.type = sk->max_type;
930 test.offset = sk->max_offset;
931
932 ret = btrfs_comp_cpu_keys(key, &test);
933 if (ret > 0)
928 return 0; 934 return 0;
929 return 1; 935 return 1;
930} 936}
@@ -998,13 +1004,18 @@ static noinline int copy_to_sk(struct btrfs_root *root,
998 break; 1004 break;
999 } 1005 }
1000advance_key: 1006advance_key:
1001 if (key->offset < (u64)-1) 1007 ret = 0;
1008 if (key->offset < (u64)-1 && key->offset < sk->max_offset)
1002 key->offset++; 1009 key->offset++;
1003 else if (key->type < (u8)-1) 1010 else if (key->type < (u8)-1 && key->type < sk->max_type) {
1011 key->offset = 0;
1004 key->type++; 1012 key->type++;
1005 else if (key->objectid < (u64)-1) 1013 } else if (key->objectid < (u64)-1 && key->objectid < sk->max_objectid) {
1014 key->offset = 0;
1015 key->type = 0;
1006 key->objectid++; 1016 key->objectid++;
1007 ret = 0; 1017 } else
1018 ret = 1;
1008overflow: 1019overflow:
1009 *num_found += found; 1020 *num_found += found;
1010 return ret; 1021 return ret;