"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
object_qid over imsg
To:
gameoftrees@openbsd.org
Date:
Mon, 4 Aug 2025 17:28:50 +0200

Download raw body.

Thread
  • Stefan Sperling:

    object_qid over imsg

Add functions which transport object ID queues across the imsg layer.

This will be needed for an upcoming got-read-pack commit coloring fix.

ok?

M  lib/got_lib_privsep.h      |   27+   0-
M  lib/pack_create_privsep.c  |    2+  44-
M  lib/privsep.c              |  124+   0-

3 files changed, 153 insertions(+), 44 deletions(-)

commit - ce6204164ae9cc9e4be847122484967b4c3c33c1
commit + 58cfb2ec1ed437bf474ca53c28a459adfa8e8c7c
blob - a539f5cf968d5bec802bad6082fe43acfc4dc609
blob + 1252f28cd25e49bcc68c40a7a8b6ca916b188c66
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
@@ -205,6 +205,10 @@ enum got_imsg_type {
 	GOT_IMSG_OBJ_ID_LIST,
 	GOT_IMSG_OBJ_ID_LIST_DONE,
 
+	/* Transfer a queue of object IDs. */
+	GOT_IMSG_OBJ_ID_QUEUE,
+	GOT_IMSG_OBJ_ID_QUEUE_DONE,
+
 	/* Messages related to patch files. */
 	GOT_IMSG_PATCH_FILE,
 	GOT_IMSG_PATCH_HUNK,
@@ -573,6 +577,24 @@ struct got_imsg_object_idlist {
 	sizeof(struct got_imsg_object_idlist)) / sizeof(struct got_object_id))
 };
 
+/*
+ * Structure for GOT_IMSG_OBJ_QID_LIST data.
+ * Multiple such messages may be sent back-to-back, where each message
+ * contains a chunk of IDs. The entire list must be terminated with a
+ * GOT_IMSG_OBJ_QID_LIST_DONE message.
+ */
+struct got_imsg_object_id_queue {
+	size_t nids;
+
+	/*
+	 * Followed by nids * struct got_object_qid.
+	 */
+
+#define GOT_IMSG_OBJ_ID_QUEUE_MAX_NIDS \
+	((MAX_IMSGSIZE - IMSG_HEADER_SIZE - \
+	sizeof(struct got_imsg_object_id_queue)) / sizeof(struct got_object_qid))
+};
+
 /* Structure for GOT_IMSG_COMMIT_TRAVERSAL_REQUEST  */
 struct got_imsg_commit_traversal_request {
 	struct got_imsg_packed_object iobj;
@@ -818,6 +840,11 @@ const struct got_error *got_privsep_send_object_idlist
 const struct got_error *got_privsep_recv_object_idlist(int *,
     struct got_object_id **, size_t *, struct imsgbuf *);
 
+const struct got_error *got_privsep_send_object_id_queue(struct imsgbuf *ibuf,
+    struct got_object_id_queue *, size_t);
+const struct got_error *got_privsep_recv_object_id_queue(int *,
+    struct got_object_id_queue *, size_t *, struct imsgbuf *);
+
 const struct got_error *got_privsep_send_delta_reuse_req(struct imsgbuf *);
 const struct got_error *got_privsep_send_reused_deltas(struct imsgbuf *,
     struct got_imsg_reused_delta *, size_t);
blob - 2a41e8fd7c124e45e9207604dc32308d4979cd05
blob + 8f72aa6c4993b257f992a9300fa14467f7402aa6
--- lib/pack_create_privsep.c
+++ lib/pack_create_privsep.c
@@ -96,38 +96,6 @@ send_idset(struct imsgbuf *ibuf, struct got_object_ids
 }
 
 static const struct got_error *
-send_filtered_id_queue(struct imsgbuf *ibuf, struct got_object_id_queue *ids,
-    uintptr_t color)
-{
-	const struct got_error *err = NULL;
-	struct got_object_qid *qid;
-	struct got_object_id *filtered_ids[GOT_IMSG_OBJ_ID_LIST_MAX_NIDS];
-	int nids = 0;
-
-	STAILQ_FOREACH(qid, ids, entry) {
-		if (color != (intptr_t)qid->data)
-			continue;
-
-		filtered_ids[nids++] = &qid->id;
-		if (nids >= GOT_IMSG_OBJ_ID_LIST_MAX_NIDS) {
-			err = got_privsep_send_object_idlist(ibuf,
-			    filtered_ids, nids);
-			if (err)
-				return err;
-			nids = 0;
-		}
-	}
-
-	if (nids > 0) {
-		err = got_privsep_send_object_idlist(ibuf, filtered_ids, nids);
-		if (err)
-			return err;
-	}
-
-	return got_privsep_send_object_idlist_done(ibuf);
-}
-
-static const struct got_error *
 recv_reused_delta(struct got_imsg_reused_delta *delta,
     struct got_object_idset *idset, struct got_pack_metavec *v)
 {
@@ -326,21 +294,11 @@ paint_packed_commits(struct got_object_qid **qid0,
 	if (err)
 		return err;
 
-	err = send_filtered_id_queue(pack->privsep_child->ibuf, ids,
-	    COLOR_KEEP);
+	err = got_privsep_send_object_id_queue(pack->privsep_child->ibuf,
+	    ids, *nqueued);
 	if (err)
 		return err;
 
-	err = send_filtered_id_queue(pack->privsep_child->ibuf, ids,
-	    COLOR_DROP);
-	if (err)
-		return err;
-
-	err = send_filtered_id_queue(pack->privsep_child->ibuf, ids,
-	    COLOR_SKIP);
-	if (err)
-		return err;
-
 	arg.ncolored = ncolored;
 	arg.nqueued = nqueued;
 	arg.nskip = nskip;
blob - 460ebb155dc401a8750ca217414e546ddad73c5a
blob + 5aaaa8e2b4a5026b7b0eaf69032bf1917b2f6d90
--- lib/privsep.c
+++ lib/privsep.c
@@ -3271,7 +3271,131 @@ got_privsep_recv_object_idlist(int *done, struct got_o
 	return err;
 }
 
+static const struct got_error *
+send_qidlist(struct imsgbuf *ibuf, struct got_object_qid **qids, size_t nids)
+{
+	const struct got_error *err = NULL;
+	struct got_imsg_object_id_queue idqueue;
+	struct ibuf *wbuf;
+	size_t i;
+
+	memset(&idqueue, 0, sizeof(idqueue));
+
+	if (nids > GOT_IMSG_OBJ_ID_QUEUE_MAX_NIDS)
+		return got_error(GOT_ERR_NO_SPACE);
+
+	wbuf = imsg_create(ibuf, GOT_IMSG_OBJ_ID_QUEUE, 0, 0,
+	    sizeof(idqueue) + nids * sizeof(struct got_object_qid));
+	if (wbuf == NULL) {
+		err = got_error_from_errno("imsg_create OBJ_ID_QUEUE");
+		return err;
+	}
+
+	idqueue.nids = nids;
+	if (imsg_add(wbuf, &idqueue, sizeof(idqueue)) == -1)
+		return got_error_from_errno("imsg_add OBJ_ID_QUEUE");
+
+	for (i = 0; i < nids; i++) {
+		struct got_object_qid *qid = qids[i];
+		if (imsg_add(wbuf, qid, sizeof(*qid)) == -1)
+			return got_error_from_errno("imsg_add OBJ_ID_LIST");
+	}
+
+	imsg_close(ibuf, wbuf);
+
+	return flush_imsg(ibuf);
+}
+
 const struct got_error *
+got_privsep_send_object_id_queue(struct imsgbuf *ibuf,
+    struct got_object_id_queue *ids, size_t nids)
+{
+	const struct got_error *err = NULL;
+	struct got_object_qid *qid, *qidlist[GOT_IMSG_OBJ_ID_QUEUE_MAX_NIDS];
+	int i, queued = 0;
+
+	qid = STAILQ_FIRST(ids);
+	for (i = 0; qid && i < nids; i++) {
+		qidlist[i % nitems(qidlist)] = qid;
+		queued++;
+		if (queued >= nitems(qidlist)) {
+			err = send_qidlist(ibuf, qidlist, queued);
+			if (err)
+				return err;
+			queued = 0;
+		}
+		qid = STAILQ_NEXT(qid, entry);
+	}
+
+	if (queued > 0) {
+		err = send_qidlist(ibuf, qidlist, queued);
+		if (err)
+			return err;
+	}
+
+	if (imsg_compose(ibuf, GOT_IMSG_OBJ_ID_QUEUE_DONE, 0, 0, -1, NULL, 0)
+	    == -1)
+		return got_error_from_errno("imsg_compose OBJ_ID_QUEUE_DONE");
+
+	return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_recv_object_id_queue(int *done, struct got_object_id_queue *ids,
+    size_t *nids, struct imsgbuf *ibuf)
+{
+	const struct got_error *err = NULL;
+	struct imsg imsg;
+	struct got_imsg_object_id_queue *qidlist;
+	struct got_object_qid *qid, *iqid;
+	size_t datalen;
+
+	*done = 0;
+	*nids = 0;
+
+	err = got_privsep_recv_imsg(&imsg, ibuf, 0);
+	if (err)
+		return err;
+
+	datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+	switch (imsg.hdr.type) {
+	case GOT_IMSG_OBJ_ID_QUEUE:
+		if (datalen < sizeof(*qidlist)) {
+			err = got_error(GOT_ERR_PRIVSEP_LEN);
+			break;
+		}
+		qidlist = imsg.data;
+		if (qidlist->nids > GOT_IMSG_OBJ_ID_LIST_MAX_NIDS ||
+		    qidlist->nids * sizeof(struct got_object_qid) !=
+		    datalen - sizeof(*qidlist)) {
+			err = got_error(GOT_ERR_PRIVSEP_LEN);
+			break;
+		}
+		iqid = (struct got_object_qid *)(imsg.data + sizeof(*qidlist));
+		while (*nids < qidlist->nids) {
+			err = got_object_qid_alloc_partial(&qid);
+			if (err)
+				break;
+			memcpy(qid, iqid, sizeof(*qid));
+			STAILQ_INSERT_TAIL(ids, qid, entry);
+			(*nids)++;
+			iqid++;
+		}
+		break;
+	case GOT_IMSG_OBJ_ID_QUEUE_DONE:
+		*done = 1;
+		break;
+	default:
+		err = got_error(GOT_ERR_PRIVSEP_MSG);
+		break;
+	}
+
+	imsg_free(&imsg);
+
+	return err;
+}
+
+const struct got_error *
 got_privsep_send_delta_reuse_req(struct imsgbuf *ibuf)
 {
 	if (imsg_compose(ibuf, GOT_IMSG_DELTA_REUSE_REQUEST, 0, 0, -1, NULL, 0)