Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30ba1f02 authored by Ilya Dryomov's avatar Ilya Dryomov Committed by Yan, Zheng
Browse files

rbd: make sure we have latest osdmap on 'rbd map'

Given an existing idle mapping (img1), mapping an image (img2) in
a newly created pool (pool2) fails:

    $ ceph osd pool create pool1 8 8
    $ rbd create --size 1000 pool1/img1
    $ sudo rbd map pool1/img1
    $ ceph osd pool create pool2 8 8
    $ rbd create --size 1000 pool2/img2
    $ sudo rbd map pool2/img2
    rbd: sysfs write failed
    rbd: map failed: (2) No such file or directory

This is because client instances are shared by default and we don't
request an osdmap update when bumping a ref on an existing client.  The
fix is to use the mon_get_version request to see if the osdmap we have
is the latest, and block until the requested update is received if it's
not.

Fixes: http://tracker.ceph.com/issues/8184



Signed-off-by: default avatarIlya Dryomov <ilya.dryomov@inktank.com>
Reviewed-by: default avatarSage Weil <sage@inktank.com>
parent 6044cde6
Loading
Loading
Loading
Loading
+33 −3
Original line number Diff line number Diff line
@@ -4682,6 +4682,38 @@ static int rbd_add_parse_args(const char *buf,
	return ret;
}

/*
 * Return pool id (>= 0) or a negative error code.
 */
static int rbd_add_get_pool_id(struct rbd_client *rbdc, const char *pool_name)
{
	u64 newest_epoch;
	unsigned long timeout = rbdc->client->options->mount_timeout * HZ;
	int tries = 0;
	int ret;

again:
	ret = ceph_pg_poolid_by_name(rbdc->client->osdc.osdmap, pool_name);
	if (ret == -ENOENT && tries++ < 1) {
		ret = ceph_monc_do_get_version(&rbdc->client->monc, "osdmap",
					       &newest_epoch);
		if (ret < 0)
			return ret;

		if (rbdc->client->osdc.osdmap->epoch < newest_epoch) {
			ceph_monc_request_next_osdmap(&rbdc->client->monc);
			(void) ceph_monc_wait_osdmap(&rbdc->client->monc,
						     newest_epoch, timeout);
			goto again;
		} else {
			/* the osdmap we have is new enough */
			return -ENOENT;
		}
	}

	return ret;
}

/*
 * An rbd format 2 image has a unique identifier, distinct from the
 * name given to it by the user.  Internally, that identifier is
@@ -5053,7 +5085,6 @@ static ssize_t do_rbd_add(struct bus_type *bus,
	struct rbd_options *rbd_opts = NULL;
	struct rbd_spec *spec = NULL;
	struct rbd_client *rbdc;
	struct ceph_osd_client *osdc;
	bool read_only;
	int rc = -ENOMEM;

@@ -5075,8 +5106,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
	}

	/* pick the pool */
	osdc = &rbdc->client->osdc;
	rc = ceph_pg_poolid_by_name(osdc->osdmap, spec->pool_name);
	rc = rbd_add_get_pool_id(rbdc, spec->pool_name);
	if (rc < 0)
		goto err_out_client;
	spec->pool_id = (u64)rc;