Skip to content

Commit c103117

Browse files
committed
rbd: decouple parent info read-in from updating rbd_dev
Unlike header read-in, parent info read-in is already decoupled in get_parent_info(), but it's buried in rbd_dev_v2_parent_info() along with the processing logic. Separate the initial read-in and update read-in logic into rbd_dev_setup_parent() and rbd_dev_update_parent() respectively and have rbd_dev_v2_parent_info() just populate struct parent_image_info (i.e. what get_parent_info() did). Some existing QoI issues, like flatten of a standalone clone being disregarded on refresh, remain. Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Reviewed-by: Dongsheng Yang <dongsheng.yang@easystack.cn>
1 parent 510a733 commit c103117

File tree

1 file changed

+80
-62
lines changed

1 file changed

+80
-62
lines changed

drivers/block/rbd.c

Lines changed: 80 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -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

56685679
e_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

57065720
e_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

58265804
out:
58275805
ret = 0;
58285806
out_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+
70297043
static 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

Comments
 (0)