yaffs Some cleanups.
[yaffs2.git] / direct / tests / nor_stress.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2010 Aleph One Ltd.
5  *   for Toby Churchill Ltd and Brightstar Engineering
6  *
7  * Created by Charles Manning <charles@aleph1.co.uk>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  */
14
15 #include "nor_stress.h"
16
17
18 #include "yaffsfs.h"
19 #include "yaffs_fsx.h"
20
21 #include <stdio.h>
22
23
24
25 #if 1
26 #define FSX_INIT(mount_pt) do{ if(interleave_fsx) yaffs_fsx_init(mount_pt); } while(0)
27 #define FSX_COMPLETE() do { if(interleave_fsx) yaffs_fsx_complete(); } while (0)
28
29 #define FSX() \
30 do { \
31   if((myrand() & 0x1) == 0){\
32      if(interleave_fsx) \
33         yaffs_fsx_do_op(); \
34   } \
35 } while(0)
36
37 #else
38 #define FSX_INIT(mount_point) do { } while(0)
39 #define FSX_COMPLETE() do { } while(0)
40 #define FSX() do { } while(0)
41 #endif
42
43
44 void (*ext_fatal)(void) = NULL;
45
46 static unsigned powerUps;
47 static unsigned cycleStarts;
48 static unsigned cycleEnds;
49
50 static int interleave_fsx;
51
52 char fullPathName[100];
53 char fullPowerUpName[100];
54 char fullStartName[100];
55 char fullEndName[100];
56 char fullMainName[100];
57 char fullTempMainName[100];
58 char fullTempCounterName[100];
59
60
61 extern int random_seed;
62
63 int myrand(void) {
64   random_seed = random_seed * 1103515245 + 12345;
65   return((unsigned)(random_seed/65536) % 32768);
66 }
67
68 void MakeName(char *fullName,const char *prefix, const char *name)
69 {
70   strcpy(fullName,prefix);
71   strcat(fullName,"/");
72   strcat(fullName,name);
73 }
74
75
76 void MakeFullNames(const char *prefix)
77 {
78   MakeName(fullPathName,prefix,"");
79   MakeName(fullPowerUpName,prefix,"powerUps");
80   MakeName(fullStartName,prefix,"starts");
81   MakeName(fullEndName,prefix,"ends");
82   MakeName(fullMainName,prefix,"main");
83   MakeName(fullTempCounterName,prefix,"tmp-counter");
84   MakeName(fullTempMainName,prefix,"tmp-main");
85 }
86
87 static void FatalError(int lineNo)
88 {
89   printf("Integrity error %d\n",lineNo);
90   if(ext_fatal)
91         ext_fatal();
92         
93   while(1){
94    sleep(1);
95   }
96 }
97 void print_stat(const char *str, struct yaffs_stat *st)
98 {
99         printf("%s inode %d\n",str,st->st_ino);
100 }
101
102 static void UpdateCounter(const char *name, unsigned *val,  int initialise)
103 {
104   int inh=-1;
105   int outh=-1;
106   unsigned x[2];
107   int nread = 0;
108   int nwritten = 0;
109   
110   x[0] = x[1] = 0;
111   
112   if(initialise){
113     x[0] = 0; 
114     x[1] = 1;
115   } else {
116     inh = yaffs_open(name,O_RDONLY, S_IREAD | S_IWRITE);
117     if(inh >= 0){
118       nread = yaffs_read(inh,x,sizeof(x));
119       yaffs_close(inh);
120     }
121
122     if(nread != sizeof(x) ||
123        x[0] + 1 != x[1]){
124       printf("Error reading counter %s handle %d, x[0] %u x[1] %u last error %d\n",
125               name, inh, x[0], x[1],yaffsfs_GetLastError());
126       FatalError(__LINE__);
127               
128     }
129     x[0]++;
130     x[1]++;
131   }
132   
133   FSX();
134   outh = yaffs_open(fullTempCounterName, O_RDWR | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE);
135   
136   if(outh >= 0){
137    struct yaffs_stat tmpstat, oldstat, tmpfstat;
138    FSX(); 
139     yaffs_fstat(outh,&tmpfstat);
140     printf("\n\n\n*** Writing file %s inode %d\n",fullTempCounterName,tmpfstat.st_ino);
141     nwritten = yaffs_write(outh,x,sizeof(x));
142     FSX();
143     yaffs_close(outh);
144     FSX();
145
146     printf("About to rename %s to %s\n",fullTempCounterName,name);
147     yaffs_stat(fullTempCounterName,&tmpstat);
148     yaffs_stat(name,&oldstat);
149     print_stat("old stat",&oldstat);
150     print_stat("new stat",&tmpstat);
151     print_stat("new fstat",&tmpfstat);
152     yaffs_rename(fullTempCounterName,name);
153     FSX();
154   }
155   
156   if(nwritten != sizeof(x)){
157       printf("Error writing counter %s handle %d, x[0] %u x[1] %u\n",
158               name, inh, x[0], x[1]);
159       FatalError(__LINE__);
160   }
161   
162   *val = x[0];
163   
164   printf("##\n"
165          "## Set counter %s to %u\n"
166          "##\n", name,x[0]);
167 }
168
169
170 static void dump_directory_tree_worker(const char *dname,int recursive)
171 {
172         yaffs_DIR *d;
173         yaffs_dirent *de;
174         struct yaffs_stat s;
175         char str[1000];
176         int error_line = 0;
177                         
178         d = yaffs_opendir(dname);
179         
180         if(!d)
181         {
182                 printf("opendir failed\n");
183         }
184         else
185         {
186                 while((de = yaffs_readdir(d)) != NULL)
187                 {
188                         strcpy(str,dname);
189                         strcat(str,"/");
190                         strcat(str,de->d_name);
191                         
192                         yaffs_lstat(str,&s);
193                         
194                         printf("%s inode %ld %d obj %x length %d mode %X ",str, de->d_ino, s.st_ino,de->d_dont_use,(int)s.st_size,s.st_mode);\
195                         if(de->d_ino != s.st_ino){
196                                 printf(" \n\n!!!! HEY inode mismatch\n\n");
197                                 error_line = __LINE__;
198                         }
199
200                         switch(s.st_mode & S_IFMT)
201                         {
202                                 case S_IFREG: printf("data file"); break;
203                                 case S_IFDIR: printf("directory"); break;
204                                 case S_IFLNK: printf("symlink -->");
205                                                           if(yaffs_readlink(str,str,100) < 0)
206                                                                 printf("no alias");
207                                                           else
208                                                                 printf("\"%s\"",str);    
209                                                           break;
210                                 default: printf("unknown"); break;
211                         }
212                         
213                         printf("\n");
214
215                         if((s.st_mode & S_IFMT) == S_IFDIR && recursive)
216                                 dump_directory_tree_worker(str,1);
217                                 
218                         if(s.st_ino > 10000)
219                           error_line = __LINE__;
220                                                         
221                 }
222                 
223                 if(error_line)
224                         FatalError(error_line);
225                 
226                 yaffs_closedir(d);
227         }
228
229 }
230
231 static void dump_directory_tree(const char *dname)
232 {
233         dump_directory_tree_worker(dname,1);
234         printf("\n");
235         printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname));
236 }
237
238
239
240
241 #define XX_SIZE 500
242
243 static unsigned xx[XX_SIZE];
244
245 static int yWriteFile(const char *fname, unsigned sz32)
246 {
247         int h;
248         int r;
249         int i;
250         struct yaffs_stat st;
251         unsigned checksum = 0;
252         
253
254         FSX();
255         h = yaffs_open(fname,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
256         yaffs_fstat(h,&st);
257         printf("\n\n\n**** Open writing file %s inode %d\n",fname, st.st_ino);
258         
259         FSX();
260
261         if(h < 0){
262                 printf("could not open file %s\n",fname);
263                 return h;
264         }
265
266         xx[0] = sz32;
267         checksum ^= xx[0];
268
269         if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
270                 goto WRITE_ERROR;
271         }
272         FSX();
273         while(sz32> 0){
274                 for(i = 0; i < XX_SIZE; i++){
275                   xx[i] = sz32 + i;
276                   checksum ^= xx[i];
277                 }
278                 
279                 FSX();
280                 if((r = yaffs_write(h,xx,sizeof(xx))) != sizeof(xx)){
281                         goto WRITE_ERROR;
282                 }
283                 sz32--;
284         }
285
286         xx[0] = checksum;
287         FSX();
288         if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
289                 goto WRITE_ERROR;
290         }
291         
292         FSX();
293         yaffs_close(h);
294         printf("File closed\n");
295         return 0;
296
297 WRITE_ERROR:
298         printf("ywrite error at position %d\n",(int)yaffs_lseek(h,0,SEEK_END));
299         yaffs_close(h);
300         return -1;
301         
302 }
303
304 static int yVerifyFile(const char *fName)
305 {
306         unsigned checksum = 0;
307         unsigned totalSize;
308         unsigned sz32;
309         unsigned recordedSize = 0;
310         int r;
311         int h;
312         int i;
313         int retval = 0;
314
315
316         printf("Verifying file %s\n",fName);
317                 
318         h = yaffs_open(fName, O_RDONLY,S_IREAD | S_IWRITE);
319
320         if(h < 0){
321                 printf("could not open file %s\n",fName);
322                 return -1;
323         }
324
325         totalSize = yaffs_lseek(h,0,SEEK_END);
326         yaffs_lseek(h,0,SEEK_SET);
327
328         r = yaffs_read(h,&sz32,sizeof(sz32));
329
330         if(r != sizeof(sz32)){
331                 printf("reading size failed ... returned %d\n",r);
332                 yaffs_close(h);
333                 return -1;
334         }
335         
336         recordedSize = sz32 * sizeof(xx) + 8;
337
338         printf("verify %s: file size is %d, recorded size is %d\n", fName, totalSize, recordedSize);
339         if(totalSize != recordedSize){
340                 printf("!!!!!!!!!!!!!!!!!!!!!!!!file size is wrong, should be %d, is %d\n", recordedSize,totalSize);
341                 yaffs_close(h);
342                 return -1;
343         }
344
345         checksum ^= sz32;
346
347
348         while(sz32 > 0){
349                 r = yaffs_read(h,xx,sizeof(xx));
350                 if(r != sizeof(xx)){
351                         printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r);
352                         yaffs_close(h);
353                         return -1;
354                 }
355                 for(i = 0; i < XX_SIZE; i++)
356                   checksum ^= xx[i];
357                 sz32--;
358         }
359         r = yaffs_read(h,xx,sizeof(xx[0]));
360         if(r != sizeof(xx[0])){
361                 printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r);
362                 yaffs_close(h);
363                 return -1;
364         }
365         
366         checksum ^= xx[0];
367
368         if(checksum != 0){
369                 printf("!!!!!!!!!!!!!!!!!!!!! checksum failed\n");
370                 retval = -1;
371         } else
372                 printf("verified ok\n");
373         yaffs_close(h);
374
375         return retval;
376 }
377
378
379 static void DoUpdateMainFile(void)
380 {
381         int result;
382         int sz32;
383         sz32 = (myrand() % 1000)   + 20;
384         
385         result = yWriteFile(fullTempMainName,sz32);
386         FSX();
387         if(result)
388             FatalError(__LINE__);
389         printf("Raname file %s to %s\n",fullTempMainName,fullMainName);
390         yaffs_rename(fullTempMainName,fullMainName);
391         FSX();
392 }
393
394 static void DoVerifyMainFile(void)
395 {
396         int result;
397         result = yVerifyFile(fullMainName);
398         if(result)
399             FatalError(__LINE__);
400
401 }
402
403
404 void NorStressTestInitialise(const char *prefix)
405 {
406   MakeFullNames(prefix);
407   
408   UpdateCounter(fullPowerUpName,&powerUps,1);
409   UpdateCounter(fullStartName,&cycleStarts,1);
410   UpdateCounter(fullEndName,&cycleEnds,1);
411   UpdateCounter(fullPowerUpName,&powerUps,1);
412   DoUpdateMainFile();
413   DoVerifyMainFile();
414 }
415
416
417 void NorStressTestRun(const char *prefix, int n_cycles, int do_fsx)
418 {
419
420   interleave_fsx = do_fsx;
421   MakeFullNames(prefix);
422   dump_directory_tree(fullPathName);
423   FSX_INIT(prefix);
424     
425   dump_directory_tree(fullPathName);
426   
427   UpdateCounter(fullPowerUpName,&powerUps,0);
428   dump_directory_tree(fullPathName);
429   
430   while(n_cycles < 0 || n_cycles > 0){
431     if(n_cycles > 0)
432       n_cycles--;
433     UpdateCounter(fullStartName, &cycleStarts,0);
434     dump_directory_tree(fullPathName);
435     DoVerifyMainFile();
436     DoUpdateMainFile();
437     dump_directory_tree(fullPathName);
438   
439     UpdateCounter(fullEndName,&cycleEnds,0);
440     dump_directory_tree(fullPathName);
441   }
442   FSX_COMPLETE();
443 }