1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2018 SUSE Linux. All Rights Reserved. 4f08c3bdfSopenharmony_ci * Author: Jan Kara <jack@suse.cz> 5f08c3bdfSopenharmony_ci * Chnaged to use fzsync library by Cyril Hrubis <chrubis@suse.cz> 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * DESCRIPTION 8f08c3bdfSopenharmony_ci * Test for inotify mark connector destruction race. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * Kernels prior to 4.17 have a race when the last fsnotify mark on the inode 11f08c3bdfSopenharmony_ci * is being deleted while another process reports event happening on that 12f08c3bdfSopenharmony_ci * inode. When the race is hit, the kernel crashes or loops. 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * The problem has been fixed by commit: 15f08c3bdfSopenharmony_ci * d90a10e2444b "fsnotify: Fix fsnotify_mark_connector race" 16f08c3bdfSopenharmony_ci */ 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_ci#include "config.h" 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci#include <stdio.h> 21f08c3bdfSopenharmony_ci#include <unistd.h> 22f08c3bdfSopenharmony_ci#include <stdlib.h> 23f08c3bdfSopenharmony_ci#include <fcntl.h> 24f08c3bdfSopenharmony_ci#include <time.h> 25f08c3bdfSopenharmony_ci#include <signal.h> 26f08c3bdfSopenharmony_ci#include <sys/time.h> 27f08c3bdfSopenharmony_ci#include <sys/wait.h> 28f08c3bdfSopenharmony_ci#include <sys/syscall.h> 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#include "tst_test.h" 31f08c3bdfSopenharmony_ci#include "tst_safe_pthread.h" 32f08c3bdfSopenharmony_ci#include "tst_fuzzy_sync.h" 33f08c3bdfSopenharmony_ci#include "inotify.h" 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci#define FNAME "stress_fname" 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_ci#if defined(HAVE_SYS_INOTIFY_H) 38f08c3bdfSopenharmony_ci#include <sys/inotify.h> 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_cistatic struct tst_fzsync_pair fzsync_pair; 41f08c3bdfSopenharmony_cistatic int fd; 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_cistatic void *write_seek(void *unused) 44f08c3bdfSopenharmony_ci{ 45f08c3bdfSopenharmony_ci char buf[64]; 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci while (tst_fzsync_run_b(&fzsync_pair)) { 48f08c3bdfSopenharmony_ci tst_fzsync_start_race_b(&fzsync_pair); 49f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ANY, fd, buf, sizeof(buf)); 50f08c3bdfSopenharmony_ci SAFE_LSEEK(fd, 0, SEEK_SET); 51f08c3bdfSopenharmony_ci tst_fzsync_end_race_b(&fzsync_pair); 52f08c3bdfSopenharmony_ci } 53f08c3bdfSopenharmony_ci return unused; 54f08c3bdfSopenharmony_ci} 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cistatic void setup(void) 57f08c3bdfSopenharmony_ci{ 58f08c3bdfSopenharmony_ci fd = SAFE_OPEN(FNAME, O_CREAT | O_RDWR, 0600); 59f08c3bdfSopenharmony_ci tst_fzsync_pair_init(&fzsync_pair); 60f08c3bdfSopenharmony_ci} 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_cistatic void cleanup(void) 63f08c3bdfSopenharmony_ci{ 64f08c3bdfSopenharmony_ci if (fd > 0) 65f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci tst_fzsync_pair_cleanup(&fzsync_pair); 68f08c3bdfSopenharmony_ci} 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_cistatic void verify_inotify(void) 71f08c3bdfSopenharmony_ci{ 72f08c3bdfSopenharmony_ci int inotify_fd; 73f08c3bdfSopenharmony_ci int wd; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci inotify_fd = SAFE_MYINOTIFY_INIT1(0); 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci tst_fzsync_pair_reset(&fzsync_pair, write_seek); 78f08c3bdfSopenharmony_ci while (tst_fzsync_run_a(&fzsync_pair)) { 79f08c3bdfSopenharmony_ci wd = SAFE_MYINOTIFY_ADD_WATCH(inotify_fd, FNAME, IN_MODIFY); 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci tst_fzsync_start_race_a(&fzsync_pair); 82f08c3bdfSopenharmony_ci wd = myinotify_rm_watch(inotify_fd, wd); 83f08c3bdfSopenharmony_ci tst_fzsync_end_race_a(&fzsync_pair); 84f08c3bdfSopenharmony_ci if (wd < 0) 85f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "inotify_rm_watch() failed."); 86f08c3bdfSopenharmony_ci } 87f08c3bdfSopenharmony_ci SAFE_CLOSE(inotify_fd); 88f08c3bdfSopenharmony_ci /* We survived for given time - test succeeded */ 89f08c3bdfSopenharmony_ci tst_res(TPASS, "kernel survived inotify beating"); 90f08c3bdfSopenharmony_ci} 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_cistatic struct tst_test test = { 93f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 94f08c3bdfSopenharmony_ci .setup = setup, 95f08c3bdfSopenharmony_ci .cleanup = cleanup, 96f08c3bdfSopenharmony_ci .test_all = verify_inotify, 97f08c3bdfSopenharmony_ci .max_runtime = 150, 98f08c3bdfSopenharmony_ci .tags = (const struct tst_tag[]) { 99f08c3bdfSopenharmony_ci {"linux-git", "d90a10e2444b"}, 100f08c3bdfSopenharmony_ci {} 101f08c3bdfSopenharmony_ci } 102f08c3bdfSopenharmony_ci}; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci#else 105f08c3bdfSopenharmony_ci TST_TEST_TCONF("system doesn't have required inotify support"); 106f08c3bdfSopenharmony_ci#endif 107