From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from forward4h.cmail.yandex.net ([87.250.230.101]:34753 "EHLO forward4h.cmail.yandex.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751294AbcJGNxl (ORCPT ); Fri, 7 Oct 2016 09:53:41 -0400 From: Andrew Perepechko 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 Message-ID: <6997257.Rh2NTvNQID@panda> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Sender: linux-fsdevel-owner@vger.kernel.org List-ID: 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 #include #include #include #include #include #include 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