/* DF-3071 node-limit check-then-act race.
 * usage: df3071b <dir> <nthreads> <files_per_thread>
 * barrier-start; each thread creates empty files until error or quota.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
static const char *dirp; static int files_each; static volatile int go=0;
static long total=0; static pthread_mutex_t mx=PTHREAD_MUTEX_INITIALIZER;
static void *w(void *arg){
    long id=(long)arg; char p[512]; int i,n=0;
    while(!go) usleep(100);
    for(i=0;i<files_each;i++){
        snprintf(p,sizeof p,"%s/n%ld_%d",dirp,id,i);
        int fd=open(p,O_CREAT|O_EXCL,0644);
        if(fd<0) break;
        close(fd); n++;
    }
    pthread_mutex_lock(&mx); total+=n; pthread_mutex_unlock(&mx);
    return NULL;
}
int main(int argc,char**argv){
    pthread_t th[128]; long i,n;
    if(argc!=4){fprintf(stderr,"usage: df3071b dir nthreads files_each\n");return 2;}
    dirp=argv[1]; n=atol(argv[2]); files_each=atoi(argv[3]);
    if(n>128)n=128;
    for(i=0;i<n;i++) pthread_create(&th[i],NULL,w,(void*)i);
    usleep(50000); go=1;
    for(i=0;i<n;i++) pthread_join(th[i],NULL);
    printf("TOTAL_FILES_CREATED=%ld\n",total);
    return 0;
}
