/* * stress_temp_dir_rm() * remove a temporary directory */ int stress_temp_dir_rm( const char *name, const pid_t pid, const uint32_t instance) { int ret; char tmp[PATH_MAX + 1]; stress_temp_dir(tmp, sizeof(tmp), name, pid, instance); ret = rmdir(tmp); if (ret < 0) { ret = -errno; pr_fail_err(name, "rmdir"); } return ret; }
/* * stress_chmod * stress chmod */ int stress_chmod( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t ppid = getppid(); int i, fd = -1, rc = EXIT_FAILURE, retries = 0; mode_t all_mask = 0; char filename[PATH_MAX], dirname[PATH_MAX]; /* * Allow for multiple workers to chmod the *same* file */ stress_temp_dir(dirname, sizeof(dirname), name, ppid, 0); if (mkdir(dirname, S_IRWXU) < 0) { if (errno != EEXIST) { pr_failed_err(name, "mkdir"); return EXIT_FAILURE; } } (void)stress_temp_filename(filename, sizeof(filename), name, ppid, 0, 0); do { errno = 0; /* * Try and open the file, it may be impossible momentarily * because other chmod stressors have already created it and * changed the permission bits. If so, wait a while and retry. */ if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) { if (errno == EPERM || errno == EACCES) { (void)usleep(100000); continue; } pr_failed_err(name, "open"); goto tidy; } break; } while (opt_do_run && ++retries < 100); if (retries >= 100) { pr_err(stderr, "%s: chmod: file %s took %d retries to create (instance %" PRIu32 ")\n", name, filename, retries, instance); goto tidy; } for (i = 0; modes[i]; i++) all_mask |= modes[i]; do { mode_t mask = 0; for (i = 0; modes[i]; i++) { mask |= modes[i]; if (do_fchmod(fd, i, mask, all_mask) < 0) { pr_fail(stderr, "%s: fchmod: errno=%d (%s)\n", name, errno, strerror(errno)); } if (do_chmod(filename, i, mask, all_mask) < 0) { if (errno == ENOENT || errno == ENOTDIR) { /* * File was removed during test by * another worker */ rc = EXIT_SUCCESS; goto tidy; } pr_fail(stderr, "%s: chmod: errno=%d (%s)\n", name, errno, strerror(errno)); } } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; tidy: (void)fchmod(fd, 0666); if (fd >= 0) (void)close(fd); (void)unlink(filename); (void)rmdir(dirname); return rc; }
/* * stress_filename() * stress filename sizes etc */ int stress_filename ( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { const pid_t pid = getpid(); int rc = EXIT_FAILURE; size_t sz_left, sz_max; char dirname[PATH_MAX]; char filename[PATH_MAX]; char *ptr; struct statvfs buf; size_t i, chars_allowed = 0, sz; stress_temp_dir(dirname, sizeof(dirname), name, pid, instance); if (mkdir(dirname, S_IRWXU) < 0) { if (errno != EEXIST) { pr_fail_err(name, "mkdir"); return EXIT_FAILURE; } } if (statvfs(dirname, &buf) < 0) { pr_fail_err(name, "statvfs"); goto tidy_dir; } if (instance == 0) pr_dbg(stderr, "%s: maximum file size: %lu bytes\n", name, (long unsigned) buf.f_namemax); strncpy(filename, dirname, sizeof(filename) - 1); ptr = filename + strlen(dirname); *(ptr++) = '/'; *(ptr) = '\0'; sz_left = sizeof(filename) - (ptr - filename); sz_max = (size_t)buf.f_namemax; if (sz_left >= PATH_MAX) { pr_fail(stderr, "%s: max file name larger than PATH_MAX\n", name); goto tidy_dir; } switch (filename_opt) { case STRESS_FILENAME_POSIX: strcpy(allowed, posix_allowed); chars_allowed = strlen(allowed); break; case STRESS_FILENAME_EXT: stress_filename_ext(&chars_allowed); break; case STRESS_FILENAME_PROBE: default: stress_filename_probe(name, filename, ptr, &chars_allowed); break; } if (instance == 0) pr_dbg(stdout, "%s: filesystem allows %zu unique characters in a filename\n", name, chars_allowed); if (chars_allowed == 0) { pr_fail(stderr, "%s: cannot determine allowed characters in a filename\n", name); goto tidy_dir; } i = 0; sz = 1; do { char ch = allowed[i]; size_t rnd_sz = 1 + (mwc32() % sz_max); i++; if (i >= chars_allowed) i = 0; /* Should succeed */ stress_filename_generate(ptr, 1, ch); stress_filename_test(name, filename, 1, true); stress_filename_generate_random(ptr, 1, chars_allowed); stress_filename_test(name, filename, 1, true); /* Should succeed */ stress_filename_generate(ptr, sz_max, ch); stress_filename_test(name, filename, sz_max, true); stress_filename_generate_random(ptr, sz_max, chars_allowed); stress_filename_test(name, filename, sz_max, true); /* Should succeed */ stress_filename_generate(ptr, sz_max - 1, ch); stress_filename_test(name, filename, sz_max - 1, true); stress_filename_generate_random(ptr, sz_max - 1, chars_allowed); stress_filename_test(name, filename, sz_max - 1, true); /* Should fail */ stress_filename_generate(ptr, sz_max + 1, ch); stress_filename_test(name, filename, sz_max + 1, false); stress_filename_generate_random(ptr, sz_max + 1, chars_allowed); stress_filename_test(name, filename, sz_max + 1, false); /* Should succeed */ stress_filename_generate(ptr, sz, ch); stress_filename_test(name, filename, sz, true); stress_filename_generate_random(ptr, sz, chars_allowed); stress_filename_test(name, filename, sz, true); /* Should succeed */ stress_filename_generate(ptr, rnd_sz, ch); stress_filename_test(name, filename, rnd_sz, true); stress_filename_generate_random(ptr, rnd_sz, chars_allowed); stress_filename_test(name, filename, rnd_sz, true); sz++; if (sz > sz_max) sz = 1; } while (opt_do_run && (!max_ops || *counter < max_ops)); rc = EXIT_SUCCESS; tidy_dir: (void)rmdir(dirname); return rc; }