Home | History | Annotate | Download | only in inotify
      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