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