1 Star 0 Fork 2

HoperunHarmony / stress-ng

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
stress-file-ioctl.c 10.97 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
/*
* Copyright (C) 2013-2021 Canonical, Ltd.
* Copyright (C) 2022 Colin Ian King.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "stress-ng.h"
#if defined(HAVE_LINUX_FS_H)
#include <linux/fs.h>
#endif
static const stress_help_t help[] = {
{ NULL, "file-ioctl N", "start N workers exercising file specific ioctls" },
{ NULL, "file-ioctl-ops N", "stop after N file ioctl bogo operations" },
{ NULL, NULL, NULL }
};
#if (defined(FIONBIO) && defined(O_NONBLOCK)) || \
(defined(FIOASYNC) && defined(O_ASYNC))
static void check_flag(
const stress_args_t *args,
const char *ioctl_name,
const int fd,
const int flag,
const int ret,
const bool set)
{
#if defined(F_GETFL)
if (ret == 0) {
int flags;
flags = fcntl(fd, F_GETFL, 0);
/*
* The fcntl failed, so checking is not a valid
* thing to sanity check with.
*/
if (errno != 0)
return;
if ((set && !(flags & flag)) ||
(!set && (flags & flag)))
pr_fail("%s: ioctl %s failed, unexpected flags when checked with F_GETFL\n",
args->name, ioctl_name);
}
#else
(void)args;
(void)ioctl_name;
(void)fd;
(void)flag;
(void)ret;
#endif
}
#endif
/*
* stress_file_ioctl
* stress file ioctls
*/
static int stress_file_ioctl(const stress_args_t *args)
{
char filename[PATH_MAX];
int ret, fd;
const int bad_fd = stress_get_bad_fd();
#if defined(FICLONE) || defined(FICLONERANGE)
int dfd;
#endif
const off_t file_sz = 8192;
uint32_t rnd = stress_mwc32();
ret = stress_temp_dir_mk_args(args);
if (ret < 0)
return exit_status(-ret);
(void)stress_temp_filename_args(args, filename, sizeof(filename), rnd);
fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0) {
ret = exit_status(errno);
pr_err("%s: cannot create %s\n", args->name, filename);
(void)stress_temp_dir_rm_args(args);
return ret;
}
(void)shim_unlink(filename);
#if defined(FICLONE) || defined(FICLONERANGE)
(void)stress_temp_filename_args(args, filename, sizeof(filename), rnd + 1);
dfd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (dfd < 0) {
ret = exit_status(errno);
(void)close(fd);
(void)stress_temp_dir_rm_args(args);
pr_err("%s: cannot create %s\n", args->name, filename);
return ret;
}
(void)shim_unlink(filename);
#endif
(void)shim_fallocate(fd, 0, 0, file_sz);
#if defined(FICLONE) || defined(FICLONERANGE)
(void)shim_fallocate(dfd, 0, 0, file_sz);
#endif
(void)shim_fsync(fd);
(void)bad_fd;
stress_set_proc_state(args->name, STRESS_STATE_RUN);
do {
int exercised = 0;
#if defined(FIOCLEX)
{
ret = ioctl(fd, FIOCLEX);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FIONCLEX)
{
ret = ioctl(fd, FIONCLEX);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FIONBIO)
{
int opt;
opt = 1;
ret = ioctl(fd, FIONBIO, &opt);
#if defined(O_NONBLOCK)
check_flag(args, "FIONBIO", fd, O_NONBLOCK, ret, true);
#else
(void)ret;
#endif
opt = 0;
ret = ioctl(fd, FIONBIO, &opt);
#if defined(O_NONBLOCK)
check_flag(args, "FIONBIO", fd, O_NONBLOCK, ret, false);
#else
(void)ret;
#endif
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FIOASYNC)
{
int opt;
opt = 1;
ret = ioctl(fd, FIOASYNC, &opt);
#if defined(O_ASYNC)
check_flag(args, "FIONASYNC", fd, O_ASYNC, ret, true);
#else
(void)ret;
#endif
opt = 0;
ret = ioctl(fd, FIOASYNC, &opt);
#if defined(O_ASYNC)
check_flag(args, "FIONASYNC", fd, O_ASYNC, ret, false);
#else
(void)ret;
#endif
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FIOQSIZE)
{
shim_loff_t sz;
struct stat buf;
ret = fstat(fd, &buf);
if (ret == 0) {
ret = ioctl(fd, FIOQSIZE, &sz);
if ((ret == 0) && (file_sz != buf.st_size))
pr_fail("%s: ioctl FIOQSIZE failed, size %jd (filesize) vs %jd (reported)\n",
args->name,
(intmax_t)file_sz, (intmax_t)sz);
}
exercised++;
}
#else
UNEXPECTED
#endif
/* Disable this at the moment, it is fragile */
#if 0
#if defined(FIFREEZE) && \
defined(FITHAW)
{
ret = ioctl(fd, FIFREEZE);
(void)ret;
ret = ioctl(fd, FITHAW);
(void)ret;
exercised++;
}
#endif
#else
/* UNEXPECTED */
#endif
#if defined(FIGETBSZ)
{
int isz;
ret = ioctl(fd, FIGETBSZ, &isz);
if ((ret == 0) && (isz < 1))
pr_fail("%s: ioctl FIGETBSZ returned unusual block size %d\n",
args->name, isz);
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FICLONE)
{
ret = ioctl(dfd, FICLONE, fd);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FICLONERANGE)
{
struct file_clone_range fcr;
(void)memset(&fcr, 0, sizeof(fcr));
fcr.src_fd = fd;
fcr.src_offset = 0;
fcr.src_length = file_sz;
fcr.dest_offset = 0;
ret = ioctl(dfd, FICLONERANGE, &fcr);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FIDEDUPERANGE)
{
const size_t sz = sizeof(struct file_dedupe_range) +
sizeof(struct file_dedupe_range_info);
char buf[sz] ALIGNED(64);
struct file_dedupe_range *d = (struct file_dedupe_range *)buf;
d->src_offset = 0;
d->src_length = file_sz;
d->dest_count = 1;
d->reserved1 = 0;
d->reserved2 = 0;
d->info[0].dest_fd = dfd;
d->info[0].dest_offset = 0;
/* Zero the return values */
d->info[0].bytes_deduped = 0;
d->info[0].status = 0;
d->info[0].reserved = 0;
ret = ioctl(fd, FIDEDUPERANGE, d);
(void)ret;
/*
* and exercise illegal dest_count to force an
* ENOMEM error
*/
d->dest_count = (uint16_t)~0U;
ret = ioctl(fd, FIDEDUPERANGE, d);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FIONREAD)
{
int isz = 0;
ret = ioctl(fd, FIONREAD, &isz);
(void)ret;
exercised++;
/*
* exercise invalid fd
*/
ret = ioctl(bad_fd, FIONREAD, &isz);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FS_IOC_GETVERSION)
{
int ver;
ret = ioctl(fd, FS_IOC_GETVERSION, &ver);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(HAVE_LINUX_FS_H) && \
defined(HAVE_FSXATTR_STRUCT) && \
defined(FS_IOC_FSGETXATTR)
{
struct fsxattr xattr;
ret = ioctl(fd, FS_IOC_FSGETXATTR, &xattr);
#if defined(FS_IOC_FSSETXATTR)
if (ret == 0)
ret = ioctl(fd, FS_IOC_FSSETXATTR, &xattr);
#endif
(void)ret;
}
#endif
#if defined(_IOW) && \
defined(__linux__)
/*
* These will eventually be in linux/falloc.h for libc, but
* define a shim version for now.
*/
struct shim_space_resv {
int16_t l_type;
int16_t l_whence;
int64_t l_start;
int64_t l_len;
int32_t l_sysid;
uint32_t l_pid;
int32_t l_pad[4];
};
#if !defined(FS_IOC_RESVSP) && \
defined(_IOW)
#define FS_IOC_RESVSP _IOW('X', 40, struct shim_space_resv)
#endif
#if !defined(FS_IOC_UNRESVSP) && \
defined(_IOW)
#define FS_IOC_UNRESVSP _IOW('X', 41, struct shim_space_resv)
#endif
#if !defined(FS_IOC_RESVSP64) && \
defined(_IOW)
#define FS_IOC_RESVSP64 _IOW('X', 42, struct shim_space_resv)
#endif
#if !defined(FS_IOC_UNRESVSP64) && \
defined(_IOW)
#define FS_IOC_UNRESVSP64 _IOW('X', 43, struct shim_space_resv)
#endif
#if !defined(FS_IOC_ZERO_RANGE) && \
defined(_IOW)
#define FS_IOC_ZERO_RANGE _IOW('X', 57, struct shim_space_resv)
#endif
#if defined(FS_IOC_RESVSP)
{
struct shim_space_resv r;
(void)memset(&r, 0, sizeof(r));
r.l_whence = SEEK_SET;
r.l_start = (int64_t)0;
r.l_len = (int64_t)file_sz * 2;
ret = ioctl(fd, FS_IOC_RESVSP, &r);
(void)ret;
if (lseek(fd, (off_t)0, SEEK_SET) != (off_t)-1) {
(void)memset(&r, 0, sizeof(r));
r.l_whence = SEEK_CUR;
r.l_start = (int64_t)0;
r.l_len = (int64_t)file_sz;
ret = ioctl(fd, FS_IOC_RESVSP, &r);
(void)ret;
(void)memset(&r, 0, sizeof(r));
r.l_whence = SEEK_END;
r.l_start = (int64_t)0;
r.l_len = (int64_t)1;
ret = ioctl(fd, FS_IOC_RESVSP, &r);
(void)ret;
}
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FS_IOC_RESVSP64)
{
struct shim_space_resv r;
(void)memset(&r, 0, sizeof(r));
r.l_whence = SEEK_SET;
r.l_start = (int64_t)0;
r.l_len = (int64_t)file_sz * 2;
ret = ioctl(fd, FS_IOC_RESVSP64, &r);
(void)ret;
if (lseek(fd, (off_t)0, SEEK_SET) != (off_t)-1) {
(void)memset(&r, 0, sizeof(r));
r.l_whence = SEEK_CUR;
r.l_start = (int64_t)0;
r.l_len = (int64_t)file_sz;
ret = ioctl(fd, FS_IOC_RESVSP64, &r);
(void)ret;
(void)memset(&r, 0, sizeof(r));
r.l_whence = SEEK_END;
r.l_start = (int64_t)0;
r.l_len = (int64_t)1;
ret = ioctl(fd, FS_IOC_RESVSP64, &r);
(void)ret;
}
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FS_IOC_UNRESVSP)
{
struct shim_space_resv r;
(void)memset(&r, 0, sizeof(r));
r.l_whence = SEEK_SET;
r.l_start = (int64_t)file_sz;
r.l_len = (int64_t)file_sz * 2;
ret = ioctl(fd, FS_IOC_UNRESVSP, &r);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FS_IOC_UNRESVSP64)
{
struct shim_space_resv r;
(void)memset(&r, 0, sizeof(r));
r.l_whence = SEEK_SET;
r.l_start = (int64_t)file_sz;
r.l_len = (int64_t)file_sz * 2;
ret = ioctl(fd, FS_IOC_UNRESVSP64, &r);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#if defined(FS_IOC_ZERO_RANGE)
{
struct shim_space_resv r;
(void)memset(&r, 0, sizeof(r));
r.l_whence = SEEK_SET;
r.l_start = (int64_t)0;
r.l_len = (int64_t)file_sz / 2;
ret = ioctl(fd, FS_IOC_ZERO_RANGE, &r);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
#endif
#if defined(FIBMAP)
{
int block;
block = 0;
ret = ioctl(fd, FIBMAP, &block);
(void)ret;
/*
* and exercise huge block request
* that should return -ERANGE or -EINVAL;
*/
block = -1;
ret = ioctl(fd, FIBMAP, &block);
(void)ret;
exercised++;
}
#else
UNEXPECTED
#endif
if (!exercised) { /* cppcheck-suppress knownConditionTrueFalse */
pr_inf("%s: no available file ioctls to exercise\n",
args->name);
ret = EXIT_NOT_IMPLEMENTED;
goto tidy;
}
inc_counter(args);
} while (keep_stressing(args));
ret = EXIT_SUCCESS;
tidy:
stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
#if defined(FICLONE) || defined(FICLONERANGE)
(void)close(dfd);
#endif
(void)close(fd);
(void)stress_temp_dir_rm_args(args);
return ret;
}
stressor_info_t stress_file_ioctl_info = {
.stressor = stress_file_ioctl,
.class = CLASS_FILESYSTEM | CLASS_OS,
.verify = VERIFY_ALWAYS,
.help = help
};
1
https://gitee.com/hoperun_harmony/stress-ng.git
git@gitee.com:hoperun_harmony/stress-ng.git
hoperun_harmony
stress-ng
stress-ng
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891