diff options
author | Alex Elder <elder@inktank.com> | 2013-05-01 13:43:03 -0400 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2013-05-02 12:58:17 -0400 |
commit | 30d1cff817808fca9801c743d2de4c61f3f38e15 (patch) | |
tree | b6944042ba2919676bd13ebf84c412b04854f00e /drivers/block | |
parent | 15228ede7d9437b0dcfe9331c9830b3646fdadf7 (diff) |
rbd: use binary search for snapshot lookup
Use bsearch(3) to make snapshot lookup by id more efficient. (There
could be thousands of snapshots, and conceivably many more.)
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/rbd.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 3f58aba6461f..82d9586a4172 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/ceph/mon_client.h> | 33 | #include <linux/ceph/mon_client.h> |
34 | #include <linux/ceph/decode.h> | 34 | #include <linux/ceph/decode.h> |
35 | #include <linux/parser.h> | 35 | #include <linux/parser.h> |
36 | #include <linux/bsearch.h> | ||
36 | 37 | ||
37 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
38 | #include <linux/device.h> | 39 | #include <linux/device.h> |
@@ -819,16 +820,39 @@ static const char *_rbd_dev_v1_snap_name(struct rbd_device *rbd_dev, u32 which) | |||
819 | return kstrdup(snap_name, GFP_KERNEL); | 820 | return kstrdup(snap_name, GFP_KERNEL); |
820 | } | 821 | } |
821 | 822 | ||
823 | /* | ||
824 | * Snapshot id comparison function for use with qsort()/bsearch(). | ||
825 | * Note that result is for snapshots in *descending* order. | ||
826 | */ | ||
827 | static int snapid_compare_reverse(const void *s1, const void *s2) | ||
828 | { | ||
829 | u64 snap_id1 = *(u64 *)s1; | ||
830 | u64 snap_id2 = *(u64 *)s2; | ||
831 | |||
832 | if (snap_id1 < snap_id2) | ||
833 | return 1; | ||
834 | return snap_id1 == snap_id2 ? 0 : -1; | ||
835 | } | ||
836 | |||
837 | /* | ||
838 | * Search a snapshot context to see if the given snapshot id is | ||
839 | * present. | ||
840 | * | ||
841 | * Returns the position of the snapshot id in the array if it's found, | ||
842 | * or BAD_SNAP_INDEX otherwise. | ||
843 | * | ||
844 | * Note: The snapshot array is in kept sorted (by the osd) in | ||
845 | * reverse order, highest snapshot id first. | ||
846 | */ | ||
822 | static u32 rbd_dev_snap_index(struct rbd_device *rbd_dev, u64 snap_id) | 847 | static u32 rbd_dev_snap_index(struct rbd_device *rbd_dev, u64 snap_id) |
823 | { | 848 | { |
824 | struct ceph_snap_context *snapc = rbd_dev->header.snapc; | 849 | struct ceph_snap_context *snapc = rbd_dev->header.snapc; |
825 | u32 which; | 850 | u64 *found; |
826 | 851 | ||
827 | for (which = 0; which < snapc->num_snaps; which++) | 852 | found = bsearch(&snap_id, &snapc->snaps, snapc->num_snaps, |
828 | if (snapc->snaps[which] == snap_id) | 853 | sizeof (snap_id), snapid_compare_reverse); |
829 | return which; | ||
830 | 854 | ||
831 | return BAD_SNAP_INDEX; | 855 | return found ? (u32)(found - &snapc->snaps[0]) : BAD_SNAP_INDEX; |
832 | } | 856 | } |
833 | 857 | ||
834 | static const char *rbd_dev_v1_snap_name(struct rbd_device *rbd_dev, | 858 | static const char *rbd_dev_v1_snap_name(struct rbd_device *rbd_dev, |