1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2008 Parallels. All Rights Reserved.
4*49cdfc7eSAndroid Build Coastguard Worker * Author: Andrew Vagin <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker */
6*49cdfc7eSAndroid Build Coastguard Worker
7*49cdfc7eSAndroid Build Coastguard Worker /*\
8*49cdfc7eSAndroid Build Coastguard Worker * [Description]
9*49cdfc7eSAndroid Build Coastguard Worker *
10*49cdfc7eSAndroid Build Coastguard Worker * Check that inotify get IN_UNMOUNT event and don't block the umount command.
11*49cdfc7eSAndroid Build Coastguard Worker */
12*49cdfc7eSAndroid Build Coastguard Worker
13*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
14*49cdfc7eSAndroid Build Coastguard Worker
15*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mount.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
18*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
20*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
22*49cdfc7eSAndroid Build Coastguard Worker #include <sys/syscall.h>
23*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
24*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
25*49cdfc7eSAndroid Build Coastguard Worker #include "inotify.h"
26*49cdfc7eSAndroid Build Coastguard Worker
27*49cdfc7eSAndroid Build Coastguard Worker #if defined(HAVE_SYS_INOTIFY_H)
28*49cdfc7eSAndroid Build Coastguard Worker #include <sys/inotify.h>
29*49cdfc7eSAndroid Build Coastguard Worker
30*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_MAX 1024
31*49cdfc7eSAndroid Build Coastguard Worker /* size of the event structure, not counting name */
32*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_SIZE (sizeof(struct inotify_event))
33*49cdfc7eSAndroid Build Coastguard Worker /* reasonable guess as to size of 1024 events */
34*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_BUF_LEN (EVENT_MAX * (EVENT_SIZE + 16))
35*49cdfc7eSAndroid Build Coastguard Worker
36*49cdfc7eSAndroid Build Coastguard Worker #define BUF_SIZE 1024
37*49cdfc7eSAndroid Build Coastguard Worker static char fname[BUF_SIZE];
38*49cdfc7eSAndroid Build Coastguard Worker static int fd, fd_notify;
39*49cdfc7eSAndroid Build Coastguard Worker static int wd;
40*49cdfc7eSAndroid Build Coastguard Worker
41*49cdfc7eSAndroid Build Coastguard Worker static unsigned int event_set[EVENT_MAX];
42*49cdfc7eSAndroid Build Coastguard Worker
43*49cdfc7eSAndroid Build Coastguard Worker static char event_buf[EVENT_BUF_LEN];
44*49cdfc7eSAndroid Build Coastguard Worker
45*49cdfc7eSAndroid Build Coastguard Worker #define DIR_MODE (S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP)
46*49cdfc7eSAndroid Build Coastguard Worker
47*49cdfc7eSAndroid Build Coastguard Worker static char *mntpoint = "mntpoint";
48*49cdfc7eSAndroid Build Coastguard Worker static int mount_flag;
49*49cdfc7eSAndroid Build Coastguard Worker
verify_inotify(void)50*49cdfc7eSAndroid Build Coastguard Worker void verify_inotify(void)
51*49cdfc7eSAndroid Build Coastguard Worker {
52*49cdfc7eSAndroid Build Coastguard Worker int ret;
53*49cdfc7eSAndroid Build Coastguard Worker int len, i, test_num;
54*49cdfc7eSAndroid Build Coastguard Worker
55*49cdfc7eSAndroid Build Coastguard Worker int test_cnt = 0;
56*49cdfc7eSAndroid Build Coastguard Worker
57*49cdfc7eSAndroid Build Coastguard Worker SAFE_MOUNT(tst_device->dev, mntpoint, tst_device->fs_type, 0, NULL);
58*49cdfc7eSAndroid Build Coastguard Worker mount_flag = 1;
59*49cdfc7eSAndroid Build Coastguard Worker
60*49cdfc7eSAndroid Build Coastguard Worker wd = SAFE_MYINOTIFY_ADD_WATCH(fd_notify, fname, IN_ALL_EVENTS);
61*49cdfc7eSAndroid Build Coastguard Worker
62*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt] = IN_UNMOUNT;
63*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
64*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt] = IN_IGNORED;
65*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
66*49cdfc7eSAndroid Build Coastguard Worker
67*49cdfc7eSAndroid Build Coastguard Worker /*check exit code from inotify_rm_watch */
68*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
69*49cdfc7eSAndroid Build Coastguard Worker
70*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "umount %s", tst_device->dev);
71*49cdfc7eSAndroid Build Coastguard Worker TEST(tst_umount(mntpoint));
72*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET != 0) {
73*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "umount(2) Failed "
74*49cdfc7eSAndroid Build Coastguard Worker "while unmounting errno = %d : %s",
75*49cdfc7eSAndroid Build Coastguard Worker TST_ERR, strerror(TST_ERR));
76*49cdfc7eSAndroid Build Coastguard Worker }
77*49cdfc7eSAndroid Build Coastguard Worker mount_flag = 0;
78*49cdfc7eSAndroid Build Coastguard Worker
79*49cdfc7eSAndroid Build Coastguard Worker len = read(fd_notify, event_buf, EVENT_BUF_LEN);
80*49cdfc7eSAndroid Build Coastguard Worker if (len < 0) {
81*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO,
82*49cdfc7eSAndroid Build Coastguard Worker "read(%d, buf, %zu) failed", fd_notify, EVENT_BUF_LEN);
83*49cdfc7eSAndroid Build Coastguard Worker }
84*49cdfc7eSAndroid Build Coastguard Worker
85*49cdfc7eSAndroid Build Coastguard Worker /* check events */
86*49cdfc7eSAndroid Build Coastguard Worker test_num = 0;
87*49cdfc7eSAndroid Build Coastguard Worker i = 0;
88*49cdfc7eSAndroid Build Coastguard Worker while (i < len) {
89*49cdfc7eSAndroid Build Coastguard Worker struct inotify_event *event;
90*49cdfc7eSAndroid Build Coastguard Worker event = (struct inotify_event *)&event_buf[i];
91*49cdfc7eSAndroid Build Coastguard Worker if (test_num >= (test_cnt - 1)) {
92*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
93*49cdfc7eSAndroid Build Coastguard Worker "get unnecessary event: wd=%d mask=%x "
94*49cdfc7eSAndroid Build Coastguard Worker "cookie=%u len=%u",
95*49cdfc7eSAndroid Build Coastguard Worker event->wd, event->mask,
96*49cdfc7eSAndroid Build Coastguard Worker event->cookie, event->len);
97*49cdfc7eSAndroid Build Coastguard Worker } else if (event_set[test_num] == event->mask) {
98*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "get event: wd=%d mask=%x"
99*49cdfc7eSAndroid Build Coastguard Worker " cookie=%u len=%u",
100*49cdfc7eSAndroid Build Coastguard Worker event->wd, event->mask,
101*49cdfc7eSAndroid Build Coastguard Worker event->cookie, event->len);
102*49cdfc7eSAndroid Build Coastguard Worker
103*49cdfc7eSAndroid Build Coastguard Worker } else {
104*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "get event: wd=%d mask=%x "
105*49cdfc7eSAndroid Build Coastguard Worker "(expected %x) cookie=%u len=%u",
106*49cdfc7eSAndroid Build Coastguard Worker event->wd, event->mask,
107*49cdfc7eSAndroid Build Coastguard Worker event_set[test_num],
108*49cdfc7eSAndroid Build Coastguard Worker event->cookie, event->len);
109*49cdfc7eSAndroid Build Coastguard Worker }
110*49cdfc7eSAndroid Build Coastguard Worker test_num++;
111*49cdfc7eSAndroid Build Coastguard Worker i += EVENT_SIZE + event->len;
112*49cdfc7eSAndroid Build Coastguard Worker }
113*49cdfc7eSAndroid Build Coastguard Worker for (; test_num < test_cnt - 1; test_num++) {
114*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "don't get event: mask=%x ",
115*49cdfc7eSAndroid Build Coastguard Worker event_set[test_num]);
116*49cdfc7eSAndroid Build Coastguard Worker
117*49cdfc7eSAndroid Build Coastguard Worker }
118*49cdfc7eSAndroid Build Coastguard Worker ret = myinotify_rm_watch(fd_notify, wd);
119*49cdfc7eSAndroid Build Coastguard Worker if (ret != -1 || errno != EINVAL)
120*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TERRNO,
121*49cdfc7eSAndroid Build Coastguard Worker "inotify_rm_watch (%d, %d) didn't return EINVAL",
122*49cdfc7eSAndroid Build Coastguard Worker fd_notify, wd);
123*49cdfc7eSAndroid Build Coastguard Worker else
124*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "inotify_rm_watch (%d, %d) returned EINVAL",
125*49cdfc7eSAndroid Build Coastguard Worker fd_notify, wd);
126*49cdfc7eSAndroid Build Coastguard Worker }
127*49cdfc7eSAndroid Build Coastguard Worker
setup(void)128*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
129*49cdfc7eSAndroid Build Coastguard Worker {
130*49cdfc7eSAndroid Build Coastguard Worker int ret;
131*49cdfc7eSAndroid Build Coastguard Worker
132*49cdfc7eSAndroid Build Coastguard Worker SAFE_MKDIR(mntpoint, DIR_MODE);
133*49cdfc7eSAndroid Build Coastguard Worker
134*49cdfc7eSAndroid Build Coastguard Worker SAFE_MOUNT(tst_device->dev, mntpoint, tst_device->fs_type, 0, NULL);
135*49cdfc7eSAndroid Build Coastguard Worker mount_flag = 1;
136*49cdfc7eSAndroid Build Coastguard Worker
137*49cdfc7eSAndroid Build Coastguard Worker sprintf(fname, "%s/tfile_%d", mntpoint, getpid());
138*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
139*49cdfc7eSAndroid Build Coastguard Worker
140*49cdfc7eSAndroid Build Coastguard Worker ret = write(fd, fname, 1);
141*49cdfc7eSAndroid Build Coastguard Worker if (ret == -1) {
142*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO,
143*49cdfc7eSAndroid Build Coastguard Worker "write(%d, %s, 1) failed", fd, fname);
144*49cdfc7eSAndroid Build Coastguard Worker }
145*49cdfc7eSAndroid Build Coastguard Worker
146*49cdfc7eSAndroid Build Coastguard Worker /* close the file we have open */
147*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
148*49cdfc7eSAndroid Build Coastguard Worker
149*49cdfc7eSAndroid Build Coastguard Worker fd_notify = SAFE_MYINOTIFY_INIT();
150*49cdfc7eSAndroid Build Coastguard Worker
151*49cdfc7eSAndroid Build Coastguard Worker tst_umount(mntpoint);
152*49cdfc7eSAndroid Build Coastguard Worker mount_flag = 0;
153*49cdfc7eSAndroid Build Coastguard Worker }
154*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)155*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
156*49cdfc7eSAndroid Build Coastguard Worker {
157*49cdfc7eSAndroid Build Coastguard Worker if (fd_notify > 0)
158*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd_notify);
159*49cdfc7eSAndroid Build Coastguard Worker
160*49cdfc7eSAndroid Build Coastguard Worker if (mount_flag) {
161*49cdfc7eSAndroid Build Coastguard Worker TEST(tst_umount(mntpoint));
162*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET != 0)
163*49cdfc7eSAndroid Build Coastguard Worker tst_res(TWARN | TTERRNO, "umount(%s) failed",
164*49cdfc7eSAndroid Build Coastguard Worker mntpoint);
165*49cdfc7eSAndroid Build Coastguard Worker }
166*49cdfc7eSAndroid Build Coastguard Worker }
167*49cdfc7eSAndroid Build Coastguard Worker
168*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
169*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1,
170*49cdfc7eSAndroid Build Coastguard Worker .format_device = 1,
171*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
172*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
173*49cdfc7eSAndroid Build Coastguard Worker .test_all = verify_inotify,
174*49cdfc7eSAndroid Build Coastguard Worker };
175*49cdfc7eSAndroid Build Coastguard Worker
176*49cdfc7eSAndroid Build Coastguard Worker #else
177*49cdfc7eSAndroid Build Coastguard Worker TST_TEST_TCONF("system doesn't have required inotify support");
178*49cdfc7eSAndroid Build Coastguard Worker #endif
179