1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/* 7f08c3bdfSopenharmony_ci * Runs several threads that fills up the filesystem repeatedly. 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci#define _GNU_SOURCE 11f08c3bdfSopenharmony_ci 12f08c3bdfSopenharmony_ci#include <stdio.h> 13f08c3bdfSopenharmony_ci#include <stdlib.h> 14f08c3bdfSopenharmony_ci#include <errno.h> 15f08c3bdfSopenharmony_ci#include <fcntl.h> 16f08c3bdfSopenharmony_ci#include <pthread.h> 17f08c3bdfSopenharmony_ci#include "tst_safe_pthread.h" 18f08c3bdfSopenharmony_ci#include "tst_test.h" 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci#define MNTPOINT "mntpoint" 21f08c3bdfSopenharmony_ci#define THREADS_DIR MNTPOINT "/subdir" 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_cistatic volatile int run; 24f08c3bdfSopenharmony_cistatic unsigned int nthreads; 25f08c3bdfSopenharmony_cistatic int enospc_cnt; 26f08c3bdfSopenharmony_cistatic struct worker *workers; 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_cistruct worker { 29f08c3bdfSopenharmony_ci enum tst_fill_access_pattern pattern; 30f08c3bdfSopenharmony_ci char dir[PATH_MAX]; 31f08c3bdfSopenharmony_ci}; 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic void *worker(void *p) 34f08c3bdfSopenharmony_ci{ 35f08c3bdfSopenharmony_ci struct worker *w = p; 36f08c3bdfSopenharmony_ci DIR *d; 37f08c3bdfSopenharmony_ci struct dirent *ent; 38f08c3bdfSopenharmony_ci char file[PATH_MAX]; 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci while (run) { 41f08c3bdfSopenharmony_ci tst_fill_fs(w->dir, 1, w->pattern); 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci tst_atomic_inc(&enospc_cnt); 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci d = SAFE_OPENDIR(w->dir); 46f08c3bdfSopenharmony_ci while ((ent = SAFE_READDIR(d))) { 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci if (!strcmp(ent->d_name, ".") || 49f08c3bdfSopenharmony_ci !strcmp(ent->d_name, "..")) 50f08c3bdfSopenharmony_ci continue; 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci snprintf(file, sizeof(file), "%s/%s", 53f08c3bdfSopenharmony_ci w->dir, ent->d_name); 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci tst_res(TINFO, "Unlinking %s", file); 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci SAFE_UNLINK(file); 58f08c3bdfSopenharmony_ci break; 59f08c3bdfSopenharmony_ci } 60f08c3bdfSopenharmony_ci SAFE_CLOSEDIR(d); 61f08c3bdfSopenharmony_ci } 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci return NULL; 64f08c3bdfSopenharmony_ci} 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_cistatic void testrun(unsigned int n) 67f08c3bdfSopenharmony_ci{ 68f08c3bdfSopenharmony_ci pthread_t threads[nthreads]; 69f08c3bdfSopenharmony_ci unsigned int i, ms; 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci tst_atomic_store(0, &enospc_cnt); 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci run = 1; 74f08c3bdfSopenharmony_ci for (i = 0; i < nthreads; i++) { 75f08c3bdfSopenharmony_ci workers[i].pattern = n; 76f08c3bdfSopenharmony_ci SAFE_PTHREAD_CREATE(&threads[i], NULL, worker, &workers[i]); 77f08c3bdfSopenharmony_ci } 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci for (ms = 0; ; ms++) { 80f08c3bdfSopenharmony_ci usleep(1000); 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci if (ms >= 1000 && tst_atomic_load(&enospc_cnt)) 83f08c3bdfSopenharmony_ci break; 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci if (tst_atomic_load(&enospc_cnt) > 100) 86f08c3bdfSopenharmony_ci break; 87f08c3bdfSopenharmony_ci } 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci run = 0; 90f08c3bdfSopenharmony_ci for (i = 0; i < nthreads; i++) 91f08c3bdfSopenharmony_ci SAFE_PTHREAD_JOIN(threads[i], NULL); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci tst_res(TPASS, "Got %i ENOSPC runtime %ims", enospc_cnt, ms); 94f08c3bdfSopenharmony_ci} 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_cistatic void setup(void) 97f08c3bdfSopenharmony_ci{ 98f08c3bdfSopenharmony_ci unsigned int i; 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci nthreads = tst_ncpus_conf() + 2; 101f08c3bdfSopenharmony_ci workers = SAFE_MALLOC(sizeof(struct worker) * nthreads); 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_ci /* 104f08c3bdfSopenharmony_ci * Avoid creating the thread directories in the root of the filesystem 105f08c3bdfSopenharmony_ci * to not hit the root entries limit on a FAT16 filesystem. 106f08c3bdfSopenharmony_ci */ 107f08c3bdfSopenharmony_ci SAFE_MKDIR(THREADS_DIR, 0700); 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci for (i = 0; i < nthreads; i++) { 110f08c3bdfSopenharmony_ci snprintf(workers[i].dir, sizeof(workers[i].dir), 111f08c3bdfSopenharmony_ci THREADS_DIR "/thread%i", i + 1); 112f08c3bdfSopenharmony_ci SAFE_MKDIR(workers[i].dir, 0700); 113f08c3bdfSopenharmony_ci } 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci tst_res(TINFO, "Running %i writer threads", nthreads); 116f08c3bdfSopenharmony_ci} 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_cistatic void cleanup(void) 119f08c3bdfSopenharmony_ci{ 120f08c3bdfSopenharmony_ci free(workers); 121f08c3bdfSopenharmony_ci} 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_cistatic struct tst_test test = { 124f08c3bdfSopenharmony_ci .max_runtime = 60, 125f08c3bdfSopenharmony_ci .needs_root = 1, 126f08c3bdfSopenharmony_ci .mount_device = 1, 127f08c3bdfSopenharmony_ci .mntpoint = MNTPOINT, 128f08c3bdfSopenharmony_ci .all_filesystems = 1, 129f08c3bdfSopenharmony_ci .setup = setup, 130f08c3bdfSopenharmony_ci .cleanup = cleanup, 131f08c3bdfSopenharmony_ci .test = testrun, 132f08c3bdfSopenharmony_ci .tcnt = 2 133f08c3bdfSopenharmony_ci}; 134