public inbox for linux-fsdevel@vger.kernel.org
 help / color / mirror / Atom feed
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