aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-04-30 01:44:33 -0400
committerSage Weil <sage@inktank.com>2013-05-02 00:20:20 -0400
commit2ad3d7167e599fb149ed370a3128140b9deabd5a (patch)
tree56648210aec482269e5da1986cf1738a71bab164
parent54cac61fb6b3bacecf5367d3838307b1dd69ace2 (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>
-rw-r--r--drivers/block/rbd.c152
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);
435static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev); 435static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev);
436static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, 436static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
437 u64 snap_id); 437 u64 snap_id);
438static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
439 u8 *order, u64 *snap_size);
440static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
441 u64 *snap_features);
442static u64 rbd_snap_id_by_name(struct rbd_device *rbd_dev, const char *name);
438 443
439static int rbd_open(struct block_device *bdev, fmode_t mode) 444static 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
843static const char *rbd_dev_v1_snap_name(struct rbd_device *rbd_dev, u64 snap_id) 848static 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
866static struct rbd_snap *snap_by_name(struct rbd_device *rbd_dev, 872static 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
878static int rbd_dev_mapping_set(struct rbd_device *rbd_dev) 899static 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); 920static 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
3825static 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
3843static 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 */
3867static 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 }