/** * mount a 512M btrfs block device. * and then fill the block device to the full with multi threads(ncpus+2). * and then unlink the files in the block device with multi threads. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#define PATH_MAX 512 unsigned int nthreads; static volatile int run; struct worker *workers; static int enospc_cnt; //no space count const char *homepath; struct worker { char dir[PATH_MAX]; }; #define MIN(a, b) ({\ typeof(a) _a = (a); \ typeof(b) _b = (b); \ _a < _b ? _a : _b; \ }) #define pr_err(a) do{\ printf("%s:%d:\n", __FILE__, __LINE__); \ perror(a); \ }while(0) unsigned int get_ncpus_conf() { unsigned int ncpus_conf = -1; if ( (ncpus_conf = sysconf(_SC_NPROCESSORS_CONF)) == -1 ) { pr_err("Fail to get ncpus!"); exit(1); } return ncpus_conf; } void fill_fs(const char *path) { int i = 0; char file[PATH_MAX]; char buf[4096]; size_t len; ssize_t ret; int fd; for (;;) { len = random() % (1024 * 102400); snprintf(file, sizeof(file), "%s/file%i", path, i++); printf("%s \n", file); fd = open(file, O_WRONLY | O_CREAT, 0700); if (fd == -1) { if (errno != ENOSPC) pr_err("Fail to open()"); exit(1); printf("No space to open() \n"); return; } while (len) { ret = write(fd, buf, MIN(len, sizeof(buf))); if (ret < 0) { close(fd); if (errno != ENOSPC) pr_err("Fail to write()"); printf("No space to write() \n"); return; } len -= ret; } close(fd); } } static void *worker(void *p) { struct worker *w = p; DIR *d; struct dirent *ent; char file[2*PATH_MAX]; while (run) { fill_fs(w->dir); __atomic_fetch_add(&enospc_cnt, 1, __ATOMIC_SEQ_CST); d = opendir(w->dir); while ((ent = readdir(d))) { if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; snprintf(file, sizeof(file), "%s/%s", w->dir, ent->d_name); printf("Unlinking %s \n", file); if( unlink(file) ) { pr_err("Fail to unlink"); } break; } closedir(d); } return NULL; } int main() { unsigned int i, ms; homepath = getenv("HOME"); nthreads = get_ncpus_conf() + 2; pthread_t threads[nthreads]; workers = malloc(sizeof(struct worker) * nthreads); if (!workers) { pr_err("Fail to malloc workers!"); exit(1); } for (i = 0; i < nthreads; i++) { snprintf(workers[i].dir, sizeof(workers[i].dir), \ "%s/tmpmnt/thread%i", homepath, i + 1); if( mkdir(workers[i].dir, 0700) ){ pr_err("Fail to mkdir workerdir"); exit(1); } } printf("Running %d writer threads \n", nthreads); run = 1; for (i = 0; i < nthreads; i++) { if( pthread_create(&threads[i], NULL, worker, &workers[i]) ) { pr_err("Fail to create pthread"); exit(1); } } for (ms = 0; ; ms++) { usleep(1000); if (ms >= 1000 && enospc_cnt) break; if (enospc_cnt > 100) break; } run = 0; for (i = 0; i < nthreads; i++){ if( pthread_join(threads[i], NULL) ) { pr_err("Fail to pthread_join"); } } printf("Got %d ENOSPC runtime %dms \n", enospc_cnt, ms); return 0; }