1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved.
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci * Started by Matthew Bobrowski <mbobrowski@mbobrowski.org>
6f08c3bdfSopenharmony_ci */
7f08c3bdfSopenharmony_ci
8f08c3bdfSopenharmony_ci/*\
9f08c3bdfSopenharmony_ci * [Description]
10f08c3bdfSopenharmony_ci * Validate that the values returned within an event when FAN_REPORT_FID is
11f08c3bdfSopenharmony_ci * specified matches those that are obtained via explicit invocation to system
12f08c3bdfSopenharmony_ci * calls statfs(2) and name_to_handle_at(2).
13f08c3bdfSopenharmony_ci */
14f08c3bdfSopenharmony_ci
15f08c3bdfSopenharmony_ci/*
16f08c3bdfSopenharmony_ci * This is also regression test for:
17f08c3bdfSopenharmony_ci *     c285a2f01d69 ("fanotify: update connector fsid cache on add mark")
18f08c3bdfSopenharmony_ci */
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci#define _GNU_SOURCE
21f08c3bdfSopenharmony_ci#include "config.h"
22f08c3bdfSopenharmony_ci
23f08c3bdfSopenharmony_ci#include <stdio.h>
24f08c3bdfSopenharmony_ci#include <string.h>
25f08c3bdfSopenharmony_ci#include <sys/statfs.h>
26f08c3bdfSopenharmony_ci#include <sys/types.h>
27f08c3bdfSopenharmony_ci#include <sys/stat.h>
28f08c3bdfSopenharmony_ci#include <sys/mount.h>
29f08c3bdfSopenharmony_ci#include <errno.h>
30f08c3bdfSopenharmony_ci#include <unistd.h>
31f08c3bdfSopenharmony_ci#include "tst_test.h"
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ci#ifdef HAVE_SYS_FANOTIFY_H
34f08c3bdfSopenharmony_ci#include "fanotify.h"
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci#define PATH_LEN 128
37f08c3bdfSopenharmony_ci#define BUF_SIZE 256
38f08c3bdfSopenharmony_ci#define DIR_ONE "dir_one"
39f08c3bdfSopenharmony_ci#define FILE_ONE "file_one"
40f08c3bdfSopenharmony_ci#define FILE_TWO "file_two"
41f08c3bdfSopenharmony_ci#define MOUNT_PATH "tstmnt"
42f08c3bdfSopenharmony_ci#define EVENT_MAX ARRAY_SIZE(objects)
43f08c3bdfSopenharmony_ci#define DIR_PATH_ONE MOUNT_PATH"/"DIR_ONE
44f08c3bdfSopenharmony_ci#define FILE_PATH_ONE MOUNT_PATH"/"FILE_ONE
45f08c3bdfSopenharmony_ci#define FILE_PATH_TWO MOUNT_PATH"/"FILE_TWO
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_ci#if defined(HAVE_NAME_TO_HANDLE_AT)
48f08c3bdfSopenharmony_cistruct event_t {
49f08c3bdfSopenharmony_ci	unsigned long long expected_mask;
50f08c3bdfSopenharmony_ci};
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_cistatic struct object_t {
53f08c3bdfSopenharmony_ci	const char *path;
54f08c3bdfSopenharmony_ci	int is_dir;
55f08c3bdfSopenharmony_ci	struct fanotify_fid_t fid;
56f08c3bdfSopenharmony_ci} objects[] = {
57f08c3bdfSopenharmony_ci	{FILE_PATH_ONE, 0, {}},
58f08c3bdfSopenharmony_ci	{FILE_PATH_TWO, 0, {}},
59f08c3bdfSopenharmony_ci	{DIR_PATH_ONE, 1, {}}
60f08c3bdfSopenharmony_ci};
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_cistatic struct test_case_t {
63f08c3bdfSopenharmony_ci	struct fanotify_mark_type mark;
64f08c3bdfSopenharmony_ci	unsigned long long mask;
65f08c3bdfSopenharmony_ci} test_cases[] = {
66f08c3bdfSopenharmony_ci	{
67f08c3bdfSopenharmony_ci		INIT_FANOTIFY_MARK_TYPE(INODE),
68f08c3bdfSopenharmony_ci		FAN_OPEN | FAN_CLOSE_NOWRITE
69f08c3bdfSopenharmony_ci	},
70f08c3bdfSopenharmony_ci	{
71f08c3bdfSopenharmony_ci		INIT_FANOTIFY_MARK_TYPE(INODE),
72f08c3bdfSopenharmony_ci		FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR
73f08c3bdfSopenharmony_ci	},
74f08c3bdfSopenharmony_ci	{
75f08c3bdfSopenharmony_ci		INIT_FANOTIFY_MARK_TYPE(MOUNT),
76f08c3bdfSopenharmony_ci		FAN_OPEN | FAN_CLOSE_NOWRITE
77f08c3bdfSopenharmony_ci	},
78f08c3bdfSopenharmony_ci	{
79f08c3bdfSopenharmony_ci		INIT_FANOTIFY_MARK_TYPE(MOUNT),
80f08c3bdfSopenharmony_ci		FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR
81f08c3bdfSopenharmony_ci	},
82f08c3bdfSopenharmony_ci	{
83f08c3bdfSopenharmony_ci		INIT_FANOTIFY_MARK_TYPE(FILESYSTEM),
84f08c3bdfSopenharmony_ci		FAN_OPEN | FAN_CLOSE_NOWRITE
85f08c3bdfSopenharmony_ci	},
86f08c3bdfSopenharmony_ci	{
87f08c3bdfSopenharmony_ci		INIT_FANOTIFY_MARK_TYPE(FILESYSTEM),
88f08c3bdfSopenharmony_ci		FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR
89f08c3bdfSopenharmony_ci	}
90f08c3bdfSopenharmony_ci};
91f08c3bdfSopenharmony_ci
92f08c3bdfSopenharmony_cistatic int ovl_mounted;
93f08c3bdfSopenharmony_cistatic int bind_mounted;
94f08c3bdfSopenharmony_cistatic int nofid_fd;
95f08c3bdfSopenharmony_cistatic int fanotify_fd;
96f08c3bdfSopenharmony_cistatic int filesystem_mark_unsupported;
97f08c3bdfSopenharmony_cistatic char events_buf[BUF_SIZE];
98f08c3bdfSopenharmony_cistatic struct event_t event_set[EVENT_MAX];
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_cistatic void create_objects(void)
101f08c3bdfSopenharmony_ci{
102f08c3bdfSopenharmony_ci	unsigned int i;
103f08c3bdfSopenharmony_ci
104f08c3bdfSopenharmony_ci	for (i = 0; i < ARRAY_SIZE(objects); i++) {
105f08c3bdfSopenharmony_ci		if (objects[i].is_dir)
106f08c3bdfSopenharmony_ci			SAFE_MKDIR(objects[i].path, 0755);
107f08c3bdfSopenharmony_ci		else
108f08c3bdfSopenharmony_ci			SAFE_FILE_PRINTF(objects[i].path, "0");
109f08c3bdfSopenharmony_ci	}
110f08c3bdfSopenharmony_ci}
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_cistatic void get_object_stats(void)
113f08c3bdfSopenharmony_ci{
114f08c3bdfSopenharmony_ci	unsigned int i;
115f08c3bdfSopenharmony_ci
116f08c3bdfSopenharmony_ci	for (i = 0; i < ARRAY_SIZE(objects); i++)
117f08c3bdfSopenharmony_ci		fanotify_save_fid(objects[i].path, &objects[i].fid);
118f08c3bdfSopenharmony_ci}
119f08c3bdfSopenharmony_ci
120f08c3bdfSopenharmony_cistatic int setup_marks(unsigned int fd, struct test_case_t *tc)
121f08c3bdfSopenharmony_ci{
122f08c3bdfSopenharmony_ci	unsigned int i;
123f08c3bdfSopenharmony_ci	struct fanotify_mark_type *mark = &tc->mark;
124f08c3bdfSopenharmony_ci
125f08c3bdfSopenharmony_ci	for (i = 0; i < ARRAY_SIZE(objects); i++) {
126f08c3bdfSopenharmony_ci		SAFE_FANOTIFY_MARK(fd, FAN_MARK_ADD | mark->flag, tc->mask,
127f08c3bdfSopenharmony_ci				   AT_FDCWD, objects[i].path);
128f08c3bdfSopenharmony_ci
129f08c3bdfSopenharmony_ci		/* Setup the expected mask for each generated event */
130f08c3bdfSopenharmony_ci		event_set[i].expected_mask = tc->mask;
131f08c3bdfSopenharmony_ci		if (!objects[i].is_dir)
132f08c3bdfSopenharmony_ci			event_set[i].expected_mask &= ~FAN_ONDIR;
133f08c3bdfSopenharmony_ci	}
134f08c3bdfSopenharmony_ci	return 0;
135f08c3bdfSopenharmony_ci}
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_cistatic void do_test(unsigned int number)
138f08c3bdfSopenharmony_ci{
139f08c3bdfSopenharmony_ci	unsigned int i;
140f08c3bdfSopenharmony_ci	int len, fds[ARRAY_SIZE(objects)];
141f08c3bdfSopenharmony_ci
142f08c3bdfSopenharmony_ci	struct file_handle *event_file_handle;
143f08c3bdfSopenharmony_ci	struct fanotify_event_metadata *metadata;
144f08c3bdfSopenharmony_ci	struct fanotify_event_info_fid *event_fid;
145f08c3bdfSopenharmony_ci	struct test_case_t *tc = &test_cases[number];
146f08c3bdfSopenharmony_ci	struct fanotify_mark_type *mark = &tc->mark;
147f08c3bdfSopenharmony_ci
148f08c3bdfSopenharmony_ci	tst_res(TINFO,
149f08c3bdfSopenharmony_ci		"Test #%d.%d: FAN_REPORT_FID with mark flag: %s",
150f08c3bdfSopenharmony_ci		number, tst_variant, mark->name);
151f08c3bdfSopenharmony_ci
152f08c3bdfSopenharmony_ci	if (tst_variant && !ovl_mounted) {
153f08c3bdfSopenharmony_ci		tst_res(TCONF, "overlayfs not supported on %s", tst_device->fs_type);
154f08c3bdfSopenharmony_ci		return;
155f08c3bdfSopenharmony_ci	}
156f08c3bdfSopenharmony_ci
157f08c3bdfSopenharmony_ci	if (filesystem_mark_unsupported && mark->flag & FAN_MARK_FILESYSTEM) {
158f08c3bdfSopenharmony_ci		tst_res(TCONF, "FAN_MARK_FILESYSTEM not supported in kernel?");
159f08c3bdfSopenharmony_ci		return;
160f08c3bdfSopenharmony_ci	}
161f08c3bdfSopenharmony_ci
162f08c3bdfSopenharmony_ci	fanotify_fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF | FAN_REPORT_FID, O_RDONLY);
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_ci	/*
165f08c3bdfSopenharmony_ci	 * Place marks on a set of objects and setup the expected masks
166f08c3bdfSopenharmony_ci	 * for each event that is expected to be generated.
167f08c3bdfSopenharmony_ci	 */
168f08c3bdfSopenharmony_ci	if (setup_marks(fanotify_fd, tc) != 0)
169f08c3bdfSopenharmony_ci		goto out;
170f08c3bdfSopenharmony_ci
171f08c3bdfSopenharmony_ci	/* Variant #1: watching upper fs - open files on overlayfs */
172f08c3bdfSopenharmony_ci	if (tst_variant == 1) {
173f08c3bdfSopenharmony_ci		if (mark->flag & FAN_MARK_MOUNT) {
174f08c3bdfSopenharmony_ci			tst_res(TCONF, "overlayfs upper fs cannot be watched with mount mark");
175f08c3bdfSopenharmony_ci			goto out;
176f08c3bdfSopenharmony_ci		}
177f08c3bdfSopenharmony_ci		SAFE_MOUNT(OVL_MNT, MOUNT_PATH, "none", MS_BIND, NULL);
178f08c3bdfSopenharmony_ci	}
179f08c3bdfSopenharmony_ci
180f08c3bdfSopenharmony_ci	/* Generate sequence of FAN_OPEN events on objects */
181f08c3bdfSopenharmony_ci	for (i = 0; i < ARRAY_SIZE(objects); i++)
182f08c3bdfSopenharmony_ci		fds[i] = SAFE_OPEN(objects[i].path, O_RDONLY);
183f08c3bdfSopenharmony_ci
184f08c3bdfSopenharmony_ci	/*
185f08c3bdfSopenharmony_ci	 * Generate sequence of FAN_CLOSE_NOWRITE events on objects. Each
186f08c3bdfSopenharmony_ci	 * FAN_CLOSE_NOWRITE event is expected to be merged with its
187f08c3bdfSopenharmony_ci	 * respective FAN_OPEN event that was performed on the same object.
188f08c3bdfSopenharmony_ci	 */
189f08c3bdfSopenharmony_ci	for (i = 0; i < ARRAY_SIZE(objects); i++) {
190f08c3bdfSopenharmony_ci		if (fds[i] > 0)
191f08c3bdfSopenharmony_ci			SAFE_CLOSE(fds[i]);
192f08c3bdfSopenharmony_ci	}
193f08c3bdfSopenharmony_ci
194f08c3bdfSopenharmony_ci	if (tst_variant == 1)
195f08c3bdfSopenharmony_ci		SAFE_UMOUNT(MOUNT_PATH);
196f08c3bdfSopenharmony_ci
197f08c3bdfSopenharmony_ci	/* Read events from event queue */
198f08c3bdfSopenharmony_ci	len = SAFE_READ(0, fanotify_fd, events_buf, BUF_SIZE);
199f08c3bdfSopenharmony_ci
200f08c3bdfSopenharmony_ci	/* Iterate over event queue */
201f08c3bdfSopenharmony_ci	for (i = 0, metadata = (struct fanotify_event_metadata *) events_buf;
202f08c3bdfSopenharmony_ci		FAN_EVENT_OK(metadata, len);
203f08c3bdfSopenharmony_ci		metadata = FAN_EVENT_NEXT(metadata, len), i++) {
204f08c3bdfSopenharmony_ci		struct fanotify_fid_t *expected_fid = &objects[i].fid;
205f08c3bdfSopenharmony_ci
206f08c3bdfSopenharmony_ci		event_fid = (struct fanotify_event_info_fid *) (metadata + 1);
207f08c3bdfSopenharmony_ci		event_file_handle = (struct file_handle *) event_fid->handle;
208f08c3bdfSopenharmony_ci
209f08c3bdfSopenharmony_ci		/* File descriptor is redundant with FAN_REPORT_FID */
210f08c3bdfSopenharmony_ci		if (metadata->fd != FAN_NOFD)
211f08c3bdfSopenharmony_ci			tst_res(TFAIL,
212f08c3bdfSopenharmony_ci				"Unexpectedly received file descriptor %d in "
213f08c3bdfSopenharmony_ci				"event. Expected to get FAN_NOFD(%d)",
214f08c3bdfSopenharmony_ci				metadata->fd, FAN_NOFD);
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci		/* Ensure that the correct mask has been reported in event */
217f08c3bdfSopenharmony_ci		if (metadata->mask != event_set[i].expected_mask)
218f08c3bdfSopenharmony_ci			tst_res(TFAIL,
219f08c3bdfSopenharmony_ci				"Unexpected mask received: %llx (expected: "
220f08c3bdfSopenharmony_ci				"%llx) in event",
221f08c3bdfSopenharmony_ci				metadata->mask,
222f08c3bdfSopenharmony_ci				event_set[i].expected_mask);
223f08c3bdfSopenharmony_ci
224f08c3bdfSopenharmony_ci		/* Verify handle_bytes returned in event */
225f08c3bdfSopenharmony_ci		if (event_file_handle->handle_bytes !=
226f08c3bdfSopenharmony_ci		    expected_fid->handle.handle_bytes) {
227f08c3bdfSopenharmony_ci			tst_res(TFAIL,
228f08c3bdfSopenharmony_ci				"handle_bytes (%x) returned in event does not "
229f08c3bdfSopenharmony_ci				"equal to handle_bytes (%x) returned in "
230f08c3bdfSopenharmony_ci				"name_to_handle_at(2)",
231f08c3bdfSopenharmony_ci				event_file_handle->handle_bytes,
232f08c3bdfSopenharmony_ci				expected_fid->handle.handle_bytes);
233f08c3bdfSopenharmony_ci			continue;
234f08c3bdfSopenharmony_ci		}
235f08c3bdfSopenharmony_ci
236f08c3bdfSopenharmony_ci		/* Verify handle_type returned in event */
237f08c3bdfSopenharmony_ci		if (event_file_handle->handle_type !=
238f08c3bdfSopenharmony_ci		    expected_fid->handle.handle_type) {
239f08c3bdfSopenharmony_ci			tst_res(TFAIL,
240f08c3bdfSopenharmony_ci				"handle_type (%x) returned in event does not "
241f08c3bdfSopenharmony_ci				"equal to handle_type (%x) returned in "
242f08c3bdfSopenharmony_ci				"name_to_handle_at(2)",
243f08c3bdfSopenharmony_ci				event_file_handle->handle_type,
244f08c3bdfSopenharmony_ci				expected_fid->handle.handle_type);
245f08c3bdfSopenharmony_ci			continue;
246f08c3bdfSopenharmony_ci		}
247f08c3bdfSopenharmony_ci
248f08c3bdfSopenharmony_ci		/* Verify file identifier f_handle returned in event */
249f08c3bdfSopenharmony_ci		if (memcmp(event_file_handle->f_handle,
250f08c3bdfSopenharmony_ci			   expected_fid->handle.f_handle,
251f08c3bdfSopenharmony_ci			   expected_fid->handle.handle_bytes) != 0) {
252f08c3bdfSopenharmony_ci			tst_res(TFAIL,
253f08c3bdfSopenharmony_ci				"file_handle returned in event does not match "
254f08c3bdfSopenharmony_ci				"the file_handle returned in "
255f08c3bdfSopenharmony_ci				"name_to_handle_at(2)");
256f08c3bdfSopenharmony_ci			continue;
257f08c3bdfSopenharmony_ci		}
258f08c3bdfSopenharmony_ci
259f08c3bdfSopenharmony_ci		/* Verify filesystem ID fsid  returned in event */
260f08c3bdfSopenharmony_ci		if (memcmp(&event_fid->fsid, &expected_fid->fsid,
261f08c3bdfSopenharmony_ci			   sizeof(expected_fid->fsid)) != 0) {
262f08c3bdfSopenharmony_ci			tst_res(TFAIL,
263f08c3bdfSopenharmony_ci				"event_fid.fsid != stat.f_fsid that was "
264f08c3bdfSopenharmony_ci				"obtained via statfs(2)");
265f08c3bdfSopenharmony_ci			continue;
266f08c3bdfSopenharmony_ci		}
267f08c3bdfSopenharmony_ci
268f08c3bdfSopenharmony_ci		tst_res(TPASS,
269f08c3bdfSopenharmony_ci			"got event: mask=%llx, pid=%d, fid=%x.%x.%lx values "
270f08c3bdfSopenharmony_ci			"returned in event match those returned in statfs(2) "
271f08c3bdfSopenharmony_ci			"and name_to_handle_at(2)",
272f08c3bdfSopenharmony_ci			metadata->mask,
273f08c3bdfSopenharmony_ci			getpid(),
274f08c3bdfSopenharmony_ci			FSID_VAL_MEMBER(event_fid->fsid, 0),
275f08c3bdfSopenharmony_ci			FSID_VAL_MEMBER(event_fid->fsid, 1),
276f08c3bdfSopenharmony_ci			*(unsigned long *) event_file_handle->f_handle);
277f08c3bdfSopenharmony_ci	}
278f08c3bdfSopenharmony_ciout:
279f08c3bdfSopenharmony_ci	SAFE_CLOSE(fanotify_fd);
280f08c3bdfSopenharmony_ci}
281f08c3bdfSopenharmony_ci
282f08c3bdfSopenharmony_cistatic void do_setup(void)
283f08c3bdfSopenharmony_ci{
284f08c3bdfSopenharmony_ci	const char *mnt;
285f08c3bdfSopenharmony_ci
286f08c3bdfSopenharmony_ci	/*
287f08c3bdfSopenharmony_ci	 * Bind mount to either base fs or to overlayfs over base fs:
288f08c3bdfSopenharmony_ci	 * Variant #0: watch base fs - open files on base fs
289f08c3bdfSopenharmony_ci	 * Variant #1: watch upper fs - open files on overlayfs
290f08c3bdfSopenharmony_ci	 *
291f08c3bdfSopenharmony_ci	 * Variant #1 tests a bug whose fix bc2473c90fca ("ovl: enable fsnotify
292f08c3bdfSopenharmony_ci	 * events on underlying real files") in kernel 6.5 is not likely to be
293f08c3bdfSopenharmony_ci	 * backported to older kernels.
294f08c3bdfSopenharmony_ci	 * To avoid waiting for events that won't arrive when testing old kernels,
295f08c3bdfSopenharmony_ci	 * require that kernel supports encoding fid with new flag AT_HADNLE_FID,
296f08c3bdfSopenharmony_ci	 * also merged to 6.5 and not likely to be backported to older kernels.
297f08c3bdfSopenharmony_ci	 */
298f08c3bdfSopenharmony_ci	if (tst_variant) {
299f08c3bdfSopenharmony_ci		REQUIRE_HANDLE_TYPE_SUPPORTED_BY_KERNEL(AT_HANDLE_FID);
300f08c3bdfSopenharmony_ci		ovl_mounted = TST_MOUNT_OVERLAY();
301f08c3bdfSopenharmony_ci		mnt = OVL_UPPER;
302f08c3bdfSopenharmony_ci	} else {
303f08c3bdfSopenharmony_ci		mnt = OVL_BASE_MNTPOINT;
304f08c3bdfSopenharmony_ci
305f08c3bdfSopenharmony_ci	}
306f08c3bdfSopenharmony_ci	REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, mnt);
307f08c3bdfSopenharmony_ci	SAFE_MKDIR(MOUNT_PATH, 0755);
308f08c3bdfSopenharmony_ci	SAFE_MOUNT(mnt, MOUNT_PATH, "none", MS_BIND, NULL);
309f08c3bdfSopenharmony_ci	bind_mounted = 1;
310f08c3bdfSopenharmony_ci
311f08c3bdfSopenharmony_ci	filesystem_mark_unsupported = fanotify_mark_supported_by_kernel(FAN_MARK_FILESYSTEM);
312f08c3bdfSopenharmony_ci
313f08c3bdfSopenharmony_ci	nofid_fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY);
314f08c3bdfSopenharmony_ci
315f08c3bdfSopenharmony_ci	/* Create file and directory objects for testing */
316f08c3bdfSopenharmony_ci	create_objects();
317f08c3bdfSopenharmony_ci
318f08c3bdfSopenharmony_ci	/*
319f08c3bdfSopenharmony_ci	 * Create a mark on first inode without FAN_REPORT_FID, to test
320f08c3bdfSopenharmony_ci	 * uninitialized connector->fsid cache. This mark remains for all test
321f08c3bdfSopenharmony_ci	 * cases and is not expected to get any events (no writes in this test).
322f08c3bdfSopenharmony_ci	 */
323f08c3bdfSopenharmony_ci	SAFE_FANOTIFY_MARK(nofid_fd, FAN_MARK_ADD, FAN_CLOSE_WRITE, AT_FDCWD,
324f08c3bdfSopenharmony_ci			  FILE_PATH_ONE);
325f08c3bdfSopenharmony_ci
326f08c3bdfSopenharmony_ci	/* Get the filesystem fsid and file handle for each created object */
327f08c3bdfSopenharmony_ci	get_object_stats();
328f08c3bdfSopenharmony_ci}
329f08c3bdfSopenharmony_ci
330f08c3bdfSopenharmony_cistatic void do_cleanup(void)
331f08c3bdfSopenharmony_ci{
332f08c3bdfSopenharmony_ci	SAFE_CLOSE(nofid_fd);
333f08c3bdfSopenharmony_ci	if (fanotify_fd > 0)
334f08c3bdfSopenharmony_ci		SAFE_CLOSE(fanotify_fd);
335f08c3bdfSopenharmony_ci	if (bind_mounted) {
336f08c3bdfSopenharmony_ci		SAFE_UMOUNT(MOUNT_PATH);
337f08c3bdfSopenharmony_ci		SAFE_RMDIR(MOUNT_PATH);
338f08c3bdfSopenharmony_ci	}
339f08c3bdfSopenharmony_ci	if (ovl_mounted)
340f08c3bdfSopenharmony_ci		SAFE_UMOUNT(OVL_MNT);
341f08c3bdfSopenharmony_ci}
342f08c3bdfSopenharmony_ci
343f08c3bdfSopenharmony_cistatic struct tst_test test = {
344f08c3bdfSopenharmony_ci	.test = do_test,
345f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(test_cases),
346f08c3bdfSopenharmony_ci	.test_variants = 2,
347f08c3bdfSopenharmony_ci	.setup = do_setup,
348f08c3bdfSopenharmony_ci	.cleanup = do_cleanup,
349f08c3bdfSopenharmony_ci	.needs_root = 1,
350f08c3bdfSopenharmony_ci	.mount_device = 1,
351f08c3bdfSopenharmony_ci	.mntpoint = OVL_BASE_MNTPOINT,
352f08c3bdfSopenharmony_ci	.all_filesystems = 1,
353f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
354f08c3bdfSopenharmony_ci		{"linux-git", "c285a2f01d69"},
355f08c3bdfSopenharmony_ci		{"linux-git", "bc2473c90fca"},
356f08c3bdfSopenharmony_ci		{}
357f08c3bdfSopenharmony_ci	}
358f08c3bdfSopenharmony_ci};
359f08c3bdfSopenharmony_ci
360f08c3bdfSopenharmony_ci#else
361f08c3bdfSopenharmony_ci	TST_TEST_TCONF("System does not have required name_to_handle_at() support");
362f08c3bdfSopenharmony_ci#endif
363f08c3bdfSopenharmony_ci#else
364f08c3bdfSopenharmony_ci	TST_TEST_TCONF("System does not have required fanotify support");
365f08c3bdfSopenharmony_ci#endif
366