1*a8c52ebaSWaiman Long // SPDX-License-Identifier: GPL-2.0 2*a8c52ebaSWaiman Long /* 3*a8c52ebaSWaiman Long * Wait until an inotify event on the given cgroup file. 4*a8c52ebaSWaiman Long */ 5*a8c52ebaSWaiman Long #include <linux/limits.h> 6*a8c52ebaSWaiman Long #include <sys/inotify.h> 7*a8c52ebaSWaiman Long #include <sys/mman.h> 8*a8c52ebaSWaiman Long #include <sys/ptrace.h> 9*a8c52ebaSWaiman Long #include <sys/stat.h> 10*a8c52ebaSWaiman Long #include <sys/types.h> 11*a8c52ebaSWaiman Long #include <errno.h> 12*a8c52ebaSWaiman Long #include <fcntl.h> 13*a8c52ebaSWaiman Long #include <poll.h> 14*a8c52ebaSWaiman Long #include <stdio.h> 15*a8c52ebaSWaiman Long #include <stdlib.h> 16*a8c52ebaSWaiman Long #include <string.h> 17*a8c52ebaSWaiman Long #include <unistd.h> 18*a8c52ebaSWaiman Long 19*a8c52ebaSWaiman Long static const char usage[] = "Usage: %s [-v] <cgroup_file>\n"; 20*a8c52ebaSWaiman Long static char *file; 21*a8c52ebaSWaiman Long static int verbose; 22*a8c52ebaSWaiman Long 23*a8c52ebaSWaiman Long static inline void fail_message(char *msg) 24*a8c52ebaSWaiman Long { 25*a8c52ebaSWaiman Long fprintf(stderr, msg, file); 26*a8c52ebaSWaiman Long exit(1); 27*a8c52ebaSWaiman Long } 28*a8c52ebaSWaiman Long 29*a8c52ebaSWaiman Long int main(int argc, char *argv[]) 30*a8c52ebaSWaiman Long { 31*a8c52ebaSWaiman Long char *cmd = argv[0]; 32*a8c52ebaSWaiman Long int c, fd; 33*a8c52ebaSWaiman Long struct pollfd fds = { .events = POLLIN, }; 34*a8c52ebaSWaiman Long 35*a8c52ebaSWaiman Long while ((c = getopt(argc, argv, "v")) != -1) { 36*a8c52ebaSWaiman Long switch (c) { 37*a8c52ebaSWaiman Long case 'v': 38*a8c52ebaSWaiman Long verbose++; 39*a8c52ebaSWaiman Long break; 40*a8c52ebaSWaiman Long } 41*a8c52ebaSWaiman Long argv++, argc--; 42*a8c52ebaSWaiman Long } 43*a8c52ebaSWaiman Long 44*a8c52ebaSWaiman Long if (argc != 2) { 45*a8c52ebaSWaiman Long fprintf(stderr, usage, cmd); 46*a8c52ebaSWaiman Long return -1; 47*a8c52ebaSWaiman Long } 48*a8c52ebaSWaiman Long file = argv[1]; 49*a8c52ebaSWaiman Long fd = open(file, O_RDONLY); 50*a8c52ebaSWaiman Long if (fd < 0) 51*a8c52ebaSWaiman Long fail_message("Cgroup file %s not found!\n"); 52*a8c52ebaSWaiman Long close(fd); 53*a8c52ebaSWaiman Long 54*a8c52ebaSWaiman Long fd = inotify_init(); 55*a8c52ebaSWaiman Long if (fd < 0) 56*a8c52ebaSWaiman Long fail_message("inotify_init() fails on %s!\n"); 57*a8c52ebaSWaiman Long if (inotify_add_watch(fd, file, IN_MODIFY) < 0) 58*a8c52ebaSWaiman Long fail_message("inotify_add_watch() fails on %s!\n"); 59*a8c52ebaSWaiman Long fds.fd = fd; 60*a8c52ebaSWaiman Long 61*a8c52ebaSWaiman Long /* 62*a8c52ebaSWaiman Long * poll waiting loop 63*a8c52ebaSWaiman Long */ 64*a8c52ebaSWaiman Long for (;;) { 65*a8c52ebaSWaiman Long int ret = poll(&fds, 1, 10000); 66*a8c52ebaSWaiman Long 67*a8c52ebaSWaiman Long if (ret < 0) { 68*a8c52ebaSWaiman Long if (errno == EINTR) 69*a8c52ebaSWaiman Long continue; 70*a8c52ebaSWaiman Long perror("poll"); 71*a8c52ebaSWaiman Long exit(1); 72*a8c52ebaSWaiman Long } 73*a8c52ebaSWaiman Long if ((ret > 0) && (fds.revents & POLLIN)) 74*a8c52ebaSWaiman Long break; 75*a8c52ebaSWaiman Long } 76*a8c52ebaSWaiman Long if (verbose) { 77*a8c52ebaSWaiman Long struct inotify_event events[10]; 78*a8c52ebaSWaiman Long long len; 79*a8c52ebaSWaiman Long 80*a8c52ebaSWaiman Long usleep(1000); 81*a8c52ebaSWaiman Long len = read(fd, events, sizeof(events)); 82*a8c52ebaSWaiman Long printf("Number of events read = %ld\n", 83*a8c52ebaSWaiman Long len/sizeof(struct inotify_event)); 84*a8c52ebaSWaiman Long } 85*a8c52ebaSWaiman Long close(fd); 86*a8c52ebaSWaiman Long return 0; 87*a8c52ebaSWaiman Long } 88