xfs: test that reflink forces the log if mounted with wsync
[xfstests-dev.git] / src / bulkstat_unlink_test.c
1 /*
2  * $Id: bulkstat_unlink_test.c,v 1.3 2007/10/30 03:07:42 mohamedb.longdrop.melbourne.sgi.com Exp $
3  * Test bulkstat doesn't returned unlinked inodes.
4  * Mark Goodwin <markgw@sgi.com> Fri Jul 20 09:13:57 EST 2007
5  */
6 #include <stdlib.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <xfs/xfs.h>
11 #include <unistd.h>
12 #include <getopt.h>
13 #include <string.h>
14
15 int
16 main(int argc, char *argv[])
17 {
18         int e;
19         int i;
20         int j;
21         int k;
22         int nfiles;
23         int stride;
24
25         int c;
26
27         struct stat sbuf;
28         ino_t *inodelist;
29         struct xfs_fsop_bulkreq a;
30         struct xfs_bstat *ret;
31         int iterations;
32         char fname[MAXPATHLEN];
33         char *dirname;
34         int chknb = 0;
35
36         while ((c = getopt(argc, argv, "r")) != -1) {
37                 switch(c) {
38                 case 'r':
39                         chknb = 1;
40                         break;
41                 default:
42                         break;
43                 }
44         }
45
46         if ((argc - optind) != 4) {
47                 fprintf(stderr, "Usage: %s iterations nfiles stride dir [options]\n", argv[0]);
48                 fprintf(stderr, "Create dir with nfiles, unlink each stride'th file, sync, bulkstat\n");
49                 exit(1);
50         }
51
52
53         iterations = atoi(argv[optind++]);
54         nfiles     = atoi(argv[optind++]);
55         stride     = atoi(argv[optind++]);
56
57         dirname = argv[optind++];
58
59         if (chknb)
60                 printf("Runing extended checks.\n");
61
62         inodelist = (ino_t *)malloc(nfiles * sizeof(ino_t));
63         ret = (struct xfs_bstat *)malloc(nfiles * sizeof(struct xfs_bstat));
64
65         for (k=0; k < iterations; k++) {
66                 int fd[nfiles + 1];
67                 xfs_ino_t last_inode = 0;
68                 int count = 0, scount = -1;
69
70                 printf("Iteration %d ... (%d files)", k, nfiles);
71
72                 memset(&a, 0, sizeof(struct xfs_fsop_bulkreq));
73                 a.lastip = (__u64 *)&last_inode;
74                 a.icount = nfiles;
75                 a.ubuffer = ret;
76                 a.ocount = &count;
77
78                 if (mkdir(dirname, 0755) < 0) {
79                         printf("Warning (%s,%d), mkdir(%s) failed.\n", __FILE__, __LINE__, dirname);
80                         perror(dirname);
81                         exit(1);
82                 }
83
84                 if ((fd[nfiles] = open(dirname, O_RDONLY)) < 0) {
85                         printf("Warning (%s,%d), open(%s) failed.\n", __FILE__, __LINE__, dirname);
86                         perror(dirname);
87                         exit(1);
88                 }
89
90                 if (chknb) { /* Get the original number of inodes (lazy) */
91                         sync();
92                         if (xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a) != 0) {
93                                 printf("Warning (%s:%d), xfsctl(XFS_IOC_FSBULKSTAT) FAILED.\n", __FILE__, __LINE__);
94                         }
95
96                         scount = count;
97                 }
98
99                 for (i=0; i < nfiles; i++) { /* Open the files */
100                         sprintf(fname, "%s/file%06d", dirname, i);
101                         if ((fd[i] = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
102                                 printf("Warning (%s,%d), open(%s) failed.\n", __FILE__, __LINE__, fname);
103                                 perror(fname);
104                                 exit(1);
105                         }
106                         write(fd[i], fname, sizeof(fname));
107                         if (fstat(fd[i], &sbuf) < 0) {
108                                 printf("Warning (%s,%d), fstat failed.\n", __FILE__, __LINE__);
109                                 perror(fname);
110                                 exit(1);
111                         }
112                         inodelist[i] = sbuf.st_ino;
113                         unlink(fname);
114                 }
115
116                 if (chknb) {
117                         /*
118                          *The files are still opened (but unlink()ed) ,
119                          * we should have more inodes than before
120                          */
121                         sync();
122                         last_inode = 0;
123                         if (xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a) != 0) {
124                                 printf("Warning (%s:%d), xfsctl(XFS_IOC_FSBULKSTAT) FAILED.\n", __FILE__, __LINE__);
125                         }
126                         if (count < scount) {
127                                 printf("ERROR, count(%d) < scount(%d).\n", count, scount);
128                                 return -1;
129                         }
130                 }
131
132                 /* Close all the files */
133                 for (i = 0; i < nfiles; i++) {
134                         close(fd[i]);
135                 }
136
137                 if (chknb) {
138                         /*
139                          * The files are now closed, we should be back to our,
140                          * previous inode count
141                          */
142                         sync();
143                         last_inode = 0;
144                         if (xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a) != 0) {
145                                 printf("Warning (%s:%d), xfsctl(XFS_IOC_FSBULKSTAT) FAILED.\n", __FILE__, __LINE__);
146                         }
147                         if (count != scount) {
148                                 printf("ERROR, count(%d) != scount(%d).\n", count, scount);
149                                 return -1;
150                         }
151                 }
152
153                 sync();
154                 last_inode = 0;
155                 for (;;) {
156                         if ((e = xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a)) < 0) {
157                                 printf("Warning (%s,%d), xfsctl failed.\n", __FILE__, __LINE__);
158                                 perror("XFS_IOC_FSBULKSTAT:");
159                                 exit(1);
160                         }
161
162                         if (count == 0)
163                                 break;
164
165                         for (i=0; i < count; i++) {
166                                 for (j=0; j < nfiles; j += stride) {
167                                         if (ret[i].bs_ino == inodelist[j]) {
168                                                 /* oops ... */
169                                                 printf("failed. Unlinked inode %llu returned by bulkstat\n", (unsigned long long)inodelist[j]);
170                                                 exit(1);
171                                         }
172                                 }
173                         }
174                 }
175
176                 close(fd[nfiles]);
177                 sprintf(fname, "rm -rf %s\n", dirname);
178                 system(fname);
179
180                 sync();
181                 sleep(2);
182                 printf("passed\n");
183         }
184
185         exit(0);
186 }