From: Jeff Layton <jlayton@kernel.org>
To: Stas Sergeev <stsp2@yandex.ru>, fstests@vger.kernel.org
Cc: Xiong Zhou <xzhou@redhat.com>
Subject: Re: [PATCH] t_ofd_locks: fix initialization sequence
Date: Wed, 05 Jul 2023 08:26:10 -0400 [thread overview]
Message-ID: <6ee5c9ee42388d2a2e25bf80b3d7db9c09384867.camel@kernel.org> (raw)
In-Reply-To: <20230630094051.3765376-1-stsp2@yandex.ru>
On Fri, 2023-06-30 at 14:40 +0500, Stas Sergeev wrote:
> Currently IPC_RMID was attempted on a semid returned after failed
> semget() with flags=IPC_CREAT|IPC_EXCL. So nothing was actually removed.
> To get a proper semid, this patch retries semget() without IPC_EXCL.
>
Nice catch.
> This opens up a race: if the lock-tester grabbed the old sem before
> lock-setter used that magic to remove it, then the lock-tester will
> remain with removed sem.
>
> Additionally locker was waiting for sem_otime on sem0 to became
> non-zero after incrementing sem0 himself. So sem_otime was never
> 0 at the time of checking it.
>
> So basically the code was all wrong.
> This patch:
> - fixes RMID after IPC_EXCL to actually remove the sem
> - moves the increment of sem1 to the lock-tester site, and the
> lock-setter waits for that event
> - replaces the wait loop on sem_otime with GETVAL, adding a small sleep.
> - lock-tester during the init sequence checks for removed sem, and
> if it is - retries the init from semget()
>
> Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
> ---
> src/t_ofd_locks.c | 73 ++++++++++++++++++++++++++++++-----------------
> 1 file changed, 47 insertions(+), 26 deletions(-)
>
> diff --git a/src/t_ofd_locks.c b/src/t_ofd_locks.c
> index e77f2659..daa6f96c 100644
> --- a/src/t_ofd_locks.c
> +++ b/src/t_ofd_locks.c
> @@ -297,6 +297,7 @@ int main(int argc, char **argv)
> semid = semget(semkey, 2, IPC_CREAT|IPC_EXCL);
> if (semid < 0 && errno == EEXIST) {
> /* remove sem set after one round of test */
> + semid = semget(semkey, 2, IPC_CREAT);
> if (semctl(semid, 2, IPC_RMID, semu) == -1)
> err_exit("rmid 0", errno);
> retry++;
> @@ -315,32 +316,29 @@ int main(int argc, char **argv)
> semu.array = vals;
> if (semctl(semid, 2, SETALL, semu) == -1)
> err_exit("init sem", errno);
> - /* Inc both new sem to 2 */
> - sop.sem_num = 0;
> - sop.sem_op = 1;
> - sop.sem_flg = 0;
> - ts.tv_sec = 5;
> - ts.tv_nsec = 0;
> - if (semtimedop(semid, &sop, 1, &ts) == -1)
> - err_exit("inc sem0 2", errno);
> - sop.sem_num = 1;
> - sop.sem_op = 1;
> - sop.sem_flg = 0;
> - ts.tv_sec = 5;
> - ts.tv_nsec = 0;
> - if (semtimedop(semid, &sop, 1, &ts) == -1)
> - err_exit("inc sem1 2", errno);
>
> /*
> - * Wait initialization complete. semctl(2) only update
> - * sem_ctime, semop(2) will update sem_otime.
> + * Wait initialization complete.
> */
> ret = -1;
> do {
> + if (ret != -1)
> + usleep(100000);
> memset(&sem_ds, 0, sizeof(sem_ds));
> semu.buf = &sem_ds;
> - ret = semctl(semid, 0, IPC_STAT, semu);
> - } while (!(ret == 0 && sem_ds.sem_otime != 0));
> + ret = semctl(semid, 1, GETVAL, semu);
> + if (ret == -1)
> + err_exit("wait sem1 2", errno);
> + } while (ret != 2);
> +
> + /* Inc sem0 to 2 */
> + sop.sem_num = 0;
> + sop.sem_op = 1;
> + sop.sem_flg = 0;
> + ts.tv_sec = 5;
> + ts.tv_nsec = 0;
> + if (semtimedop(semid, &sop, 1, &ts) == -1)
> + err_exit("inc sem0 2", errno);
>
> /* place the lock */
> if (fcntl(fd, setlk_macro, &flk) < 0)
> @@ -393,10 +391,26 @@ int main(int argc, char **argv)
> /* getlck */
> if (lock_cmd == 0) {
> /* wait sem created and initialized */
> +again:
> retry = 5;
> do {
> semid = semget(semkey, 2, 0);
> - if (semid != -1)
> + ret = -1;
> + if (semid != -1) do {
> + if (ret != -1)
> + usleep(100000);
> + memset(&sem_ds, 0, sizeof(sem_ds));
> + semu.buf = &sem_ds;
> + ret = semctl(semid, 0, GETVAL, semu);
> + if (ret == -1 && (errno == EINVAL
> + || errno == EIDRM)) {
> + /* sem removed */
> + goto again;
> + }
> + if (ret == -1)
> + break;
> + } while (ret != 1);
> + if (ret == 1)
> break;
> if (errno == ENOENT && retry) {
> sleep(1);
> @@ -406,11 +420,15 @@ int main(int argc, char **argv)
> err_exit("getlk_semget", errno);
> }
> } while (1);
> - do {
> - memset(&sem_ds, 0, sizeof(sem_ds));
> - semu.buf = &sem_ds;
> - ret = semctl(semid, 0, IPC_STAT, semu);
> - } while (!(ret == 0 && sem_ds.sem_otime != 0));
> +
> + /* inc sem1 to 2 (initialization completed) */
> + sop.sem_num = 1;
> + sop.sem_op = 1;
> + sop.sem_flg = 0;
> + ts.tv_sec = 5;
> + ts.tv_nsec = 0;
> + if (semtimedop(semid, &sop, 1, &ts) == -1)
> + err_exit("inc sem1 2", errno);
>
> /* wait sem0 == 0 (setlk and close fd done) */
> sop.sem_num = 0;
> @@ -418,8 +436,11 @@ int main(int argc, char **argv)
> sop.sem_flg = 0;
> ts.tv_sec = 5;
> ts.tv_nsec = 0;
> - if (semtimedop(semid, &sop, 1, &ts) == -1)
> + if (semtimedop(semid, &sop, 1, &ts) == -1) {
> + if (errno == EIDRM || errno == EINVAL)
> + goto again;
> err_exit("wait sem0 0", errno);
> + }
>
> if (fcntl(fd, getlk_macro, &flk) < 0)
> err_exit("getlk", errno);
(cc'ing Murphy)
The patch looks reasonable to me at first glance, though I confess I'm
no expert in semaphore handling.
Acked-by: Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2023-07-05 12:26 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-30 9:40 [PATCH] t_ofd_locks: fix initialization sequence Stas Sergeev
2023-07-05 12:26 ` Jeff Layton [this message]
2023-07-06 8:41 ` Murphy Zhou
2023-07-06 8:54 ` stsp
2023-07-09 9:17 ` stsp
2023-07-10 4:27 ` Murphy Zhou
2023-07-10 6:18 ` stsp
2023-07-31 11:34 ` stsp
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6ee5c9ee42388d2a2e25bf80b3d7db9c09384867.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=fstests@vger.kernel.org \
--cc=stsp2@yandex.ru \
--cc=xzhou@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox