/* DF-3071 - tmpfs page-limit check-then-act race.
 * usage: df3071 <dir> <nthreads> <bytes_per_thread>
 * Each thread creates a file and appends 4096B writes until it has written
 * bytes_per_thread or gets an error. Prints total bytes successfully written.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>

static long total; static pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER;
static long bytes_per_thread; static const char *dirp;

static void *w(void *arg)
{
    long id=(long)arg; char p[512]; char b[4096];
    long done=0; int fd, r;
    memset(b,'x',sizeof b);
    snprintf(p,sizeof p,"%s/t%ld", dirp, id);
    fd=open(p,O_WRONLY|O_CREAT|O_TRUNC,0644);
    if (fd<0) return NULL;
    while (done < bytes_per_thread) {
        r=write(fd,b,sizeof b);
        if (r<=0) break;
        done+=r;
    }
    close(fd);
    pthread_mutex_lock(&mx); total+=done; pthread_mutex_unlock(&mx);
    return NULL;
}
int main(int argc,char**argv)
{
    pthread_t th[64]; long i,n;
    if (argc!=4){fprintf(stderr,"usage: df3071 dir nthreads bytes/thread\n");return 2;}
    dirp=argv[1]; n=atol(argv[2]); bytes_per_thread=atol(argv[3]);
    if (n>64)n=64;
    for(i=0;i<n;i++) pthread_create(&th[i],NULL,w,(void*)i);
    for(i=0;i<n;i++) pthread_join(th[i],NULL);
    printf("TOTAL_BYTES_WRITTEN=%ld\n", total);
    return 0;
}
