Modify existing test cases, and add a new one.
[xfstests-dev.git] / src / bulkstat_unlink_test_modified.c
1 /*
2  * $Id: bulkstat_unlink_test_modified.c,v 1.1 2007/10/03 16:23:57 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  * This is a modified version of bulkstat_unlink_test.c to reproduce a specific
7  * problem see pv 969192
8  */
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <xfs/xfs.h>
13 #include <unistd.h>
14
15 int
16 main(int argc, char *argv[])
17 {
18     int e;
19     int fd = 0;
20     int i;
21     int j;
22     int k;
23     int nfiles;
24     int stride;
25     struct stat sbuf;
26     ino_t *inodelist;
27     __u32 *genlist;
28     xfs_fsop_bulkreq_t a;
29     xfs_bstat_t *ret;
30     int iterations;
31     char fname[MAXPATHLEN];
32     char *dirname;
33
34     if (argc != 5) {
35         fprintf(stderr, "Usage: %s iterations nfiles stride dir\n", argv[0]);
36         fprintf(stderr, "Create dir with nfiles, unlink each stride'th file, sync, bulkstat\n");
37         exit(1);
38     }
39
40     iterations = atoi(argv[1]);
41     nfiles = atoi(argv[2]);
42     stride = atoi(argv[3]);
43     dirname = argv[4];
44     if (!nfiles || !iterations) {
45         fprintf(stderr, "Iterations and nfiles showld be non zero.\n");
46         exit(1);
47     }
48
49     inodelist = (ino_t *)malloc(nfiles * sizeof(ino_t));
50     genlist = (__u32 *)malloc(nfiles * sizeof(__u32));
51     ret = (xfs_bstat_t *)malloc(nfiles * sizeof(xfs_bstat_t));
52
53     for (k=0; k < iterations; k++) {
54         xfs_ino_t last_inode = 0;
55         int count = 0;
56         int testFiles = 0;
57
58         printf("Iteration %d ... \n", k);
59
60         memset(inodelist, 0, nfiles * sizeof(ino_t));
61         memset(genlist, 0, nfiles * sizeof(__u32));
62         memset(ret, 0, nfiles * sizeof(xfs_bstat_t));
63         memset(&a, 0, sizeof(xfs_fsop_bulkreq_t));
64         a.lastip = &last_inode;
65         a.icount = nfiles;
66         a.ubuffer = ret;
67         a.ocount = &count;
68
69         if (mkdir(dirname, 0755) < 0) {
70             perror(dirname);
71             exit(1);
72         }
73
74         /* create nfiles and store their inode numbers in inodelist */
75         for (i=0; i < nfiles; i++) {
76             sprintf(fname, "%s/file%06d", dirname, i);
77             if ((fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
78                 perror(fname);
79                 exit(1);
80             }
81             write(fd, fname, sizeof(fname));
82             if (fstat(fd, &sbuf) < 0) {
83                 perror(fname);
84                 exit(1);
85             }
86             inodelist[i] = sbuf.st_ino;
87             close(fd);
88         }
89         
90         sync();
91         
92         /* collect bs_gen for the nfiles files */
93         if ((fd = open(dirname, O_RDONLY)) < 0) {
94             perror(dirname);
95             exit(1);
96         }
97
98         testFiles = 0;
99         for (;;) {
100             if ((e = xfsctl(dirname, fd, XFS_IOC_FSBULKSTAT, &a)) < 0) {
101                 perror("XFS_IOC_FSBULKSTAT1:");
102                 exit(1);
103             }
104
105             if (count == 0)
106                 break;
107
108             for (i=0; i < count; i++) {
109                 for (j=0; j < nfiles; j += stride) {
110                     if (ret[i].bs_ino == inodelist[j]) {
111                         genlist[j] = ret[i].bs_gen;
112                         testFiles++;
113                     }
114                 }
115             }
116         }
117         close(fd);
118         
119         printf("testFiles %d ... \n", testFiles);
120
121         /* remove some of the first set of files */
122         for (i=0; i < nfiles; i += stride) {
123             sprintf(fname, "%s/file%06d", dirname, i);
124             if (unlink(fname) < 0) {
125                 perror(fname);
126                 exit(1);
127             }
128         }
129
130         /* create a new set of files (replacing the unlinked ones) */
131         for (i=0; i < nfiles; i += stride) {
132             sprintf(fname, "%s/file%06d", dirname, i);
133             if ((fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
134                 perror(fname);
135                 exit(1);
136             }
137             write(fd, fname, sizeof(fname));
138             close(fd);
139         }
140
141         sync();
142         last_inode = 0; count = 0;
143
144         if ((fd = open(dirname, O_RDONLY)) < 0) {
145             perror(dirname);
146             exit(1);
147         }
148
149         for (;;) {
150             if ((e = xfsctl(dirname, fd, XFS_IOC_FSBULKSTAT, &a)) < 0) {
151                 perror("XFS_IOC_FSBULKSTAT:");
152                 exit(1);
153             }
154
155             if (count == 0)
156                     break;
157
158             for (i=0; i < count; i++) {
159                 for (j=0; j < nfiles; j += stride) {
160                     if ((ret[i].bs_ino == inodelist[j]) &&
161                         (ret[i].bs_gen == genlist[j])) {
162                         /* oops, the same inode with old gen number */
163                         printf("Unlinked inode %ld with generation %d "
164                                "returned by bulkstat\n",
165                                 inodelist[j], genlist[j]);
166                         exit(1);
167                     }
168                     if ((ret[i].bs_ino == inodelist[j])) {
169                         if ((genlist[j] + 1) != ret[i].bs_gen) {
170                                 /* oops, the new gen number is not 1 bigger than the old */
171                                 printf("Inode with old generation %d, new generation %d\n",
172                                 genlist[j], ret[i].bs_gen);
173                                 exit(1);
174                         }
175                     }
176                 }
177             }
178         }
179
180         close(fd);
181
182         sprintf(fname, "rm -rf %s\n", dirname);
183         system(fname);
184
185         sync();
186         sleep(2);
187         printf("passed\n");
188     }
189
190     exit(0);
191 }