From: Andrew Perepechko <anserper@yandex.ru>
To: linux-fsdevel@vger.kernel.org
Cc: andrew.perepechko@seagate.com, alexey.lyashkov@seagate.com
Subject: races, getcwd vs rename
Date: Fri, 07 Oct 2016 16:48:33 +0300 [thread overview]
Message-ID: <6997257.Rh2NTvNQID@panda> (raw)
Hello!
Our applications are sometimes getting ENOENT from getcwd() though
the CWD was never really unlinked. Looking into the code of getcwd(),
it appears that the (d_unlinked(pwd.dentry)) check is not properly
protected against a concurrent d_move(), which unhashes and then
rehashes the dentry. I wrote a trivial reproducer for this issue (see below).
The reproducer gets ENOENT when a getcwd() call races with rename().
Is this the expected behaviour? My understanding is that rename() should be
atomic.
Thank you,
Andrew
root@panda:/mnt/sss# cat zzz.c
#include <pthread.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
void *thread_main(void *unused)
{
int rc;
for (;;) {
rc = rename("/tmp/t-a", "/tmp/t-b");
assert(rc == 0);
rc = rename("/tmp/t-b", "/tmp/t-a");
assert(rc == 0);
}
return NULL;
}
int main(void)
{
int rc, i;
pthread_t ptt;
rmdir("/tmp/t-a");
rmdir("/tmp/t-b");
rc = mkdir("/tmp/t-a", 0666);
assert(rc == 0);
rc = chdir("/tmp/t-a");
assert(rc == 0);
rc = pthread_create(&ptt, NULL, thread_main, NULL);
assert(rc == 0);
for (i = 0;; i++) {
char buf[100], *b;
b = getcwd(buf, sizeof(buf));
if (b == NULL) {
printf("getcwd failed on iter %d with %d\n", i,
errno);
break;
}
}
return 0;
}
root@panda:/mnt/sss# gcc -pthread zzz.c
root@panda:/mnt/sss# ./a.out
getcwd failed on iter 1225 with 2
root@panda:/mnt/sss# ./a.out
getcwd failed on iter 327 with 2
root@panda:/mnt/sss# ./a.out
getcwd failed on iter 637 with 2
reply other threads:[~2016-10-07 13:53 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=6997257.Rh2NTvNQID@panda \
--to=anserper@yandex.ru \
--cc=alexey.lyashkov@seagate.com \
--cc=andrew.perepechko@seagate.com \
--cc=linux-fsdevel@vger.kernel.org \
/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