fsstress: translate flags in fiemap_f
[xfstests-dev.git] / src / stale_handle.c
1 /*
2  *  stale_handle.c - attempt to create a stale handle and open it
3  *
4  *  Copyright (C) 2010 Red Hat, Inc. All Rights reserved.
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  */
20
21 #define TEST_UTIME
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <errno.h>
31 #include <xfs/xfs.h>
32 #include <xfs/handle.h>
33
34 #define NUMFILES 1024
35 int main(int argc, char **argv)
36 {
37         int     i;
38         int     fd;
39         int     ret;
40         int     failed = 0;
41         char    fname[MAXPATHLEN];
42         char    *test_dir;
43         void    *handle[NUMFILES];
44         size_t  hlen[NUMFILES];
45         char    fshandle[256];
46         size_t  fshlen;
47         struct stat st;
48
49
50         if (argc != 2) {
51                 fprintf(stderr, "usage: stale_handle test_dir\n");
52                 return EXIT_FAILURE;
53         }
54
55         test_dir = argv[1];
56         if (stat(test_dir, &st) != 0) {
57                 perror("stat");
58                 return EXIT_FAILURE;
59         }
60
61         ret = path_to_fshandle(test_dir, (void **)fshandle, &fshlen);
62         if (ret < 0) {
63                 perror("path_to_fshandle");
64                 return EXIT_FAILURE;
65         }
66
67         /*
68          * create a large number of files to force allocation of new inode
69          * chunks on disk.
70          */
71         for (i=0; i < NUMFILES; i++) {
72                 sprintf(fname, "%s/file%06d", test_dir, i);
73                 fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
74                 if (fd < 0) {
75                         printf("Warning (%s,%d), open(%s) failed.\n", __FILE__, __LINE__, fname);
76                         perror(fname);
77                         return EXIT_FAILURE;
78                 }
79                 close(fd);
80         }
81
82         /* sync to get the new inodes to hit the disk */
83         sync();
84
85         /* create the handles */
86         for (i=0; i < NUMFILES; i++) {
87                 sprintf(fname, "%s/file%06d", test_dir, i);
88                 ret = path_to_handle(fname, &handle[i], &hlen[i]);
89                 if (ret < 0) {
90                         perror("path_to_handle");
91                         return EXIT_FAILURE;
92                 }
93         }
94
95         /* unlink the files */
96         for (i=0; i < NUMFILES; i++) {
97                 sprintf(fname, "%s/file%06d", test_dir, i);
98                 ret = unlink(fname);
99                 if (ret < 0) {
100                         perror("unlink");
101                         return EXIT_FAILURE;
102                 }
103         }
104
105         /* sync to get log forced for unlink transactions to hit the disk */
106         sync();
107
108         /* sync once more FTW */
109         sync();
110
111         /*
112          * now drop the caches so that unlinked inodes are reclaimed and
113          * buftarg page cache is emptied so that the inode cluster has to be
114          * fetched from disk again for the open_by_handle() call.
115          */
116         system("echo 3 > /proc/sys/vm/drop_caches");
117
118         /*
119          * now try to open the files by the stored handles. Expecting ENOENT
120          * for all of them.
121          */
122         for (i=0; i < NUMFILES; i++) {
123                 errno = 0;
124                 fd = open_by_handle(handle[i], hlen[i], O_RDWR);
125                 if (fd < 0 && (errno == ENOENT || errno == ESTALE)) {
126                         free_handle(handle[i], hlen[i]);
127                         continue;
128                 }
129                 if (fd >= 0) {
130                         printf("open_by_handle(%d) opened an unlinked file!\n", i);
131                         close(fd);
132                 } else
133                         printf("open_by_handle(%d) returned %d incorrectly on an unlinked file!\n", i, errno);
134                 free_handle(handle[i], hlen[i]);
135                 failed++;
136         }
137         if (failed)
138                 return EXIT_FAILURE;
139         return EXIT_SUCCESS;
140 }