1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2021 CTERA Networks. All Rights Reserved. 4 * 5 * Started by Amir Goldstein <amir73il@gmail.com> 6 */ 7 8/*\ 9 * [Description] 10 * 11 * Check that dnotify DN_RENAME event is reported only on rename inside same parent. 12 */ 13 14#include <fcntl.h> 15#include <signal.h> 16#include <stdio.h> 17#include <unistd.h> 18#include "tst_test.h" 19#include "lapi/fcntl.h" 20 21#define TEST_DIR "test_dir" 22#define TEST_DIR2 "test_dir2" 23#define TEST_FILE "test_file" 24 25#define TEST_SIG (SIGRTMIN+1) 26 27static int parent_fd, subdir_fd; 28static int got_parent_event, got_subdir_event; 29 30static void dnotify_handler(int sig, siginfo_t *si, void *data LTP_ATTRIBUTE_UNUSED) 31{ 32 if (si->si_fd == parent_fd) 33 got_parent_event = 1; 34 else if (si->si_fd == subdir_fd) 35 got_subdir_event = 1; 36 else 37 tst_brk(TBROK, "Got unexpected signal %d with si_fd %d", sig, si->si_fd); 38} 39 40static void setup_dnotify(int fd) 41{ 42 struct sigaction act; 43 44 act.sa_sigaction = dnotify_handler; 45 sigemptyset(&act.sa_mask); 46 act.sa_flags = SA_SIGINFO; 47 sigaction(TEST_SIG, &act, NULL); 48 49 TEST(fcntl(fd, F_SETSIG, TEST_SIG)); 50 if (TST_RET != 0) { 51 tst_brk(TBROK, "F_SETSIG failed errno = %d : %s", 52 TST_ERR, strerror(TST_ERR)); 53 } 54 55 TEST(fcntl(fd, F_NOTIFY, DN_RENAME|DN_MULTISHOT)); 56 if (TST_RET != 0) { 57 tst_brk(TBROK, "F_NOTIFY failed errno = %d : %s", 58 TST_ERR, strerror(TST_ERR)); 59 } 60} 61 62static void verify_dnotify(void) 63{ 64 parent_fd = SAFE_OPEN(".", O_RDONLY); 65 subdir_fd = SAFE_OPEN(TEST_DIR, O_RDONLY); 66 67 /* Watch renames inside ".", but not in and out of "." */ 68 setup_dnotify(parent_fd); 69 70 /* Also watch for renames inside subdir, but not in and out of subdir */ 71 setup_dnotify(subdir_fd); 72 73 /* Rename file from "." to subdir should not generate DN_RENAME on either */ 74 tst_res(TINFO, "Testing no DN_RENAME on rename from parent to subdir"); 75 SAFE_RENAME(TEST_FILE, TEST_DIR "/" TEST_FILE); 76 77 if (got_parent_event) 78 tst_res(TFAIL, "Got unexpected event on parent"); 79 else 80 tst_res(TPASS, "No event on parent as expected"); 81 82 if (got_subdir_event) 83 tst_res(TFAIL, "Got unexpected event on subdir"); 84 else 85 tst_res(TPASS, "No event on subdir as expected"); 86 87 /* Rename subdir itself should generate DN_RENAME on ".", but not on itself */ 88 tst_res(TINFO, "Testing DN_RENAME on rename of subdir itself"); 89 SAFE_RENAME(TEST_DIR, TEST_DIR2); 90 91 if (got_parent_event) 92 tst_res(TPASS, "Got event on parent as expected"); 93 else 94 tst_res(TFAIL, "Missing event on parent"); 95 96 if (got_subdir_event) 97 tst_res(TFAIL, "Got unexpected event on subdir"); 98 else 99 tst_res(TPASS, "No event on subdir as expected"); 100 101 SAFE_CLOSE(parent_fd); 102 SAFE_CLOSE(subdir_fd); 103 104 /* Cleanup before rerun */ 105 SAFE_RENAME(TEST_DIR2 "/" TEST_FILE, TEST_FILE); 106 SAFE_RENAME(TEST_DIR2, TEST_DIR); 107 got_parent_event = 0; 108 got_subdir_event = 0; 109} 110 111static void setup(void) 112{ 113 SAFE_MKDIR(TEST_DIR, 00700); 114 SAFE_TOUCH(TEST_FILE, 0666, NULL); 115} 116 117static void cleanup(void) 118{ 119 if (parent_fd > 0) 120 SAFE_CLOSE(parent_fd); 121 122 if (subdir_fd > 0) 123 SAFE_CLOSE(subdir_fd); 124} 125 126static struct tst_test test = { 127 .needs_tmpdir = 1, 128 .setup = setup, 129 .cleanup = cleanup, 130 .test_all = verify_dnotify, 131 .needs_kconfigs = (const char *[]) { "CONFIG_DNOTIFY=y", NULL }, 132}; 133