1/* 2 * Copyright (c) 2014 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@suse.cz> 20 * 21 * DESCRIPTION 22 * Check that fanotify overflow event is properly generated 23 * 24 * ALGORITHM 25 * Generate enough events without reading them and check that overflow 26 * event is generated. 27 */ 28#include "config.h" 29 30#include <stdio.h> 31#include <sys/stat.h> 32#include <sys/types.h> 33#include <sys/fcntl.h> 34#include <errno.h> 35#include <string.h> 36#include <sys/syscall.h> 37#include "test.h" 38#include "linux_syscall_numbers.h" 39#include "fanotify.h" 40#include "safe_macros.h" 41 42char *TCID = "fanotify05"; 43int TST_TOTAL = 1; 44 45#if defined(HAVE_SYS_FANOTIFY_H) 46#include <sys/fanotify.h> 47 48/* Currently this is fixed in kernel... */ 49#define MAX_EVENTS 16384 50 51static void setup(void); 52static void cleanup(void); 53 54#define BUF_SIZE 256 55static char fname[BUF_SIZE]; 56static int fd, fd_notify; 57 58struct fanotify_event_metadata event; 59 60int main(int ac, char **av) 61{ 62 int lc, i; 63 int len; 64 65 tst_parse_opts(ac, av, NULL, NULL); 66 67 setup(); 68 69 for (lc = 0; TEST_LOOPING(lc); lc++) { 70 /* 71 * generate events 72 */ 73 for (i = 0; i < MAX_EVENTS + 1; i++) { 74 sprintf(fname, "fname_%d", i); 75 fd = SAFE_OPEN(cleanup, fname, O_RDWR | O_CREAT, 0644); 76 SAFE_CLOSE(cleanup, fd); 77 } 78 79 while (1) { 80 /* 81 * get list on events 82 */ 83 len = read(fd_notify, &event, sizeof(event)); 84 if (len < 0) { 85 if (errno == -EAGAIN) { 86 tst_resm(TFAIL, "Overflow event not " 87 "generated!\n"); 88 break; 89 } 90 tst_brkm(TBROK | TERRNO, cleanup, 91 "read of notification event failed"); 92 break; 93 } 94 if (event.fd != FAN_NOFD) 95 close(event.fd); 96 97 /* 98 * check events 99 */ 100 if (event.mask != FAN_OPEN && 101 event.mask != FAN_Q_OVERFLOW) { 102 tst_resm(TFAIL, 103 "get event: mask=%llx (expected %llx)" 104 "pid=%u fd=%d", 105 (unsigned long long)event.mask, 106 (unsigned long long)FAN_OPEN, 107 (unsigned)event.pid, event.fd); 108 break; 109 } 110 if (event.mask == FAN_Q_OVERFLOW) { 111 if (event.fd != FAN_NOFD) { 112 tst_resm(TFAIL, 113 "invalid overflow event: " 114 "mask=%llx pid=%u fd=%d", 115 (unsigned long long)event.mask, 116 (unsigned)event.pid, 117 event.fd); 118 break; 119 } 120 tst_resm(TPASS, 121 "get event: mask=%llx pid=%u fd=%d", 122 (unsigned long long)event.mask, 123 (unsigned)event.pid, event.fd); 124 break; 125 } 126 } 127 } 128 129 cleanup(); 130 tst_exit(); 131} 132 133static void setup(void) 134{ 135 tst_sig(NOFORK, DEF_HANDLER, cleanup); 136 137 TEST_PAUSE; 138 139 tst_tmpdir(); 140 141 fd_notify = fanotify_init(FAN_CLASS_NOTIF | FAN_NONBLOCK, O_RDONLY); 142 if (fd_notify < 0) { 143 if (errno == ENOSYS) { 144 tst_brkm(TCONF, cleanup, 145 "fanotify is not configured in this kernel."); 146 } else { 147 tst_brkm(TBROK | TERRNO, cleanup, 148 "fanotify_init failed"); 149 } 150 } 151 152 if (fanotify_mark(fd_notify, FAN_MARK_MOUNT | FAN_MARK_ADD, FAN_OPEN, 153 AT_FDCWD, ".") < 0) { 154 tst_brkm(TBROK | TERRNO, cleanup, 155 "fanotify_mark (%d, FAN_MARK_MOUNT | FAN_MARK_ADD, " 156 "FAN_OPEN, AT_FDCWD, \".\") failed", 157 fd_notify); 158 } 159} 160 161static void cleanup(void) 162{ 163 if (fd_notify > 0 && close(fd_notify)) 164 tst_resm(TWARN | TERRNO, "close(%d) failed", fd_notify); 165 166 tst_rmdir(); 167} 168 169#else 170 171int main(void) 172{ 173 tst_brkm(TCONF, NULL, "system doesn't have required fanotify support"); 174} 175 176#endif 177