Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / Documentation / cgroups / cgroup_event_listener.c
1 /*
2  * cgroup_event_listener.c - Simple listener of cgroup events
3  *
4  * Copyright (C) Kirill A. Shutemov <kirill@shutemov.name>
5  */
6
7 #include <assert.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <libgen.h>
11 #include <limits.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 #include <sys/eventfd.h>
17
18 #define USAGE_STR "Usage: cgroup_event_listener <path-to-control-file> <args>\n"
19
20 int main(int argc, char **argv)
21 {
22         int efd = -1;
23         int cfd = -1;
24         int event_control = -1;
25         char event_control_path[PATH_MAX];
26         char line[LINE_MAX];
27         int ret;
28
29         if (argc != 3) {
30                 fputs(USAGE_STR, stderr);
31                 return 1;
32         }
33
34         cfd = open(argv[1], O_RDONLY);
35         if (cfd == -1) {
36                 fprintf(stderr, "Cannot open %s: %s\n", argv[1],
37                                 strerror(errno));
38                 goto out;
39         }
40
41         ret = snprintf(event_control_path, PATH_MAX, "%s/cgroup.event_control",
42                         dirname(argv[1]));
43         if (ret >= PATH_MAX) {
44                 fputs("Path to cgroup.event_control is too long\n", stderr);
45                 goto out;
46         }
47
48         event_control = open(event_control_path, O_WRONLY);
49         if (event_control == -1) {
50                 fprintf(stderr, "Cannot open %s: %s\n", event_control_path,
51                                 strerror(errno));
52                 goto out;
53         }
54
55         efd = eventfd(0, 0);
56         if (efd == -1) {
57                 perror("eventfd() failed");
58                 goto out;
59         }
60
61         ret = snprintf(line, LINE_MAX, "%d %d %s", efd, cfd, argv[2]);
62         if (ret >= LINE_MAX) {
63                 fputs("Arguments string is too long\n", stderr);
64                 goto out;
65         }
66
67         ret = write(event_control, line, strlen(line) + 1);
68         if (ret == -1) {
69                 perror("Cannot write to cgroup.event_control");
70                 goto out;
71         }
72
73         while (1) {
74                 uint64_t result;
75
76                 ret = read(efd, &result, sizeof(result));
77                 if (ret == -1) {
78                         if (errno == EINTR)
79                                 continue;
80                         perror("Cannot read from eventfd");
81                         break;
82                 }
83                 assert(ret == sizeof(result));
84
85                 ret = access(event_control_path, W_OK);
86                 if ((ret == -1) && (errno == ENOENT)) {
87                                 puts("The cgroup seems to have removed.");
88                                 ret = 0;
89                                 break;
90                 }
91
92                 if (ret == -1) {
93                         perror("cgroup.event_control "
94                                         "is not accessable any more");
95                         break;
96                 }
97
98                 printf("%s %s: crossed\n", argv[1], argv[2]);
99         }
100
101 out:
102         if (efd >= 0)
103                 close(efd);
104         if (event_control >= 0)
105                 close(event_control);
106         if (cfd >= 0)
107                 close(cfd);
108
109         return (ret != 0);
110 }