1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2020 CTERA Networks. All Rights Reserved. 4 * 5 * Started by Amir Goldstein <amir73il@gmail.com> 6 * 7 * DESCRIPTION 8 * Check that dnotify event is reported to both parent and subdir 9 */ 10 11#include <signal.h> 12#include <stdio.h> 13#include <unistd.h> 14#include "tst_test.h" 15#include "lapi/fcntl.h" 16 17#define TEST_DIR "test_dir" 18 19#define TEST_SIG SIGRTMIN+1 20 21static int parent_fd, subdir_fd; 22static int got_parent_event, got_subdir_event; 23 24static void dnotify_handler(int sig, siginfo_t *si, void *data __attribute__((unused))) 25{ 26 if (si->si_fd == parent_fd) 27 got_parent_event = 1; 28 else if (si->si_fd == subdir_fd) 29 got_subdir_event = 1; 30 else 31 tst_brk(TBROK, "Got unexpected signal %d with si_fd %d", sig, si->si_fd); 32} 33 34static void setup_dnotify(int fd) 35{ 36 struct sigaction act; 37 38 act.sa_sigaction = dnotify_handler; 39 sigemptyset(&act.sa_mask); 40 act.sa_flags = SA_SIGINFO; 41 sigaction(TEST_SIG, &act, NULL); 42 43 TEST(fcntl(fd, F_SETSIG, TEST_SIG)); 44 if (TST_RET != 0) { 45 tst_brk(TBROK, "F_SETSIG failed errno = %d : %s", 46 TST_ERR, strerror(TST_ERR)); 47 } 48 TEST(fcntl(fd, F_NOTIFY, DN_ATTRIB|DN_MULTISHOT)); 49 if (TST_RET != 0) { 50 tst_brk(TBROK, "F_NOTIFY failed errno = %d : %s", 51 TST_ERR, strerror(TST_ERR)); 52 } 53} 54 55static void verify_dnotify(void) 56{ 57 parent_fd = SAFE_OPEN(".", O_RDONLY); 58 subdir_fd = SAFE_OPEN(TEST_DIR, O_RDONLY); 59 /* Watch "." and its children for changes */ 60 setup_dnotify(parent_fd); 61 /* Also watch subdir itself for changes */ 62 setup_dnotify(subdir_fd); 63 /* Generate DN_ATTRIB event on subdir that should send a signal on both fds */ 64 SAFE_CHMOD(TEST_DIR, 0755); 65 if (got_parent_event) 66 tst_res(TPASS, "Got event on parent as expected"); 67 else 68 tst_res(TFAIL, "Missing event on parent"); 69 if (got_subdir_event) 70 tst_res(TPASS, "Got event on subdir as expected"); 71 else 72 tst_res(TFAIL, "Missing event on subdir"); 73 SAFE_CLOSE(parent_fd); 74 SAFE_CLOSE(subdir_fd); 75} 76 77static void setup(void) 78{ 79 SAFE_MKDIR(TEST_DIR, 00700); 80} 81 82static void cleanup(void) 83{ 84 if (parent_fd > 0) 85 SAFE_CLOSE(parent_fd); 86 if (subdir_fd > 0) 87 SAFE_CLOSE(subdir_fd); 88} 89 90static struct tst_test test = { 91 .needs_tmpdir = 1, 92 .setup = setup, 93 .cleanup = cleanup, 94 .test_all = verify_dnotify, 95 .needs_kconfigs = (const char *[]) { "CONFIG_DNOTIFY=y", NULL }, 96}; 97