check: try reloading modules
[xfstests-dev.git] / src / stale_handle.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  stale_handle.c - attempt to create a stale handle and open it
4  *  Copyright (C) 2010 Red Hat, Inc. All Rights reserved.
5  */
6
7 #define TEST_UTIME
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <errno.h>
17 #include <xfs/xfs.h>
18 #include <xfs/handle.h>
19
20 #define NUMFILES 1024
21 int main(int argc, char **argv)
22 {
23         int     i;
24         int     fd;
25         int     ret;
26         int     failed = 0;
27         char    fname[MAXPATHLEN];
28         char    *test_dir;
29         void    *handle[NUMFILES];
30         size_t  hlen[NUMFILES];
31         char    fshandle[256];
32         size_t  fshlen;
33         struct stat st;
34
35
36         if (argc != 2) {
37                 fprintf(stderr, "usage: stale_handle test_dir\n");
38                 return EXIT_FAILURE;
39         }
40
41         test_dir = argv[1];
42         if (stat(test_dir, &st) != 0) {
43                 perror("stat");
44                 return EXIT_FAILURE;
45         }
46
47         ret = path_to_fshandle(test_dir, (void **)fshandle, &fshlen);
48         if (ret < 0) {
49                 perror("path_to_fshandle");
50                 return EXIT_FAILURE;
51         }
52
53         /*
54          * create a large number of files to force allocation of new inode
55          * chunks on disk.
56          */
57         for (i=0; i < NUMFILES; i++) {
58                 sprintf(fname, "%s/file%06d", test_dir, i);
59                 fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
60                 if (fd < 0) {
61                         printf("Warning (%s,%d), open(%s) failed.\n", __FILE__, __LINE__, fname);
62                         perror(fname);
63                         return EXIT_FAILURE;
64                 }
65                 close(fd);
66         }
67
68         /* sync to get the new inodes to hit the disk */
69         sync();
70
71         /* create the handles */
72         for (i=0; i < NUMFILES; i++) {
73                 sprintf(fname, "%s/file%06d", test_dir, i);
74                 ret = path_to_handle(fname, &handle[i], &hlen[i]);
75                 if (ret < 0) {
76                         perror("path_to_handle");
77                         return EXIT_FAILURE;
78                 }
79         }
80
81         /* unlink the files */
82         for (i=0; i < NUMFILES; i++) {
83                 sprintf(fname, "%s/file%06d", test_dir, i);
84                 ret = unlink(fname);
85                 if (ret < 0) {
86                         perror("unlink");
87                         return EXIT_FAILURE;
88                 }
89         }
90
91         /* sync to get log forced for unlink transactions to hit the disk */
92         sync();
93
94         /* sync once more FTW */
95         sync();
96
97         /*
98          * now drop the caches so that unlinked inodes are reclaimed and
99          * buftarg page cache is emptied so that the inode cluster has to be
100          * fetched from disk again for the open_by_handle() call.
101          */
102         system("echo 3 > /proc/sys/vm/drop_caches");
103
104         /*
105          * now try to open the files by the stored handles. Expecting ENOENT
106          * for all of them.
107          */
108         for (i=0; i < NUMFILES; i++) {
109                 errno = 0;
110                 fd = open_by_handle(handle[i], hlen[i], O_RDWR);
111                 if (fd < 0 && (errno == ENOENT || errno == ESTALE)) {
112                         free_handle(handle[i], hlen[i]);
113                         continue;
114                 }
115                 if (fd >= 0) {
116                         printf("open_by_handle(%d) opened an unlinked file!\n", i);
117                         close(fd);
118                 } else
119                         printf("open_by_handle(%d) returned %d incorrectly on an unlinked file!\n", i, errno);
120                 free_handle(handle[i], hlen[i]);
121                 failed++;
122         }
123         if (failed)
124                 return EXIT_FAILURE;
125         return EXIT_SUCCESS;
126 }