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