diff options
author | Alex Elder <elder@inktank.com> | 2013-04-30 01:44:33 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-05-02 00:20:20 -0400 |
commit | 2ad3d7167e599fb149ed370a3128140b9deabd5a (patch) | |
tree | 56648210aec482269e5da1986cf1738a71bab164 /drivers/block/rbd.c | |
parent | 54cac61fb6b3bacecf5367d3838307b1dd69ace2 (diff) |
rbd: define rbd_snap_size() and rbd_snap_features()
This patch defines a handful of new functions that will allow
us to get rid of the rbd device structure's list of snapshots.
Define rbd_snap_id_by_name() to look up a snapshot id given its
name. This is efficient for format 1 images but not for format 2.
Fortunately it only gets called at mapping time so it's not that
critical.
Use rbd_snap_id_by_name() to find out the id for a snapshot getting
mapped, and pass that id to new functions rbd_snap_size() and
rbd_snap_features() to look up information about a given snapshot's
size and feature mask given its snapshot id. All this gets done
in rbd_dev_mapping_set().
As a result, snap_by_name() is no longer needed, so get rid of it.
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block/rbd.c')
-rw-r--r-- | drivers/block/rbd.c | 152 |
1 files changed, 129 insertions, 23 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index eb78d575d9b2..bf836dea113a 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -435,6 +435,11 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev); | |||
435 | static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev); | 435 | static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev); |
436 | static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, | 436 | static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, |
437 | u64 snap_id); | 437 | u64 snap_id); |
438 | static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id, | ||
439 | u8 *order, u64 *snap_size); | ||
440 | static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id, | ||
441 | u64 *snap_features); | ||
442 | static u64 rbd_snap_id_by_name(struct rbd_device *rbd_dev, const char *name); | ||
438 | 443 | ||
439 | static int rbd_open(struct block_device *bdev, fmode_t mode) | 444 | static int rbd_open(struct block_device *bdev, fmode_t mode) |
440 | { | 445 | { |
@@ -840,7 +845,8 @@ static u32 rbd_dev_snap_index(struct rbd_device *rbd_dev, u64 snap_id) | |||
840 | return BAD_SNAP_INDEX; | 845 | return BAD_SNAP_INDEX; |
841 | } | 846 | } |
842 | 847 | ||
843 | static const char *rbd_dev_v1_snap_name(struct rbd_device *rbd_dev, u64 snap_id) | 848 | static const char *rbd_dev_v1_snap_name(struct rbd_device *rbd_dev, |
849 | u64 snap_id) | ||
844 | { | 850 | { |
845 | u32 which; | 851 | u32 which; |
846 | 852 | ||
@@ -863,35 +869,85 @@ static const char *rbd_snap_name(struct rbd_device *rbd_dev, u64 snap_id) | |||
863 | return rbd_dev_v2_snap_name(rbd_dev, snap_id); | 869 | return rbd_dev_v2_snap_name(rbd_dev, snap_id); |
864 | } | 870 | } |
865 | 871 | ||
866 | static struct rbd_snap *snap_by_name(struct rbd_device *rbd_dev, | 872 | static int rbd_snap_size(struct rbd_device *rbd_dev, u64 snap_id, |
867 | const char *snap_name) | 873 | u64 *snap_size) |
868 | { | 874 | { |
869 | struct rbd_snap *snap; | 875 | rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); |
876 | if (snap_id == CEPH_NOSNAP) { | ||
877 | *snap_size = rbd_dev->header.image_size; | ||
878 | } else if (rbd_dev->image_format == 1) { | ||
879 | u32 which; | ||
870 | 880 | ||
871 | list_for_each_entry(snap, &rbd_dev->snaps, node) | 881 | which = rbd_dev_snap_index(rbd_dev, snap_id); |
872 | if (!strcmp(snap_name, snap->name)) | 882 | if (which == BAD_SNAP_INDEX) |
873 | return snap; | 883 | return -ENOENT; |
874 | 884 | ||
875 | return NULL; | 885 | *snap_size = rbd_dev->header.snap_sizes[which]; |
886 | } else { | ||
887 | u64 size = 0; | ||
888 | int ret; | ||
889 | |||
890 | ret = _rbd_dev_v2_snap_size(rbd_dev, snap_id, NULL, &size); | ||
891 | if (ret) | ||
892 | return ret; | ||
893 | |||
894 | *snap_size = size; | ||
895 | } | ||
896 | return 0; | ||
876 | } | 897 | } |
877 | 898 | ||
878 | static int rbd_dev_mapping_set(struct rbd_device *rbd_dev) | 899 | static int rbd_snap_features(struct rbd_device *rbd_dev, u64 snap_id, |
900 | u64 *snap_features) | ||
879 | { | 901 | { |
880 | if (!memcmp(rbd_dev->spec->snap_name, RBD_SNAP_HEAD_NAME, | 902 | rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); |
881 | sizeof (RBD_SNAP_HEAD_NAME))) { | 903 | if (snap_id == CEPH_NOSNAP) { |
882 | rbd_dev->mapping.size = rbd_dev->header.image_size; | 904 | *snap_features = rbd_dev->header.features; |
883 | rbd_dev->mapping.features = rbd_dev->header.features; | 905 | } else if (rbd_dev->image_format == 1) { |
906 | *snap_features = 0; /* No features for format 1 */ | ||
884 | } else { | 907 | } else { |
885 | struct rbd_snap *snap; | 908 | u64 features = 0; |
909 | int ret; | ||
910 | |||
911 | ret = _rbd_dev_v2_snap_features(rbd_dev, snap_id, &features); | ||
912 | if (ret) | ||
913 | return ret; | ||
914 | |||
915 | *snap_features = features; | ||
916 | } | ||
917 | return 0; | ||
918 | } | ||
886 | 919 | ||
887 | snap = snap_by_name(rbd_dev, rbd_dev->spec->snap_name); | 920 | static int rbd_dev_mapping_set(struct rbd_device *rbd_dev) |
888 | if (!snap) | 921 | { |
922 | const char *snap_name = rbd_dev->spec->snap_name; | ||
923 | u64 snap_id; | ||
924 | u64 size = 0; | ||
925 | u64 features = 0; | ||
926 | int ret; | ||
927 | |||
928 | if (strcmp(snap_name, RBD_SNAP_HEAD_NAME)) { | ||
929 | snap_id = rbd_snap_id_by_name(rbd_dev, snap_name); | ||
930 | if (snap_id == CEPH_NOSNAP) | ||
889 | return -ENOENT; | 931 | return -ENOENT; |
890 | rbd_dev->mapping.size = snap->size; | 932 | } else { |
891 | rbd_dev->mapping.features = snap->features; | 933 | snap_id = CEPH_NOSNAP; |
892 | rbd_dev->mapping.read_only = true; | ||
893 | } | 934 | } |
894 | 935 | ||
936 | ret = rbd_snap_size(rbd_dev, snap_id, &size); | ||
937 | if (ret) | ||
938 | return ret; | ||
939 | ret = rbd_snap_features(rbd_dev, snap_id, &features); | ||
940 | if (ret) | ||
941 | return ret; | ||
942 | |||
943 | rbd_dev->mapping.size = size; | ||
944 | rbd_dev->mapping.features = features; | ||
945 | |||
946 | /* If we are mapping a snapshot it must be marked read-only */ | ||
947 | |||
948 | if (snap_id != CEPH_NOSNAP) | ||
949 | rbd_dev->mapping.read_only = true; | ||
950 | |||
895 | return 0; | 951 | return 0; |
896 | } | 952 | } |
897 | 953 | ||
@@ -3766,6 +3822,56 @@ out: | |||
3766 | return image_name; | 3822 | return image_name; |
3767 | } | 3823 | } |
3768 | 3824 | ||
3825 | static u64 rbd_v1_snap_id_by_name(struct rbd_device *rbd_dev, const char *name) | ||
3826 | { | ||
3827 | struct ceph_snap_context *snapc = rbd_dev->header.snapc; | ||
3828 | const char *snap_name; | ||
3829 | u32 which = 0; | ||
3830 | |||
3831 | /* Skip over names until we find the one we are looking for */ | ||
3832 | |||
3833 | snap_name = rbd_dev->header.snap_names; | ||
3834 | while (which < snapc->num_snaps) { | ||
3835 | if (!strcmp(name, snap_name)) | ||
3836 | return snapc->snaps[which]; | ||
3837 | snap_name += strlen(snap_name) + 1; | ||
3838 | which++; | ||
3839 | } | ||
3840 | return CEPH_NOSNAP; | ||
3841 | } | ||
3842 | |||
3843 | static u64 rbd_v2_snap_id_by_name(struct rbd_device *rbd_dev, const char *name) | ||
3844 | { | ||
3845 | struct ceph_snap_context *snapc = rbd_dev->header.snapc; | ||
3846 | u32 which; | ||
3847 | bool found = false; | ||
3848 | u64 snap_id; | ||
3849 | |||
3850 | for (which = 0; !found && which < snapc->num_snaps; which++) { | ||
3851 | const char *snap_name; | ||
3852 | |||
3853 | snap_id = snapc->snaps[which]; | ||
3854 | snap_name = rbd_dev_v2_snap_name(rbd_dev, snap_id); | ||
3855 | if (IS_ERR(snap_name)) | ||
3856 | break; | ||
3857 | found = !strcmp(name, snap_name); | ||
3858 | kfree(snap_name); | ||
3859 | } | ||
3860 | return found ? snap_id : CEPH_NOSNAP; | ||
3861 | } | ||
3862 | |||
3863 | /* | ||
3864 | * Assumes name is never RBD_SNAP_HEAD_NAME; returns CEPH_NOSNAP if | ||
3865 | * no snapshot by that name is found, or if an error occurs. | ||
3866 | */ | ||
3867 | static u64 rbd_snap_id_by_name(struct rbd_device *rbd_dev, const char *name) | ||
3868 | { | ||
3869 | if (rbd_dev->image_format == 1) | ||
3870 | return rbd_v1_snap_id_by_name(rbd_dev, name); | ||
3871 | |||
3872 | return rbd_v2_snap_id_by_name(rbd_dev, name); | ||
3873 | } | ||
3874 | |||
3769 | /* | 3875 | /* |
3770 | * When an rbd image has a parent image, it is identified by the | 3876 | * When an rbd image has a parent image, it is identified by the |
3771 | * pool, image, and snapshot ids (not names). This function fills | 3877 | * pool, image, and snapshot ids (not names). This function fills |
@@ -3797,12 +3903,12 @@ static int rbd_dev_spec_update(struct rbd_device *rbd_dev) | |||
3797 | */ | 3903 | */ |
3798 | if (spec->pool_name) { | 3904 | if (spec->pool_name) { |
3799 | if (strcmp(spec->snap_name, RBD_SNAP_HEAD_NAME)) { | 3905 | if (strcmp(spec->snap_name, RBD_SNAP_HEAD_NAME)) { |
3800 | struct rbd_snap *snap; | 3906 | u64 snap_id; |
3801 | 3907 | ||
3802 | snap = snap_by_name(rbd_dev, spec->snap_name); | 3908 | snap_id = rbd_snap_id_by_name(rbd_dev, spec->snap_name); |
3803 | if (!snap) | 3909 | if (snap_id == CEPH_NOSNAP) |
3804 | return -ENOENT; | 3910 | return -ENOENT; |
3805 | spec->snap_id = snap->id; | 3911 | spec->snap_id = snap_id; |
3806 | } else { | 3912 | } else { |
3807 | spec->snap_id = CEPH_NOSNAP; | 3913 | spec->snap_id = CEPH_NOSNAP; |
3808 | } | 3914 | } |