1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2014 SUSE Linux. All Rights Reserved. 4 * Author: Jan Kara <jack@suse.cz> 5 * 6 * DESCRIPTION 7 * Check that inotify overflow event is properly generated 8 * 9 * ALGORITHM 10 * Generate enough events without reading them and check that overflow 11 * event is generated. 12 */ 13#include "config.h" 14 15#include <stdio.h> 16#include <sys/stat.h> 17#include <sys/types.h> 18#include <fcntl.h> 19#include <errno.h> 20#include <string.h> 21#include <sys/syscall.h> 22#include "tst_test.h" 23#include "inotify.h" 24 25#if defined(HAVE_SYS_INOTIFY_H) 26#include <sys/inotify.h> 27 28/* size of the event structure, not counting name */ 29#define EVENT_SIZE (sizeof(struct inotify_event)) 30#define EVENT_BUF_LEN (EVENT_SIZE * 16) 31 32#define BUF_SIZE 256 33static char fname[BUF_SIZE]; 34static char buf[BUF_SIZE]; 35static int fd, fd_notify; 36static int wd; 37static int max_events; 38 39static char event_buf[EVENT_BUF_LEN]; 40 41void verify_inotify(void) 42{ 43 int i; 44 int len, stop; 45 46 /* 47 * generate events 48 */ 49 fd = SAFE_OPEN(fname, O_RDWR); 50 51 for (i = 0; i < max_events; i++) { 52 SAFE_LSEEK(fd, 0, SEEK_SET); 53 SAFE_READ(1, fd, buf, BUF_SIZE); 54 SAFE_LSEEK(fd, 0, SEEK_SET); 55 SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, BUF_SIZE); 56 } 57 58 SAFE_CLOSE(fd); 59 60 stop = 0; 61 while (!stop) { 62 /* 63 * get list on events 64 */ 65 len = read(fd_notify, event_buf, EVENT_BUF_LEN); 66 if (len < 0) { 67 tst_brk(TBROK | TERRNO, 68 "read(%d, buf, %zu) failed", 69 fd_notify, EVENT_BUF_LEN); 70 } 71 72 /* 73 * check events 74 */ 75 i = 0; 76 while (i < len) { 77 struct inotify_event *event; 78 79 event = (struct inotify_event *)&event_buf[i]; 80 if (event->mask != IN_ACCESS && 81 event->mask != IN_MODIFY && 82 event->mask != IN_OPEN && 83 event->mask != IN_Q_OVERFLOW) { 84 tst_res(TFAIL, 85 "get event: wd=%d mask=%x " 86 "cookie=%u (expected 0) len=%u", 87 event->wd, event->mask, 88 event->cookie, event->len); 89 stop = 1; 90 break; 91 } 92 if (event->mask == IN_Q_OVERFLOW) { 93 if (event->len != 0 || 94 event->cookie != 0 || 95 event->wd != -1) { 96 tst_res(TFAIL, 97 "invalid overflow event: " 98 "wd=%d mask=%x " 99 "cookie=%u len=%u", 100 event->wd, event->mask, 101 event->cookie, 102 event->len); 103 stop = 1; 104 break; 105 } 106 if ((int)(i + EVENT_SIZE) != len) { 107 tst_res(TFAIL, 108 "overflow event is not last"); 109 stop = 1; 110 break; 111 } 112 tst_res(TPASS, "get event: wd=%d " 113 "mask=%x cookie=%u len=%u", 114 event->wd, event->mask, 115 event->cookie, event->len); 116 stop = 1; 117 break; 118 } 119 i += EVENT_SIZE + event->len; 120 } 121 } 122} 123 124static void setup(void) 125{ 126 sprintf(fname, "tfile_%d", getpid()); 127 fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700); 128 SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, BUF_SIZE); 129 SAFE_CLOSE(fd); 130 131 fd_notify = SAFE_MYINOTIFY_INIT1(O_NONBLOCK); 132 133 wd = SAFE_MYINOTIFY_ADD_WATCH(fd_notify, fname, IN_ALL_EVENTS); 134 135 SAFE_FILE_SCANF("/proc/sys/fs/inotify/max_queued_events", 136 "%d", &max_events); 137} 138 139static void cleanup(void) 140{ 141 if (fd_notify > 0 && myinotify_rm_watch(fd_notify, wd) == -1) { 142 tst_res(TWARN | TERRNO, "inotify_rm_watch (%d, %d) failed", 143 fd_notify, wd); 144 } 145 146 if (fd_notify > 0) 147 SAFE_CLOSE(fd_notify); 148} 149 150static struct tst_test test = { 151 .needs_tmpdir = 1, 152 .setup = setup, 153 .cleanup = cleanup, 154 .test_all = verify_inotify, 155}; 156 157#else 158 TST_TEST_TCONF("system doesn't have required inotify support"); 159#endif 160