1 /* 2 * Copyright (c) 2015 SUSE Linux. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * Started by Jan Kara <jack (at) suse.cz> 20 * 21 * DESCRIPTION 22 * Test for inotify mark destruction race. 23 * 24 * Kernels prior to 4.2 have a race when inode is being deleted while 25 * inotify group watching that inode is being torn down. When the race is 26 * hit, the kernel crashes or loops. 27 * 28 * The problem has been fixed by commit: 29 * 8f2f3eb59dff "fsnotify: fix oops in fsnotify_clear_marks_by_group_flags()". 30 */ 31 32 #include "config.h" 33 34 #include <stdio.h> 35 #include <unistd.h> 36 #include <stdlib.h> 37 #include <fcntl.h> 38 #include <time.h> 39 #include <signal.h> 40 #include <sys/time.h> 41 #include <sys/wait.h> 42 #include <sys/syscall.h> 43 44 #include "tst_test.h" 45 #include "inotify.h" 46 47 #if defined(HAVE_SYS_INOTIFY_H) 48 #include <sys/inotify.h> 49 50 /* Number of test loops to run the test for */ 51 #define TEARDOWNS 400 52 53 /* Number of files to test (must be > 1) */ 54 #define FILES 5 55 56 char names[FILES][PATH_MAX]; 57 58 static void setup(void) 59 { 60 int i; 61 62 for (i = 0; i < FILES; i++) 63 sprintf(names[i], "fname_%d", i); 64 } 65 66 static void verify_inotify(void) 67 { 68 int inotify_fd, fd; 69 pid_t pid; 70 int i, tests; 71 72 pid = SAFE_FORK(); 73 if (pid == 0) { 74 while (1) { 75 for (i = 0; i < FILES; i++) { 76 fd = SAFE_OPEN(names[i], O_CREAT | O_RDWR, 0600); 77 SAFE_CLOSE(fd); 78 } 79 for (i = 0; i < FILES; i++) 80 SAFE_UNLINK(names[i]); 81 } 82 } 83 84 for (tests = 0; tests < TEARDOWNS; tests++) { 85 inotify_fd = myinotify_init1(O_NONBLOCK); 86 if (inotify_fd < 0) 87 tst_brk(TBROK | TERRNO, "inotify_init failed"); 88 89 for (i = 0; i < FILES; i++) { 90 /* 91 * Both failure and success are fine since 92 * files are being deleted in parallel - this 93 * is what provokes the race we want to test 94 * for... 95 */ 96 myinotify_add_watch(inotify_fd, names[i], IN_MODIFY); 97 } 98 SAFE_CLOSE(inotify_fd); 99 } 100 /* We survived for given time - test succeeded */ 101 tst_res(TPASS, "kernel survived inotify beating"); 102 103 /* Kill the child creating / deleting files and wait for it */ 104 SAFE_KILL(pid, SIGKILL); 105 SAFE_WAIT(NULL); 106 } 107 108 static struct tst_test test = { 109 .timeout = 600, 110 .needs_tmpdir = 1, 111 .forks_child = 1, 112 .setup = setup, 113 .test_all = verify_inotify, 114 }; 115 116 #else 117 TST_TEST_TCONF("system doesn't have required inotify support"); 118 #endif 119