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

Commit d30291b9 authored by Ilya Dryomov's avatar Ilya Dryomov
Browse files

libceph: variable-sized ceph_object_id



Currently ceph_object_id can hold object names of up to 100
(CEPH_MAX_OID_NAME_LEN) characters.  This is enough for all use cases,
expect one - long rbd image names:

- a format 1 header is named "<imgname>.rbd"
- an object that points to a format 2 header is named "rbd_id.<imgname>"

We operate on these potentially long-named objects during rbd map, and,
for format 1 images, during header refresh.  (A format 2 header name is
a small system-generated string.)

Lift this 100 character limit by making ceph_object_id be able to point
to an externally-allocated string.  Apart from being able to work with
almost arbitrarily-long named objects, this allows us to reduce the
size of ceph_object_id from >100 bytes to 64 bytes.

Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent 711da55d
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -1965,7 +1965,9 @@ static struct ceph_osd_request *rbd_osd_req_create(
	osd_req->r_priv = obj_request;

	osd_req->r_base_oloc.pool = ceph_file_layout_pg_pool(rbd_dev->layout);
	ceph_oid_set_name(&osd_req->r_base_oid, obj_request->object_name);
	if (ceph_oid_aprintf(&osd_req->r_base_oid, GFP_NOIO, "%s",
			     obj_request->object_name))
		goto fail;

	if (ceph_osdc_alloc_messages(osd_req, GFP_NOIO))
		goto fail;
@@ -2017,7 +2019,9 @@ rbd_osd_req_create_copyup(struct rbd_obj_request *obj_request)
	osd_req->r_priv = obj_request;

	osd_req->r_base_oloc.pool = ceph_file_layout_pg_pool(rbd_dev->layout);
	ceph_oid_set_name(&osd_req->r_base_oid, obj_request->object_name);
	if (ceph_oid_aprintf(&osd_req->r_base_oid, GFP_NOIO, "%s",
			     obj_request->object_name))
		goto fail;

	if (ceph_osdc_alloc_messages(osd_req, GFP_NOIO))
		goto fail;
+2 −4
Original line number Diff line number Diff line
@@ -1758,9 +1758,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
	rd_req->r_flags = CEPH_OSD_FLAG_READ;
	osd_req_op_init(rd_req, 0, CEPH_OSD_OP_STAT, 0);
	rd_req->r_base_oloc.pool = pool;
	snprintf(rd_req->r_base_oid.name, sizeof(rd_req->r_base_oid.name),
		 "%llx.00000000", ci->i_vino.ino);
	rd_req->r_base_oid.name_len = strlen(rd_req->r_base_oid.name);
	ceph_oid_printf(&rd_req->r_base_oid, "%llx.00000000", ci->i_vino.ino);

	err = ceph_osdc_alloc_messages(rd_req, GFP_NOFS);
	if (err)
@@ -1777,7 +1775,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
			  CEPH_OSD_FLAG_ACK | CEPH_OSD_FLAG_ONDISK;
	osd_req_op_init(wr_req, 0, CEPH_OSD_OP_CREATE, CEPH_OSD_OP_FLAG_EXCL);
	wr_req->r_base_oloc.pool = pool;
	wr_req->r_base_oid = rd_req->r_base_oid;
	ceph_oid_copy(&wr_req->r_base_oid, &rd_req->r_base_oid);

	err = ceph_osdc_alloc_messages(wr_req, GFP_NOFS);
	if (err)
+1 −1
Original line number Diff line number Diff line
@@ -715,7 +715,7 @@ static void ceph_aio_retry_work(struct work_struct *work)
			CEPH_OSD_FLAG_ONDISK |
			CEPH_OSD_FLAG_WRITE;
	req->r_base_oloc = orig_req->r_base_oloc;
	req->r_base_oid = orig_req->r_base_oid;
	ceph_oid_copy(&req->r_base_oid, &orig_req->r_base_oid);

	ret = ceph_osdc_alloc_messages(req, GFP_NOFS);
	if (ret) {
+1 −1
Original line number Diff line number Diff line
@@ -213,7 +213,7 @@ static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
		 ceph_ino(inode), dl.object_no);

	oloc.pool = ceph_file_layout_pg_pool(ci->i_layout);
	ceph_oid_set_name(&oid, dl.object_name);
	ceph_oid_printf(&oid, "%s", dl.object_name);

	r = ceph_oloc_oid_to_pg(osdc->osdmap, &oloc, &oid, &pgid);
	if (r < 0) {
+37 −25
Original line number Diff line number Diff line
@@ -64,11 +64,47 @@ struct ceph_object_locator {
 */
#define CEPH_MAX_OID_NAME_LEN 100

/*
 * 51-char inline_name is long enough for all cephfs and all but one
 * rbd requests: <imgname> in "<imgname>.rbd"/"rbd_id.<imgname>" can be
 * arbitrarily long (~PAGE_SIZE).  It's done once during rbd map; all
 * other rbd requests fit into inline_name.
 *
 * Makes ceph_object_id 64 bytes on 64-bit.
 */
#define CEPH_OID_INLINE_LEN 52

/*
 * Both inline and external buffers have space for a NUL-terminator,
 * which is carried around.  It's not required though - RADOS object
 * names don't have to be NUL-terminated and may contain NULs.
 */
struct ceph_object_id {
	char name[CEPH_MAX_OID_NAME_LEN];
	char *name;
	char inline_name[CEPH_OID_INLINE_LEN];
	int name_len;
};

static inline void ceph_oid_init(struct ceph_object_id *oid)
{
	oid->name = oid->inline_name;
	oid->name_len = 0;
}

static inline bool ceph_oid_empty(const struct ceph_object_id *oid)
{
	return oid->name == oid->inline_name && !oid->name_len;
}

void ceph_oid_copy(struct ceph_object_id *dest,
		   const struct ceph_object_id *src);
__printf(2, 3)
void ceph_oid_printf(struct ceph_object_id *oid, const char *fmt, ...);
__printf(3, 4)
int ceph_oid_aprintf(struct ceph_object_id *oid, gfp_t gfp,
		     const char *fmt, ...);
void ceph_oid_destroy(struct ceph_object_id *oid);

struct ceph_pg_mapping {
	struct rb_node node;
	struct ceph_pg pgid;
@@ -113,30 +149,6 @@ struct ceph_osdmap {
	int crush_scratch_ary[CEPH_PG_MAX_SIZE * 3];
};

static inline void ceph_oid_set_name(struct ceph_object_id *oid,
				     const char *name)
{
	int len;

	len = strlen(name);
	if (len > sizeof(oid->name)) {
		WARN(1, "ceph_oid_set_name '%s' len %d vs %zu, truncating\n",
		     name, len, sizeof(oid->name));
		len = sizeof(oid->name);
	}

	memcpy(oid->name, name, len);
	oid->name_len = len;
}

static inline void ceph_oid_copy(struct ceph_object_id *dest,
				 struct ceph_object_id *src)
{
	BUG_ON(src->name_len > sizeof(dest->name));
	memcpy(dest->name, src->name, src->name_len);
	dest->name_len = src->name_len;
}

static inline int ceph_osd_exists(struct ceph_osdmap *map, int osd)
{
	return osd >= 0 && osd < map->max_osd &&
Loading