@@ -5594,6 +5594,14 @@ struct parent_image_info {
55945594 u64 overlap ;
55955595};
55965596
5597+ static void rbd_parent_info_cleanup (struct parent_image_info * pii )
5598+ {
5599+ kfree (pii -> pool_ns );
5600+ kfree (pii -> image_id );
5601+
5602+ memset (pii , 0 , sizeof (* pii ));
5603+ }
5604+
55975605/*
55985606 * The caller is responsible for @pii.
55995607 */
@@ -5663,6 +5671,9 @@ static int __get_parent_info(struct rbd_device *rbd_dev,
56635671 if (pii -> has_overlap )
56645672 ceph_decode_64_safe (& p , end , pii -> overlap , e_inval );
56655673
5674+ dout ("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n" ,
5675+ __func__ , pii -> pool_id , pii -> pool_ns , pii -> image_id , pii -> snap_id ,
5676+ pii -> has_overlap , pii -> overlap );
56665677 return 0 ;
56675678
56685679e_inval :
@@ -5701,14 +5712,17 @@ static int __get_parent_info_legacy(struct rbd_device *rbd_dev,
57015712 pii -> has_overlap = true;
57025713 ceph_decode_64_safe (& p , end , pii -> overlap , e_inval );
57035714
5715+ dout ("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n" ,
5716+ __func__ , pii -> pool_id , pii -> pool_ns , pii -> image_id , pii -> snap_id ,
5717+ pii -> has_overlap , pii -> overlap );
57045718 return 0 ;
57055719
57065720e_inval :
57075721 return - EINVAL ;
57085722}
57095723
5710- static int get_parent_info (struct rbd_device * rbd_dev ,
5711- struct parent_image_info * pii )
5724+ static int rbd_dev_v2_parent_info (struct rbd_device * rbd_dev ,
5725+ struct parent_image_info * pii )
57125726{
57135727 struct page * req_page , * reply_page ;
57145728 void * p ;
@@ -5736,7 +5750,7 @@ static int get_parent_info(struct rbd_device *rbd_dev,
57365750 return ret ;
57375751}
57385752
5739- static int rbd_dev_v2_parent_info (struct rbd_device * rbd_dev )
5753+ static int rbd_dev_setup_parent (struct rbd_device * rbd_dev )
57405754{
57415755 struct rbd_spec * parent_spec ;
57425756 struct parent_image_info pii = { 0 };
@@ -5746,37 +5760,12 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
57465760 if (!parent_spec )
57475761 return - ENOMEM ;
57485762
5749- ret = get_parent_info (rbd_dev , & pii );
5763+ ret = rbd_dev_v2_parent_info (rbd_dev , & pii );
57505764 if (ret )
57515765 goto out_err ;
57525766
5753- dout ("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n" ,
5754- __func__ , pii .pool_id , pii .pool_ns , pii .image_id , pii .snap_id ,
5755- pii .has_overlap , pii .overlap );
5756-
5757- if (pii .pool_id == CEPH_NOPOOL || !pii .has_overlap ) {
5758- /*
5759- * Either the parent never existed, or we have
5760- * record of it but the image got flattened so it no
5761- * longer has a parent. When the parent of a
5762- * layered image disappears we immediately set the
5763- * overlap to 0. The effect of this is that all new
5764- * requests will be treated as if the image had no
5765- * parent.
5766- *
5767- * If !pii.has_overlap, the parent image spec is not
5768- * applicable. It's there to avoid duplication in each
5769- * snapshot record.
5770- */
5771- if (rbd_dev -> parent_overlap ) {
5772- rbd_dev -> parent_overlap = 0 ;
5773- rbd_dev_parent_put (rbd_dev );
5774- pr_info ("%s: clone image has been flattened\n" ,
5775- rbd_dev -> disk -> disk_name );
5776- }
5777-
5767+ if (pii .pool_id == CEPH_NOPOOL || !pii .has_overlap )
57785768 goto out ; /* No parent? No problem. */
5779- }
57805769
57815770 /* The ceph file layout needs to fit pool id in 32 bits */
57825771
@@ -5788,46 +5777,34 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
57885777 }
57895778
57905779 /*
5791- * The parent won't change (except when the clone is
5792- * flattened, already handled that). So we only need to
5793- * record the parent spec we have not already done so.
5780+ * The parent won't change except when the clone is flattened,
5781+ * so we only need to record the parent image spec once.
57945782 */
5795- if (!rbd_dev -> parent_spec ) {
5796- parent_spec -> pool_id = pii .pool_id ;
5797- if (pii .pool_ns && * pii .pool_ns ) {
5798- parent_spec -> pool_ns = pii .pool_ns ;
5799- pii .pool_ns = NULL ;
5800- }
5801- parent_spec -> image_id = pii .image_id ;
5802- pii .image_id = NULL ;
5803- parent_spec -> snap_id = pii .snap_id ;
5804-
5805- rbd_dev -> parent_spec = parent_spec ;
5806- parent_spec = NULL ; /* rbd_dev now owns this */
5783+ parent_spec -> pool_id = pii .pool_id ;
5784+ if (pii .pool_ns && * pii .pool_ns ) {
5785+ parent_spec -> pool_ns = pii .pool_ns ;
5786+ pii .pool_ns = NULL ;
58075787 }
5788+ parent_spec -> image_id = pii .image_id ;
5789+ pii .image_id = NULL ;
5790+ parent_spec -> snap_id = pii .snap_id ;
5791+
5792+ rbd_assert (!rbd_dev -> parent_spec );
5793+ rbd_dev -> parent_spec = parent_spec ;
5794+ parent_spec = NULL ; /* rbd_dev now owns this */
58085795
58095796 /*
5810- * We always update the parent overlap. If it's zero we issue
5811- * a warning, as we will proceed as if there was no parent.
5797+ * Record the parent overlap. If it's zero, issue a warning as
5798+ * we will proceed as if there is no parent.
58125799 */
5813- if (!pii .overlap ) {
5814- if (parent_spec ) {
5815- /* refresh, careful to warn just once */
5816- if (rbd_dev -> parent_overlap )
5817- rbd_warn (rbd_dev ,
5818- "clone now standalone (overlap became 0)" );
5819- } else {
5820- /* initial probe */
5821- rbd_warn (rbd_dev , "clone is standalone (overlap 0)" );
5822- }
5823- }
5800+ if (!pii .overlap )
5801+ rbd_warn (rbd_dev , "clone is standalone (overlap 0)" );
58245802 rbd_dev -> parent_overlap = pii .overlap ;
58255803
58265804out :
58275805 ret = 0 ;
58285806out_err :
5829- kfree (pii .pool_ns );
5830- kfree (pii .image_id );
5807+ rbd_parent_info_cleanup (& pii );
58315808 rbd_spec_put (parent_spec );
58325809 return ret ;
58335810}
@@ -6977,7 +6954,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
69776954 }
69786955
69796956 if (rbd_dev -> header .features & RBD_FEATURE_LAYERING ) {
6980- ret = rbd_dev_v2_parent_info (rbd_dev );
6957+ ret = rbd_dev_setup_parent (rbd_dev );
69816958 if (ret )
69826959 goto err_out_probe ;
69836960 }
@@ -7026,9 +7003,47 @@ static void rbd_dev_update_header(struct rbd_device *rbd_dev,
70267003 }
70277004}
70287005
7006+ static void rbd_dev_update_parent (struct rbd_device * rbd_dev ,
7007+ struct parent_image_info * pii )
7008+ {
7009+ if (pii -> pool_id == CEPH_NOPOOL || !pii -> has_overlap ) {
7010+ /*
7011+ * Either the parent never existed, or we have
7012+ * record of it but the image got flattened so it no
7013+ * longer has a parent. When the parent of a
7014+ * layered image disappears we immediately set the
7015+ * overlap to 0. The effect of this is that all new
7016+ * requests will be treated as if the image had no
7017+ * parent.
7018+ *
7019+ * If !pii.has_overlap, the parent image spec is not
7020+ * applicable. It's there to avoid duplication in each
7021+ * snapshot record.
7022+ */
7023+ if (rbd_dev -> parent_overlap ) {
7024+ rbd_dev -> parent_overlap = 0 ;
7025+ rbd_dev_parent_put (rbd_dev );
7026+ pr_info ("%s: clone has been flattened\n" ,
7027+ rbd_dev -> disk -> disk_name );
7028+ }
7029+ } else {
7030+ rbd_assert (rbd_dev -> parent_spec );
7031+
7032+ /*
7033+ * Update the parent overlap. If it became zero, issue
7034+ * a warning as we will proceed as if there is no parent.
7035+ */
7036+ if (!pii -> overlap && rbd_dev -> parent_overlap )
7037+ rbd_warn (rbd_dev ,
7038+ "clone has become standalone (overlap 0)" );
7039+ rbd_dev -> parent_overlap = pii -> overlap ;
7040+ }
7041+ }
7042+
70297043static int rbd_dev_refresh (struct rbd_device * rbd_dev )
70307044{
70317045 struct rbd_image_header header = { 0 };
7046+ struct parent_image_info pii = { 0 };
70327047 u64 mapping_size ;
70337048 int ret ;
70347049
@@ -7044,12 +7059,14 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
70447059 * mapped image getting flattened.
70457060 */
70467061 if (rbd_dev -> parent ) {
7047- ret = rbd_dev_v2_parent_info (rbd_dev );
7062+ ret = rbd_dev_v2_parent_info (rbd_dev , & pii );
70487063 if (ret )
70497064 goto out ;
70507065 }
70517066
70527067 rbd_dev_update_header (rbd_dev , & header );
7068+ if (rbd_dev -> parent )
7069+ rbd_dev_update_parent (rbd_dev , & pii );
70537070
70547071 rbd_assert (!rbd_is_snap (rbd_dev ));
70557072 rbd_dev -> mapping .size = rbd_dev -> header .image_size ;
@@ -7059,6 +7076,7 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
70597076 if (!ret && mapping_size != rbd_dev -> mapping .size )
70607077 rbd_dev_update_size (rbd_dev );
70617078
7079+ rbd_parent_info_cleanup (& pii );
70627080 rbd_image_header_cleanup (& header );
70637081 return ret ;
70647082}
0 commit comments