linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* races, getcwd vs rename
@ 2016-10-07 13:48 Andrew Perepechko
  0 siblings, 0 replies; only message in thread
From: Andrew Perepechko @ 2016-10-07 13:48 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: andrew.perepechko, alexey.lyashkov

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



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2016-10-07 13:53 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-07 13:48 races, getcwd vs rename Andrew Perepechko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).