[LTP] [PATCH v2] syscalls/msgrcv07: Add functional test for MSG_COPY flag

Cyril Hrubis chrubis@suse.cz
Tue Sep 8 16:08:38 CEST 2020


Hi!
> +static void test_msg_copy(void)
> +{
> +	struct msqid_ds buf = {0};
> +
> +	if (!msg_copy_sup) {
> +		tst_res(TCONF, "kernel doesn't support MSG_COPY flag, skip it");
> +		return;
> +	}
> +	prepare_queue();
> +
> +	/*
> +	 * If MSG_COPY flag was specified, then mtype is interpreted as number
> +	 * of the message to copy.
> +	 */
> +	SAFE_MSGRCV(queue_id, &rcv_buf, MSGSIZE, 0, MSG_COPY | IPC_NOWAIT);
> +	if (strcmp(rcv_buf.mtext, MSG1) == 0 && rcv_buf.type == MSGTYPE1)
> +		tst_res(TPASS, "msgrcv(MSG_COPY) got MSGTYPE1 msg data"
> +			" correctly");
> +	else
> +		tst_res(TFAIL, "msgrcv(MSG_COPY) got MSGTYPE1 msg data"
> +			" incorrectly");
> +
> +	SAFE_MSGRCV(queue_id, &rcv_buf, MSGSIZE, 1, MSG_COPY | IPC_NOWAIT);
> +	if (strcmp(rcv_buf.mtext, MSG2) == 0 && rcv_buf.type == MSGTYPE2)
> +		tst_res(TPASS, "msgrcv(MSG_COPY) got MSGTYPE2 msg data"
> +			" correctly");
> +	else
> +		tst_res(TFAIL, "msgrcv(MSG_COPY) got MSGTYPE2 msg data"
> +			" incorrectly");

Can we please keep the strings on a single line?

I guess that we can shorten the messages a bit e.g.

tst_res(TFAIL, "msgrcv(MSG_COPY) got MSGTYPE2 data correctly");

Or even:

tst_res(TFAIL, "MSG_COPY got MSGTYPE2 data correctly");

Please try to keep the messages short and to the point.

> +	SAFE_MSGCTL(queue_id, IPC_STAT, &buf);
> +	if (buf.msg_qnum == 2)
> +		tst_res(TPASS, "msgrcv(MSG_COPY) succeeded, msg queue "
> +			"still has 2 msg");
> +	else
> +		tst_res(TFAIL, "msgrcv(MSG_COPY) msg queue expected 2 msg num,"
> +			" but only got %d", (int)buf.msg_qnum);

Here as well we can shorten it to something as:

	tst_res(TPASS, "Two messages still in queue");

	tst_res(TFAIL, "Expected 2 msgs in queue got %i",
		(int)buf.msg_qnum);

> +	SAFE_MSGCTL(queue_id, IPC_RMID, NULL);
> +}
> +
>  static void test_zero_msgtyp(void)
>  {
>  	prepare_queue();
> @@ -159,11 +203,28 @@ static void test_negative_msgtyp(void)
>  static void setup(void)
>  {
>  	msgkey = GETIPCKEY();
> +	prepare_queue();
> +	TEST(msgrcv(queue_id, &rcv_buf, MSGSIZE, MSGTYPE1, MSG_COPY));
> +	if (TST_RET != -1)
> +		tst_res(TINFO, "msgrcv succeeded unexpectedly, kernel doesn't"
> +			" support MSG_COPY flag");
> +
> +	if (TST_ERR == EINVAL) {
> +		tst_res(TINFO, "msgrcv failed as expected when not using"
> +			" MSG_COPY and IPC_NOWAIT concurrently");
> +		msg_copy_sup = 1;
> +	} else if (TST_ERR == ENOSYS) {
> +		tst_res(TINFO, "kernel doesn't enable CONFIG_CHECKPOINT_RESTORE");
> +	} else {
> +		tst_res(TINFO | TTERRNO, "msgrcv failed when not using MSG_COPY"
> +			"and IPC_NOWAIT concurrently, expected EINVAL but got");
> +	}

This check actually does not work, it fails to detect the support on
newer kernels, e.g. 5.6.1 without the CONFIG_CHECKPOINT_RESTORE.

When kernel is new enough call to msgrcv() with MSG_COPY without
IPC_NOWAIT returns EINVAL even without CONFIG_CHECKPOINT_RESTORE I guess
that the flags are checked in the generic code and not ifdefed out. You
will get ENOSYS only on correct combination i.e. MSG_COPY | IPC_NOWAIT.

So why don't we rather:

* Check if the kernel is older than 3.8 and skip the MSG_COPY test when
  it is

* Check for ENOSYS in the test_msg_copy() function

These two conditions should cover all possible cases.

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list