15d0238ba8c76757fb9483b82a38a7a119a5d357
[yaffs2.git] / yaffs_guts.c
1 /*
2  * YAFFS: Yet Another Flash File System. 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 #include "yportenv.h"
15 #include "yaffs_trace.h"
16
17 #include "yaffs_guts.h"
18 #include "yaffs_tagsvalidity.h"
19 #include "yaffs_getblockinfo.h"
20
21 #include "yaffs_tagscompat.h"
22
23 #include "yaffs_nand.h"
24
25 #include "yaffs_yaffs1.h"
26 #include "yaffs_yaffs2.h"
27 #include "yaffs_bitmap.h"
28 #include "yaffs_verify.h"
29
30 #include "yaffs_nand.h"
31 #include "yaffs_packedtags2.h"
32
33 #include "yaffs_nameval.h"
34 #include "yaffs_allocator.h"
35
36 #include "yaffs_attribs.h"
37
38 /* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */
39 #define YAFFS_GC_GOOD_ENOUGH 2
40 #define YAFFS_GC_PASSIVE_THRESHOLD 4
41
42 #include "yaffs_ecc.h"
43
44 /* Forward declarations */
45
46
47 static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
48                              const u8 * buffer, int n_bytes, int use_reserve);
49
50
51
52 /* Function to calculate chunk and offset */
53
54 static void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
55                                 int *chunk_out, u32 * offset_out)
56 {
57         int chunk;
58         u32 offset;
59
60         chunk = (u32) (addr >> dev->chunk_shift);
61
62         if (dev->chunk_div == 1) {
63                 /* easy power of 2 case */
64                 offset = (u32) (addr & dev->chunk_mask);
65         } else {
66                 /* Non power-of-2 case */
67
68                 loff_t chunk_base;
69
70                 chunk /= dev->chunk_div;
71
72                 chunk_base = ((loff_t) chunk) * dev->data_bytes_per_chunk;
73                 offset = (u32) (addr - chunk_base);
74         }
75
76         *chunk_out = chunk;
77         *offset_out = offset;
78 }
79
80 /* Function to return the number of shifts for a power of 2 greater than or
81  * equal to the given number
82  * Note we don't try to cater for all possible numbers and this does not have to
83  * be hellishly efficient.
84  */
85
86 static u32 calc_shifts_ceiling(u32 x)
87 {
88         int extra_bits;
89         int shifts;
90
91         shifts = extra_bits = 0;
92
93         while (x > 1) {
94                 if (x & 1)
95                         extra_bits++;
96                 x >>= 1;
97                 shifts++;
98         }
99
100         if (extra_bits)
101                 shifts++;
102
103         return shifts;
104 }
105
106 /* Function to return the number of shifts to get a 1 in bit 0
107  */
108
109 static u32 calc_shifts(u32 x)
110 {
111         u32 shifts;
112
113         shifts = 0;
114
115         if (!x)
116                 return 0;
117
118         while (!(x & 1)) {
119                 x >>= 1;
120                 shifts++;
121         }
122
123         return shifts;
124 }
125
126 /*
127  * Temporary buffer manipulations.
128  */
129
130 static int yaffs_init_tmp_buffers(struct yaffs_dev *dev)
131 {
132         int i;
133         u8 *buf = (u8 *) 1;
134
135         memset(dev->temp_buffer, 0, sizeof(dev->temp_buffer));
136
137         for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
138                 dev->temp_buffer[i].line = 0;   /* not in use */
139                 dev->temp_buffer[i].buffer = buf =
140                     kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
141         }
142
143         return buf ? YAFFS_OK : YAFFS_FAIL;
144 }
145
146 u8 *yaffs_get_temp_buffer(struct yaffs_dev * dev, int line_no)
147 {
148         int i, j;
149
150         dev->temp_in_use++;
151         if (dev->temp_in_use > dev->max_temp)
152                 dev->max_temp = dev->temp_in_use;
153
154         for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
155                 if (dev->temp_buffer[i].line == 0) {
156                         dev->temp_buffer[i].line = line_no;
157                         if ((i + 1) > dev->max_temp) {
158                                 dev->max_temp = i + 1;
159                                 for (j = 0; j <= i; j++)
160                                         dev->temp_buffer[j].max_line =
161                                             dev->temp_buffer[j].line;
162                         }
163
164                         return dev->temp_buffer[i].buffer;
165                 }
166         }
167
168         T(YAFFS_TRACE_BUFFERS,
169           (TSTR("Out of temp buffers at line %d, other held by lines:"),
170            line_no));
171         for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)
172                 T(YAFFS_TRACE_BUFFERS,
173                   (TSTR(" %d "), dev->temp_buffer[i].line));
174
175         T(YAFFS_TRACE_BUFFERS, (TSTR(" " TENDSTR)));
176
177         /*
178          * If we got here then we have to allocate an unmanaged one
179          * This is not good.
180          */
181
182         dev->unmanaged_buffer_allocs++;
183         return kmalloc(dev->data_bytes_per_chunk, GFP_NOFS);
184
185 }
186
187 void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 * buffer, int line_no)
188 {
189         int i;
190
191         dev->temp_in_use--;
192
193         for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
194                 if (dev->temp_buffer[i].buffer == buffer) {
195                         dev->temp_buffer[i].line = 0;
196                         return;
197                 }
198         }
199
200         if (buffer) {
201                 /* assume it is an unmanaged one. */
202                 T(YAFFS_TRACE_BUFFERS,
203                   (TSTR("Releasing unmanaged temp buffer in line %d" TENDSTR),
204                    line_no));
205                 kfree(buffer);
206                 dev->unmanaged_buffer_deallocs++;
207         }
208
209 }
210
211 /*
212  * Determine if we have a managed buffer.
213  */
214 int yaffs_is_managed_tmp_buffer(struct yaffs_dev *dev, const u8 * buffer)
215 {
216         int i;
217
218         for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
219                 if (dev->temp_buffer[i].buffer == buffer)
220                         return 1;
221         }
222
223         for (i = 0; i < dev->param.n_caches; i++) {
224                 if (dev->cache[i].data == buffer)
225                         return 1;
226         }
227
228         if (buffer == dev->checkpt_buffer)
229                 return 1;
230
231         T(YAFFS_TRACE_ALWAYS,
232           (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR)));
233         return 0;
234 }
235
236 /*
237  * Functions for robustisizing TODO
238  *
239  */
240
241 static void yaffs_handle_chunk_wr_ok(struct yaffs_dev *dev, int nand_chunk,
242                                      const u8 * data,
243                                      const struct yaffs_ext_tags *tags)
244 {
245         dev = dev;
246         nand_chunk = nand_chunk;
247         data = data;
248         tags = tags;
249 }
250
251 static void yaffs_handle_chunk_update(struct yaffs_dev *dev, int nand_chunk,
252                                       const struct yaffs_ext_tags *tags)
253 {
254         dev = dev;
255         nand_chunk = nand_chunk;
256         tags = tags;
257 }
258
259 void yaffs_handle_chunk_error(struct yaffs_dev *dev,
260                               struct yaffs_block_info *bi)
261 {
262         if (!bi->gc_prioritise) {
263                 bi->gc_prioritise = 1;
264                 dev->has_pending_prioritised_gc = 1;
265                 bi->chunk_error_strikes++;
266
267                 if (bi->chunk_error_strikes > 3) {
268                         bi->needs_retiring = 1; /* Too many stikes, so retire this */
269                         T(YAFFS_TRACE_ALWAYS,
270                           (TSTR("yaffs: Block struck out" TENDSTR)));
271
272                 }
273         }
274 }
275
276 static void yaffs_handle_chunk_wr_error(struct yaffs_dev *dev, int nand_chunk,
277                                         int erased_ok)
278 {
279         int flash_block = nand_chunk / dev->param.chunks_per_block;
280         struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block);
281
282         yaffs_handle_chunk_error(dev, bi);
283
284         if (erased_ok) {
285                 /* Was an actual write failure, so mark the block for retirement  */
286                 bi->needs_retiring = 1;
287                 T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
288                   (TSTR("**>> Block %d needs retiring" TENDSTR), flash_block));
289         }
290
291         /* Delete the chunk */
292         yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
293         yaffs_skip_rest_of_block(dev);
294 }
295
296 /*
297  * Verification code
298  */
299
300 /*
301  *  Simple hash function. Needs to have a reasonable spread
302  */
303
304 static Y_INLINE int yaffs_hash_fn(int n)
305 {
306         n = abs(n);
307         return n % YAFFS_NOBJECT_BUCKETS;
308 }
309
310 /*
311  * Access functions to useful fake objects.
312  * Note that root might have a presence in NAND if permissions are set.
313  */
314
315 struct yaffs_obj *yaffs_root(struct yaffs_dev *dev)
316 {
317         return dev->root_dir;
318 }
319
320 struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev)
321 {
322         return dev->lost_n_found;
323 }
324
325 /*
326  *  Erased NAND checking functions
327  */
328
329 int yaffs_check_ff(u8 * buffer, int n_bytes)
330 {
331         /* Horrible, slow implementation */
332         while (n_bytes--) {
333                 if (*buffer != 0xFF)
334                         return 0;
335                 buffer++;
336         }
337         return 1;
338 }
339
340 static int yaffs_check_chunk_erased(struct yaffs_dev *dev, int nand_chunk)
341 {
342         int retval = YAFFS_OK;
343         u8 *data = yaffs_get_temp_buffer(dev, __LINE__);
344         struct yaffs_ext_tags tags;
345         int result;
346
347         result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags);
348
349         if (tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR)
350                 retval = YAFFS_FAIL;
351
352         if (!yaffs_check_ff(data, dev->data_bytes_per_chunk) || tags.chunk_used) {
353                 T(YAFFS_TRACE_NANDACCESS,
354                   (TSTR("Chunk %d not erased" TENDSTR), nand_chunk));
355                 retval = YAFFS_FAIL;
356         }
357
358         yaffs_release_temp_buffer(dev, data, __LINE__);
359
360         return retval;
361
362 }
363
364 static int yaffs_verify_chunk_written(struct yaffs_dev *dev,
365                                       int nand_chunk,
366                                       const u8 * data,
367                                       struct yaffs_ext_tags *tags)
368 {
369         int retval = YAFFS_OK;
370         struct yaffs_ext_tags temp_tags;
371         u8 *buffer = yaffs_get_temp_buffer(dev, __LINE__);
372         int result;
373
374         result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, buffer, &temp_tags);
375         if (memcmp(buffer, data, dev->data_bytes_per_chunk) ||
376             temp_tags.obj_id != tags->obj_id ||
377             temp_tags.chunk_id != tags->chunk_id ||
378             temp_tags.n_bytes != tags->n_bytes)
379                 retval = YAFFS_FAIL;
380
381         yaffs_release_temp_buffer(dev, buffer, __LINE__);
382
383         return retval;
384 }
385
386
387 int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks)
388 {
389         int reserved_chunks;
390         int reserved_blocks = dev->param.n_reserved_blocks;
391         int checkpt_blocks;
392
393         checkpt_blocks = yaffs_calc_checkpt_blocks_required(dev);
394
395         reserved_chunks =
396             ((reserved_blocks + checkpt_blocks) * dev->param.chunks_per_block);
397
398         return (dev->n_free_chunks > (reserved_chunks + n_chunks));
399 }
400
401 static int yaffs_find_alloc_block(struct yaffs_dev *dev)
402 {
403         int i;
404
405         struct yaffs_block_info *bi;
406
407         if (dev->n_erased_blocks < 1) {
408                 /* Hoosterman we've got a problem.
409                  * Can't get space to gc
410                  */
411                 T(YAFFS_TRACE_ERROR,
412                   (TSTR("yaffs tragedy: no more erased blocks" TENDSTR)));
413
414                 return -1;
415         }
416
417         /* Find an empty block. */
418
419         for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
420                 dev->alloc_block_finder++;
421                 if (dev->alloc_block_finder < dev->internal_start_block
422                     || dev->alloc_block_finder > dev->internal_end_block) {
423                         dev->alloc_block_finder = dev->internal_start_block;
424                 }
425
426                 bi = yaffs_get_block_info(dev, dev->alloc_block_finder);
427
428                 if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
429                         bi->block_state = YAFFS_BLOCK_STATE_ALLOCATING;
430                         dev->seq_number++;
431                         bi->seq_number = dev->seq_number;
432                         dev->n_erased_blocks--;
433                         T(YAFFS_TRACE_ALLOCATE,
434                           (TSTR("Allocated block %d, seq  %d, %d left" TENDSTR),
435                            dev->alloc_block_finder, dev->seq_number,
436                            dev->n_erased_blocks));
437                         return dev->alloc_block_finder;
438                 }
439         }
440
441         T(YAFFS_TRACE_ALWAYS,
442           (TSTR
443            ("yaffs tragedy: no more erased blocks, but there should have been %d"
444             TENDSTR), dev->n_erased_blocks));
445
446         return -1;
447 }
448 static int yaffs_alloc_chunk(struct yaffs_dev *dev, int use_reserver,
449                              struct yaffs_block_info **block_ptr)
450 {
451         int ret_val;
452         struct yaffs_block_info *bi;
453
454         if (dev->alloc_block < 0) {
455                 /* Get next block to allocate off */
456                 dev->alloc_block = yaffs_find_alloc_block(dev);
457                 dev->alloc_page = 0;
458         }
459
460         if (!use_reserver && !yaffs_check_alloc_available(dev, 1)) {
461                 /* Not enough space to allocate unless we're allowed to use the reserve. */
462                 return -1;
463         }
464
465         if (dev->n_erased_blocks < dev->param.n_reserved_blocks
466             && dev->alloc_page == 0) {
467                 T(YAFFS_TRACE_ALLOCATE, (TSTR("Allocating reserve" TENDSTR)));
468         }
469
470         /* Next page please.... */
471         if (dev->alloc_block >= 0) {
472                 bi = yaffs_get_block_info(dev, dev->alloc_block);
473
474                 ret_val = (dev->alloc_block * dev->param.chunks_per_block) +
475                     dev->alloc_page;
476                 bi->pages_in_use++;
477                 yaffs_set_chunk_bit(dev, dev->alloc_block, dev->alloc_page);
478
479                 dev->alloc_page++;
480
481                 dev->n_free_chunks--;
482
483                 /* If the block is full set the state to full */
484                 if (dev->alloc_page >= dev->param.chunks_per_block) {
485                         bi->block_state = YAFFS_BLOCK_STATE_FULL;
486                         dev->alloc_block = -1;
487                 }
488
489                 if (block_ptr)
490                         *block_ptr = bi;
491
492                 return ret_val;
493         }
494
495         T(YAFFS_TRACE_ERROR,
496           (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));
497
498         return -1;
499 }
500
501 static int yaffs_get_erased_chunks(struct yaffs_dev *dev)
502 {
503         int n;
504
505         n = dev->n_erased_blocks * dev->param.chunks_per_block;
506
507         if (dev->alloc_block > 0)
508                 n += (dev->param.chunks_per_block - dev->alloc_page);
509
510         return n;
511
512 }
513
514 /*
515  * yaffs_skip_rest_of_block() skips over the rest of the allocation block
516  * if we don't want to write to it.
517  */
518 void yaffs_skip_rest_of_block(struct yaffs_dev *dev)
519 {
520         if (dev->alloc_block > 0) {
521                 struct yaffs_block_info *bi =
522                     yaffs_get_block_info(dev, dev->alloc_block);
523                 if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) {
524                         bi->block_state = YAFFS_BLOCK_STATE_FULL;
525                         dev->alloc_block = -1;
526                 }
527         }
528 }
529
530 static int yaffs_write_new_chunk(struct yaffs_dev *dev,
531                                  const u8 * data,
532                                  struct yaffs_ext_tags *tags, int use_reserver)
533 {
534         int attempts = 0;
535         int write_ok = 0;
536         int chunk;
537
538         yaffs2_checkpt_invalidate(dev);
539
540         do {
541                 struct yaffs_block_info *bi = 0;
542                 int erased_ok = 0;
543
544                 chunk = yaffs_alloc_chunk(dev, use_reserver, &bi);
545                 if (chunk < 0) {
546                         /* no space */
547                         break;
548                 }
549
550                 /* First check this chunk is erased, if it needs
551                  * checking.  The checking policy (unless forced
552                  * always on) is as follows:
553                  *
554                  * Check the first page we try to write in a block.
555                  * If the check passes then we don't need to check any
556                  * more.        If the check fails, we check again...
557                  * If the block has been erased, we don't need to check.
558                  *
559                  * However, if the block has been prioritised for gc,
560                  * then we think there might be something odd about
561                  * this block and stop using it.
562                  *
563                  * Rationale: We should only ever see chunks that have
564                  * not been erased if there was a partially written
565                  * chunk due to power loss.  This checking policy should
566                  * catch that case with very few checks and thus save a
567                  * lot of checks that are most likely not needed.
568                  *
569                  * Mods to the above
570                  * If an erase check fails or the write fails we skip the 
571                  * rest of the block.
572                  */
573
574                 /* let's give it a try */
575                 attempts++;
576
577                 if (dev->param.always_check_erased)
578                         bi->skip_erased_check = 0;
579
580                 if (!bi->skip_erased_check) {
581                         erased_ok = yaffs_check_chunk_erased(dev, chunk);
582                         if (erased_ok != YAFFS_OK) {
583                                 T(YAFFS_TRACE_ERROR,
584                                   (TSTR("**>> yaffs chunk %d was not erased"
585                                         TENDSTR), chunk));
586
587                                 /* If not erased, delete this one,
588                                  * skip rest of block and
589                                  * try another chunk */
590                                 yaffs_chunk_del(dev, chunk, 1, __LINE__);
591                                 yaffs_skip_rest_of_block(dev);
592                                 continue;
593                         }
594                 }
595
596                 write_ok = yaffs_wr_chunk_tags_nand(dev, chunk, data, tags);
597
598                 if (!bi->skip_erased_check)
599                         write_ok =
600                             yaffs_verify_chunk_written(dev, chunk, data, tags);
601
602                 if (write_ok != YAFFS_OK) {
603                         /* Clean up aborted write, skip to next block and
604                          * try another chunk */
605                         yaffs_handle_chunk_wr_error(dev, chunk, erased_ok);
606                         continue;
607                 }
608
609                 bi->skip_erased_check = 1;
610
611                 /* Copy the data into the robustification buffer */
612                 yaffs_handle_chunk_wr_ok(dev, chunk, data, tags);
613
614         } while (write_ok != YAFFS_OK &&
615                  (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
616
617         if (!write_ok)
618                 chunk = -1;
619
620         if (attempts > 1) {
621                 T(YAFFS_TRACE_ERROR,
622                   (TSTR("**>> yaffs write required %d attempts" TENDSTR),
623                    attempts));
624
625                 dev->n_retired_writes += (attempts - 1);
626         }
627
628         return chunk;
629 }
630
631 /*
632  * Block retiring for handling a broken block.
633  */
634
635 static void yaffs_retire_block(struct yaffs_dev *dev, int flash_block)
636 {
637         struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block);
638
639         yaffs2_checkpt_invalidate(dev);
640
641         yaffs2_clear_oldest_dirty_seq(dev, bi);
642
643         if (yaffs_mark_bad(dev, flash_block) != YAFFS_OK) {
644                 if (yaffs_erase_block(dev, flash_block) != YAFFS_OK) {
645                         T(YAFFS_TRACE_ALWAYS,
646                           (TSTR
647                            ("yaffs: Failed to mark bad and erase block %d"
648                             TENDSTR), flash_block));
649                 } else {
650                         struct yaffs_ext_tags tags;
651                         int chunk_id =
652                             flash_block * dev->param.chunks_per_block;
653
654                         u8 *buffer = yaffs_get_temp_buffer(dev, __LINE__);
655
656                         memset(buffer, 0xff, dev->data_bytes_per_chunk);
657                         yaffs_init_tags(&tags);
658                         tags.seq_number = YAFFS_SEQUENCE_BAD_BLOCK;
659                         if (dev->param.write_chunk_tags_fn(dev, chunk_id -
660                                                            dev->chunk_offset,
661                                                            buffer,
662                                                            &tags) != YAFFS_OK)
663                                 T(YAFFS_TRACE_ALWAYS,
664                                   (TSTR
665                                    ("yaffs: Failed to "
666                                     TCONT("write bad block marker to block %d")
667                                     TENDSTR), flash_block));
668
669                         yaffs_release_temp_buffer(dev, buffer, __LINE__);
670                 }
671         }
672
673         bi->block_state = YAFFS_BLOCK_STATE_DEAD;
674         bi->gc_prioritise = 0;
675         bi->needs_retiring = 0;
676
677         dev->n_retired_blocks++;
678 }
679
680 /*---------------- Name handling functions ------------*/
681
682 static u16 yaffs_calc_name_sum(const YCHAR * name)
683 {
684         u16 sum = 0;
685         u16 i = 1;
686
687         const YUCHAR *bname = (const YUCHAR *)name;
688         if (bname) {
689                 while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH / 2))) {
690
691                         /* 0x1f mask is case insensitive */
692                         sum += ((*bname) & 0x1f) * i;
693                         i++;
694                         bname++;
695                 }
696         }
697         return sum;
698 }
699
700 void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name)
701 {
702 #ifndef CONFIG_YAFFS_NO_SHORT_NAMES
703         memset(obj->short_name, 0, sizeof(obj->short_name));
704         if (name && 
705                 strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <=
706             YAFFS_SHORT_NAME_LENGTH)
707                 strcpy(obj->short_name, name);
708         else
709                 obj->short_name[0] = _Y('\0');
710 #endif
711         obj->sum = yaffs_calc_name_sum(name);
712 }
713
714 void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj,
715                                 const struct yaffs_obj_hdr *oh)
716 {
717 #ifdef CONFIG_YAFFS_AUTO_UNICODE
718         YCHAR tmp_name[YAFFS_MAX_NAME_LENGTH + 1];
719         memset(tmp_name, 0, sizeof(tmp_name));
720         yaffs_load_name_from_oh(obj->my_dev, tmp_name, oh->name,
721                                 YAFFS_MAX_NAME_LENGTH + 1);
722         yaffs_set_obj_name(obj, tmp_name);
723 #else
724         yaffs_set_obj_name(obj, oh->name);
725 #endif
726 }
727
728 /*-------------------- TNODES -------------------
729
730  * List of spare tnodes
731  * The list is hooked together using the first pointer
732  * in the tnode.
733  */
734
735 struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev)
736 {
737         struct yaffs_tnode *tn = yaffs_alloc_raw_tnode(dev);
738         if (tn) {
739                 memset(tn, 0, dev->tnode_size);
740                 dev->n_tnodes++;
741         }
742
743         dev->checkpoint_blocks_required = 0;    /* force recalculation */
744
745         return tn;
746 }
747
748 /* FreeTnode frees up a tnode and puts it back on the free list */
749 static void yaffs_free_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
750 {
751         yaffs_free_raw_tnode(dev, tn);
752         dev->n_tnodes--;
753         dev->checkpoint_blocks_required = 0;    /* force recalculation */
754 }
755
756 static void yaffs_deinit_tnodes_and_objs(struct yaffs_dev *dev)
757 {
758         yaffs_deinit_raw_tnodes_and_objs(dev);
759         dev->n_obj = 0;
760         dev->n_tnodes = 0;
761 }
762
763 void yaffs_load_tnode_0(struct yaffs_dev *dev, struct yaffs_tnode *tn,
764                         unsigned pos, unsigned val)
765 {
766         u32 *map = (u32 *) tn;
767         u32 bit_in_map;
768         u32 bit_in_word;
769         u32 word_in_map;
770         u32 mask;
771
772         pos &= YAFFS_TNODES_LEVEL0_MASK;
773         val >>= dev->chunk_grp_bits;
774
775         bit_in_map = pos * dev->tnode_width;
776         word_in_map = bit_in_map / 32;
777         bit_in_word = bit_in_map & (32 - 1);
778
779         mask = dev->tnode_mask << bit_in_word;
780
781         map[word_in_map] &= ~mask;
782         map[word_in_map] |= (mask & (val << bit_in_word));
783
784         if (dev->tnode_width > (32 - bit_in_word)) {
785                 bit_in_word = (32 - bit_in_word);
786                 word_in_map++;;
787                 mask =
788                     dev->tnode_mask >> ( /*dev->tnode_width - */ bit_in_word);
789                 map[word_in_map] &= ~mask;
790                 map[word_in_map] |= (mask & (val >> bit_in_word));
791         }
792 }
793
794 u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
795                          unsigned pos)
796 {
797         u32 *map = (u32 *) tn;
798         u32 bit_in_map;
799         u32 bit_in_word;
800         u32 word_in_map;
801         u32 val;
802
803         pos &= YAFFS_TNODES_LEVEL0_MASK;
804
805         bit_in_map = pos * dev->tnode_width;
806         word_in_map = bit_in_map / 32;
807         bit_in_word = bit_in_map & (32 - 1);
808
809         val = map[word_in_map] >> bit_in_word;
810
811         if (dev->tnode_width > (32 - bit_in_word)) {
812                 bit_in_word = (32 - bit_in_word);
813                 word_in_map++;;
814                 val |= (map[word_in_map] << bit_in_word);
815         }
816
817         val &= dev->tnode_mask;
818         val <<= dev->chunk_grp_bits;
819
820         return val;
821 }
822
823 /* ------------------- End of individual tnode manipulation -----------------*/
824
825 /* ---------Functions to manipulate the look-up tree (made up of tnodes) ------
826  * The look up tree is represented by the top tnode and the number of top_level
827  * in the tree. 0 means only the level 0 tnode is in the tree.
828  */
829
830 /* FindLevel0Tnode finds the level 0 tnode, if one exists. */
831 struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev,
832                                        struct yaffs_file_var *file_struct,
833                                        u32 chunk_id)
834 {
835         struct yaffs_tnode *tn = file_struct->top;
836         u32 i;
837         int required_depth;
838         int level = file_struct->top_level;
839
840         dev = dev;
841
842         /* Check sane level and chunk Id */
843         if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL)
844                 return NULL;
845
846         if (chunk_id > YAFFS_MAX_CHUNK_ID)
847                 return NULL;
848
849         /* First check we're tall enough (ie enough top_level) */
850
851         i = chunk_id >> YAFFS_TNODES_LEVEL0_BITS;
852         required_depth = 0;
853         while (i) {
854                 i >>= YAFFS_TNODES_INTERNAL_BITS;
855                 required_depth++;
856         }
857
858         if (required_depth > file_struct->top_level)
859                 return NULL;    /* Not tall enough, so we can't find it */
860
861         /* Traverse down to level 0 */
862         while (level > 0 && tn) {
863                 tn = tn->internal[(chunk_id >>
864                                    (YAFFS_TNODES_LEVEL0_BITS +
865                                     (level - 1) *
866                                     YAFFS_TNODES_INTERNAL_BITS)) &
867                                   YAFFS_TNODES_INTERNAL_MASK];
868                 level--;
869         }
870
871         return tn;
872 }
873
874 /* AddOrFindLevel0Tnode finds the level 0 tnode if it exists, otherwise first expands the tree.
875  * This happens in two steps:
876  *  1. If the tree isn't tall enough, then make it taller.
877  *  2. Scan down the tree towards the level 0 tnode adding tnodes if required.
878  *
879  * Used when modifying the tree.
880  *
881  *  If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will
882  *  be plugged into the ttree.
883  */
884
885 struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev,
886                                            struct yaffs_file_var *file_struct,
887                                            u32 chunk_id,
888                                            struct yaffs_tnode *passed_tn)
889 {
890         int required_depth;
891         int i;
892         int l;
893         struct yaffs_tnode *tn;
894
895         u32 x;
896
897         /* Check sane level and page Id */
898         if (file_struct->top_level < 0
899             || file_struct->top_level > YAFFS_TNODES_MAX_LEVEL)
900                 return NULL;
901
902         if (chunk_id > YAFFS_MAX_CHUNK_ID)
903                 return NULL;
904
905         /* First check we're tall enough (ie enough top_level) */
906
907         x = chunk_id >> YAFFS_TNODES_LEVEL0_BITS;
908         required_depth = 0;
909         while (x) {
910                 x >>= YAFFS_TNODES_INTERNAL_BITS;
911                 required_depth++;
912         }
913
914         if (required_depth > file_struct->top_level) {
915                 /* Not tall enough, gotta make the tree taller */
916                 for (i = file_struct->top_level; i < required_depth; i++) {
917
918                         tn = yaffs_get_tnode(dev);
919
920                         if (tn) {
921                                 tn->internal[0] = file_struct->top;
922                                 file_struct->top = tn;
923                                 file_struct->top_level++;
924                         } else {
925                                 T(YAFFS_TRACE_ERROR,
926                                   (TSTR("yaffs: no more tnodes" TENDSTR)));
927                                 return NULL;
928                         }
929                 }
930         }
931
932         /* Traverse down to level 0, adding anything we need */
933
934         l = file_struct->top_level;
935         tn = file_struct->top;
936
937         if (l > 0) {
938                 while (l > 0 && tn) {
939                         x = (chunk_id >>
940                              (YAFFS_TNODES_LEVEL0_BITS +
941                               (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) &
942                             YAFFS_TNODES_INTERNAL_MASK;
943
944                         if ((l > 1) && !tn->internal[x]) {
945                                 /* Add missing non-level-zero tnode */
946                                 tn->internal[x] = yaffs_get_tnode(dev);
947                                 if (!tn->internal[x])
948                                         return NULL;
949                         } else if (l == 1) {
950                                 /* Looking from level 1 at level 0 */
951                                 if (passed_tn) {
952                                         /* If we already have one, then release it. */
953                                         if (tn->internal[x])
954                                                 yaffs_free_tnode(dev,
955                                                                  tn->
956                                                                  internal[x]);
957                                         tn->internal[x] = passed_tn;
958
959                                 } else if (!tn->internal[x]) {
960                                         /* Don't have one, none passed in */
961                                         tn->internal[x] = yaffs_get_tnode(dev);
962                                         if (!tn->internal[x])
963                                                 return NULL;
964                                 }
965                         }
966
967                         tn = tn->internal[x];
968                         l--;
969                 }
970         } else {
971                 /* top is level 0 */
972                 if (passed_tn) {
973                         memcpy(tn, passed_tn,
974                                (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8);
975                         yaffs_free_tnode(dev, passed_tn);
976                 }
977         }
978
979         return tn;
980 }
981
982 static int yaffs_tags_match(const struct yaffs_ext_tags *tags, int obj_id,
983                             int chunk_obj)
984 {
985         return (tags->chunk_id == chunk_obj &&
986                 tags->obj_id == obj_id && !tags->is_deleted) ? 1 : 0;
987
988 }
989
990 static int yaffs_find_chunk_in_group(struct yaffs_dev *dev, int the_chunk,
991                                      struct yaffs_ext_tags *tags, int obj_id,
992                                      int inode_chunk)
993 {
994         int j;
995
996         for (j = 0; the_chunk && j < dev->chunk_grp_size; j++) {
997                 if (yaffs_check_chunk_bit
998                     (dev, the_chunk / dev->param.chunks_per_block,
999                      the_chunk % dev->param.chunks_per_block)) {
1000
1001                         if (dev->chunk_grp_size == 1)
1002                                 return the_chunk;
1003                         else {
1004                                 yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL,
1005                                                          tags);
1006                                 if (yaffs_tags_match(tags, obj_id, inode_chunk)) {
1007                                         /* found it; */
1008                                         return the_chunk;
1009                                 }
1010                         }
1011                 }
1012                 the_chunk++;
1013         }
1014         return -1;
1015 }
1016
1017 static int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
1018                                     struct yaffs_ext_tags *tags)
1019 {
1020         /*Get the Tnode, then get the level 0 offset chunk offset */
1021         struct yaffs_tnode *tn;
1022         int the_chunk = -1;
1023         struct yaffs_ext_tags local_tags;
1024         int ret_val = -1;
1025
1026         struct yaffs_dev *dev = in->my_dev;
1027
1028         if (!tags) {
1029                 /* Passed a NULL, so use our own tags space */
1030                 tags = &local_tags;
1031         }
1032
1033         tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk);
1034
1035         if (tn) {
1036                 the_chunk = yaffs_get_group_base(dev, tn, inode_chunk);
1037
1038                 ret_val =
1039                     yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id,
1040                                               inode_chunk);
1041         }
1042         return ret_val;
1043 }
1044
1045 static int yaffs_find_del_file_chunk(struct yaffs_obj *in, int inode_chunk,
1046                                      struct yaffs_ext_tags *tags)
1047 {
1048         /* Get the Tnode, then get the level 0 offset chunk offset */
1049         struct yaffs_tnode *tn;
1050         int the_chunk = -1;
1051         struct yaffs_ext_tags local_tags;
1052
1053         struct yaffs_dev *dev = in->my_dev;
1054         int ret_val = -1;
1055
1056         if (!tags) {
1057                 /* Passed a NULL, so use our own tags space */
1058                 tags = &local_tags;
1059         }
1060
1061         tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk);
1062
1063         if (tn) {
1064
1065                 the_chunk = yaffs_get_group_base(dev, tn, inode_chunk);
1066
1067                 ret_val =
1068                     yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id,
1069                                               inode_chunk);
1070
1071                 /* Delete the entry in the filestructure (if found) */
1072                 if (ret_val != -1)
1073                         yaffs_load_tnode_0(dev, tn, inode_chunk, 0);
1074         }
1075
1076         return ret_val;
1077 }
1078
1079 int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
1080                             int nand_chunk, int in_scan)
1081 {
1082         /* NB in_scan is zero unless scanning.
1083          * For forward scanning, in_scan is > 0;
1084          * for backward scanning in_scan is < 0
1085          *
1086          * nand_chunk = 0 is a dummy insert to make sure the tnodes are there.
1087          */
1088
1089         struct yaffs_tnode *tn;
1090         struct yaffs_dev *dev = in->my_dev;
1091         int existing_cunk;
1092         struct yaffs_ext_tags existing_tags;
1093         struct yaffs_ext_tags new_tags;
1094         unsigned existing_serial, new_serial;
1095
1096         if (in->variant_type != YAFFS_OBJECT_TYPE_FILE) {
1097                 /* Just ignore an attempt at putting a chunk into a non-file during scanning
1098                  * If it is not during Scanning then something went wrong!
1099                  */
1100                 if (!in_scan) {
1101                         T(YAFFS_TRACE_ERROR,
1102                           (TSTR
1103                            ("yaffs tragedy:attempt to put data chunk into a non-file"
1104                             TENDSTR)));
1105                         YBUG();
1106                 }
1107
1108                 yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
1109                 return YAFFS_OK;
1110         }
1111
1112         tn = yaffs_add_find_tnode_0(dev,
1113                                     &in->variant.file_variant,
1114                                     inode_chunk, NULL);
1115         if (!tn)
1116                 return YAFFS_FAIL;
1117
1118         if (!nand_chunk)
1119                 /* Dummy insert, bail now */
1120                 return YAFFS_OK;
1121
1122         existing_cunk = yaffs_get_group_base(dev, tn, inode_chunk);
1123
1124         if (in_scan != 0) {
1125                 /* If we're scanning then we need to test for duplicates
1126                  * NB This does not need to be efficient since it should only ever
1127                  * happen when the power fails during a write, then only one
1128                  * chunk should ever be affected.
1129                  *
1130                  * Correction for YAFFS2: This could happen quite a lot and we need to think about efficiency! TODO
1131                  * Update: For backward scanning we don't need to re-read tags so this is quite cheap.
1132                  */
1133
1134                 if (existing_cunk > 0) {
1135                         /* NB Right now existing chunk will not be real chunk_id if the chunk group size > 1
1136                          *    thus we have to do a FindChunkInFile to get the real chunk id.
1137                          *
1138                          * We have a duplicate now we need to decide which one to use:
1139                          *
1140                          * Backwards scanning YAFFS2: The old one is what we use, dump the new one.
1141                          * Forward scanning YAFFS2: The new one is what we use, dump the old one.
1142                          * YAFFS1: Get both sets of tags and compare serial numbers.
1143                          */
1144
1145                         if (in_scan > 0) {
1146                                 /* Only do this for forward scanning */
1147                                 yaffs_rd_chunk_tags_nand(dev,
1148                                                          nand_chunk,
1149                                                          NULL, &new_tags);
1150
1151                                 /* Do a proper find */
1152                                 existing_cunk =
1153                                     yaffs_find_chunk_in_file(in, inode_chunk,
1154                                                              &existing_tags);
1155                         }
1156
1157                         if (existing_cunk <= 0) {
1158                                 /*Hoosterman - how did this happen? */
1159
1160                                 T(YAFFS_TRACE_ERROR,
1161                                   (TSTR
1162                                    ("yaffs tragedy: existing chunk < 0 in scan"
1163                                     TENDSTR)));
1164
1165                         }
1166
1167                         /* NB The deleted flags should be false, otherwise the chunks will
1168                          * not be loaded during a scan
1169                          */
1170
1171                         if (in_scan > 0) {
1172                                 new_serial = new_tags.serial_number;
1173                                 existing_serial = existing_tags.serial_number;
1174                         }
1175
1176                         if ((in_scan > 0) &&
1177                             (existing_cunk <= 0 ||
1178                              ((existing_serial + 1) & 3) == new_serial)) {
1179                                 /* Forward scanning.
1180                                  * Use new
1181                                  * Delete the old one and drop through to update the tnode
1182                                  */
1183                                 yaffs_chunk_del(dev, existing_cunk, 1,
1184                                                 __LINE__);
1185                         } else {
1186                                 /* Backward scanning or we want to use the existing one
1187                                  * Use existing.
1188                                  * Delete the new one and return early so that the tnode isn't changed
1189                                  */
1190                                 yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
1191                                 return YAFFS_OK;
1192                         }
1193                 }
1194
1195         }
1196
1197         if (existing_cunk == 0)
1198                 in->n_data_chunks++;
1199
1200         yaffs_load_tnode_0(dev, tn, inode_chunk, nand_chunk);
1201
1202         return YAFFS_OK;
1203 }
1204
1205 static void yaffs_soft_del_chunk(struct yaffs_dev *dev, int chunk)
1206 {
1207         struct yaffs_block_info *the_block;
1208         unsigned block_no;
1209
1210         T(YAFFS_TRACE_DELETION, (TSTR("soft delete chunk %d" TENDSTR), chunk));
1211
1212         block_no = chunk / dev->param.chunks_per_block;
1213         the_block = yaffs_get_block_info(dev, block_no);
1214         if (the_block) {
1215                 the_block->soft_del_pages++;
1216                 dev->n_free_chunks++;
1217                 yaffs2_update_oldest_dirty_seq(dev, block_no, the_block);
1218         }
1219 }
1220
1221 /* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file.
1222  * All soft deleting does is increment the block's softdelete count and pulls the chunk out
1223  * of the tnode.
1224  * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
1225  */
1226
1227 static int yaffs_soft_del_worker(struct yaffs_obj *in, struct yaffs_tnode *tn,
1228                                  u32 level, int chunk_offset)
1229 {
1230         int i;
1231         int the_chunk;
1232         int all_done = 1;
1233         struct yaffs_dev *dev = in->my_dev;
1234
1235         if (tn) {
1236                 if (level > 0) {
1237
1238                         for (i = YAFFS_NTNODES_INTERNAL - 1; all_done && i >= 0;
1239                              i--) {
1240                                 if (tn->internal[i]) {
1241                                         all_done =
1242                                             yaffs_soft_del_worker(in,
1243                                                                   tn->internal
1244                                                                   [i],
1245                                                                   level - 1,
1246                                                                   (chunk_offset
1247                                                                    <<
1248                                                                    YAFFS_TNODES_INTERNAL_BITS)
1249                                                                   + i);
1250                                         if (all_done) {
1251                                                 yaffs_free_tnode(dev,
1252                                                                  tn->internal
1253                                                                  [i]);
1254                                                 tn->internal[i] = NULL;
1255                                         } else {
1256                                                 /* Hoosterman... how could this happen? */
1257                                         }
1258                                 }
1259                         }
1260                         return (all_done) ? 1 : 0;
1261                 } else if (level == 0) {
1262
1263                         for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) {
1264                                 the_chunk = yaffs_get_group_base(dev, tn, i);
1265                                 if (the_chunk) {
1266                                         /* Note this does not find the real chunk, only the chunk group.
1267                                          * We make an assumption that a chunk group is not larger than
1268                                          * a block.
1269                                          */
1270                                         yaffs_soft_del_chunk(dev, the_chunk);
1271                                         yaffs_load_tnode_0(dev, tn, i, 0);
1272                                 }
1273
1274                         }
1275                         return 1;
1276
1277                 }
1278
1279         }
1280
1281         return 1;
1282
1283 }
1284
1285 static void yaffs_remove_obj_from_dir(struct yaffs_obj *obj)
1286 {
1287         struct yaffs_dev *dev = obj->my_dev;
1288         struct yaffs_obj *parent;
1289
1290         yaffs_verify_obj_in_dir(obj);
1291         parent = obj->parent;
1292
1293         yaffs_verify_dir(parent);
1294
1295         if (dev && dev->param.remove_obj_fn)
1296                 dev->param.remove_obj_fn(obj);
1297
1298         list_del_init(&obj->siblings);
1299         obj->parent = NULL;
1300
1301         yaffs_verify_dir(parent);
1302 }
1303
1304 void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj)
1305 {
1306         if (!directory) {
1307                 T(YAFFS_TRACE_ALWAYS,
1308                   (TSTR
1309                    ("tragedy: Trying to add an object to a null pointer directory"
1310                     TENDSTR)));
1311                 YBUG();
1312                 return;
1313         }
1314         if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
1315                 T(YAFFS_TRACE_ALWAYS,
1316                   (TSTR
1317                    ("tragedy: Trying to add an object to a non-directory"
1318                     TENDSTR)));
1319                 YBUG();
1320         }
1321
1322         if (obj->siblings.prev == NULL) {
1323                 /* Not initialised */
1324                 YBUG();
1325         }
1326
1327         yaffs_verify_dir(directory);
1328
1329         yaffs_remove_obj_from_dir(obj);
1330
1331         /* Now add it */
1332         list_add(&obj->siblings, &directory->variant.dir_variant.children);
1333         obj->parent = directory;
1334
1335         if (directory == obj->my_dev->unlinked_dir
1336             || directory == obj->my_dev->del_dir) {
1337                 obj->unlinked = 1;
1338                 obj->my_dev->n_unlinked_files++;
1339                 obj->rename_allowed = 0;
1340         }
1341
1342         yaffs_verify_dir(directory);
1343         yaffs_verify_obj_in_dir(obj);
1344 }
1345
1346 static int yaffs_change_obj_name(struct yaffs_obj *obj,
1347                                  struct yaffs_obj *new_dir,
1348                                  const YCHAR * new_name, int force, int shadows)
1349 {
1350         int unlink_op;
1351         int del_op;
1352
1353         struct yaffs_obj *existing_target;
1354
1355         if (new_dir == NULL)
1356                 new_dir = obj->parent;  /* use the old directory */
1357
1358         if (new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
1359                 T(YAFFS_TRACE_ALWAYS,
1360                   (TSTR
1361                    ("tragedy: yaffs_change_obj_name: new_dir is not a directory"
1362                     TENDSTR)));
1363                 YBUG();
1364         }
1365
1366         /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
1367         if (obj->my_dev->param.is_yaffs2)
1368                 unlink_op = (new_dir == obj->my_dev->unlinked_dir);
1369         else
1370                 unlink_op = (new_dir == obj->my_dev->unlinked_dir
1371                              && obj->variant_type == YAFFS_OBJECT_TYPE_FILE);
1372
1373         del_op = (new_dir == obj->my_dev->del_dir);
1374
1375         existing_target = yaffs_find_by_name(new_dir, new_name);
1376
1377         /* If the object is a file going into the unlinked directory,
1378          *   then it is OK to just stuff it in since duplicate names are allowed.
1379          *   else only proceed if the new name does not exist and if we're putting
1380          *   it into a directory.
1381          */
1382         if ((unlink_op ||
1383              del_op ||
1384              force ||
1385              (shadows > 0) ||
1386              !existing_target) &&
1387             new_dir->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) {
1388                 yaffs_set_obj_name(obj, new_name);
1389                 obj->dirty = 1;
1390
1391                 yaffs_add_obj_to_dir(new_dir, obj);
1392
1393                 if (unlink_op)
1394                         obj->unlinked = 1;
1395
1396                 /* If it is a deletion then we mark it as a shrink for gc purposes. */
1397                 if (yaffs_update_oh(obj, new_name, 0, del_op, shadows, NULL) >=
1398                     0)
1399                         return YAFFS_OK;
1400         }
1401
1402         return YAFFS_FAIL;
1403 }
1404
1405 /*------------------------ Short Operations Cache ----------------------------------------
1406  *   In many situations where there is no high level buffering  a lot of
1407  *   reads might be short sequential reads, and a lot of writes may be short
1408  *   sequential writes. eg. scanning/writing a jpeg file.
1409  *   In these cases, a short read/write cache can provide a huge perfomance
1410  *   benefit with dumb-as-a-rock code.
1411  *   In Linux, the page cache provides read buffering and the short op cache 
1412  *   provides write buffering.
1413  *
1414  *   There are a limited number (~10) of cache chunks per device so that we don't
1415  *   need a very intelligent search.
1416  */
1417
1418 static int yaffs_obj_cache_dirty(struct yaffs_obj *obj)
1419 {
1420         struct yaffs_dev *dev = obj->my_dev;
1421         int i;
1422         struct yaffs_cache *cache;
1423         int n_caches = obj->my_dev->param.n_caches;
1424
1425         for (i = 0; i < n_caches; i++) {
1426                 cache = &dev->cache[i];
1427                 if (cache->object == obj && cache->dirty)
1428                         return 1;
1429         }
1430
1431         return 0;
1432 }
1433
1434 static void yaffs_flush_file_cache(struct yaffs_obj *obj)
1435 {
1436         struct yaffs_dev *dev = obj->my_dev;
1437         int lowest = -99;       /* Stop compiler whining. */
1438         int i;
1439         struct yaffs_cache *cache;
1440         int chunk_written = 0;
1441         int n_caches = obj->my_dev->param.n_caches;
1442
1443         if (n_caches > 0) {
1444                 do {
1445                         cache = NULL;
1446
1447                         /* Find the dirty cache for this object with the lowest chunk id. */
1448                         for (i = 0; i < n_caches; i++) {
1449                                 if (dev->cache[i].object == obj &&
1450                                     dev->cache[i].dirty) {
1451                                         if (!cache
1452                                             || dev->cache[i].chunk_id <
1453                                             lowest) {
1454                                                 cache = &dev->cache[i];
1455                                                 lowest = cache->chunk_id;
1456                                         }
1457                                 }
1458                         }
1459
1460                         if (cache && !cache->locked) {
1461                                 /* Write it out and free it up */
1462
1463                                 chunk_written =
1464                                     yaffs_wr_data_obj(cache->object,
1465                                                       cache->chunk_id,
1466                                                       cache->data,
1467                                                       cache->n_bytes, 1);
1468                                 cache->dirty = 0;
1469                                 cache->object = NULL;
1470                         }
1471
1472                 } while (cache && chunk_written > 0);
1473
1474                 if (cache) {
1475                         /* Hoosterman, disk full while writing cache out. */
1476                         T(YAFFS_TRACE_ERROR,
1477                           (TSTR
1478                            ("yaffs tragedy: no space during cache write"
1479                             TENDSTR)));
1480
1481                 }
1482         }
1483
1484 }
1485
1486 /*yaffs_flush_whole_cache(dev)
1487  *
1488  *
1489  */
1490
1491 void yaffs_flush_whole_cache(struct yaffs_dev *dev)
1492 {
1493         struct yaffs_obj *obj;
1494         int n_caches = dev->param.n_caches;
1495         int i;
1496
1497         /* Find a dirty object in the cache and flush it...
1498          * until there are no further dirty objects.
1499          */
1500         do {
1501                 obj = NULL;
1502                 for (i = 0; i < n_caches && !obj; i++) {
1503                         if (dev->cache[i].object && dev->cache[i].dirty)
1504                                 obj = dev->cache[i].object;
1505
1506                 }
1507                 if (obj)
1508                         yaffs_flush_file_cache(obj);
1509
1510         } while (obj);
1511
1512 }
1513
1514 /* Grab us a cache chunk for use.
1515  * First look for an empty one.
1516  * Then look for the least recently used non-dirty one.
1517  * Then look for the least recently used dirty one...., flush and look again.
1518  */
1519 static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
1520 {
1521         int i;
1522
1523         if (dev->param.n_caches > 0) {
1524                 for (i = 0; i < dev->param.n_caches; i++) {
1525                         if (!dev->cache[i].object)
1526                                 return &dev->cache[i];
1527                 }
1528         }
1529
1530         return NULL;
1531 }
1532
1533 static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
1534 {
1535         struct yaffs_cache *cache;
1536         struct yaffs_obj *the_obj;
1537         int usage;
1538         int i;
1539         int pushout;
1540
1541         if (dev->param.n_caches > 0) {
1542                 /* Try find a non-dirty one... */
1543
1544                 cache = yaffs_grab_chunk_worker(dev);
1545
1546                 if (!cache) {
1547                         /* They were all dirty, find the last recently used object and flush
1548                          * its cache, then  find again.
1549                          * NB what's here is not very accurate, we actually flush the object
1550                          * the last recently used page.
1551                          */
1552
1553                         /* With locking we can't assume we can use entry zero */
1554
1555                         the_obj = NULL;
1556                         usage = -1;
1557                         cache = NULL;
1558                         pushout = -1;
1559
1560                         for (i = 0; i < dev->param.n_caches; i++) {
1561                                 if (dev->cache[i].object &&
1562                                     !dev->cache[i].locked &&
1563                                     (dev->cache[i].last_use < usage
1564                                      || !cache)) {
1565                                         usage = dev->cache[i].last_use;
1566                                         the_obj = dev->cache[i].object;
1567                                         cache = &dev->cache[i];
1568                                         pushout = i;
1569                                 }
1570                         }
1571
1572                         if (!cache || cache->dirty) {
1573                                 /* Flush and try again */
1574                                 yaffs_flush_file_cache(the_obj);
1575                                 cache = yaffs_grab_chunk_worker(dev);
1576                         }
1577
1578                 }
1579                 return cache;
1580         } else {
1581                 return NULL;
1582         }
1583 }
1584
1585 /* Find a cached chunk */
1586 static struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj,
1587                                                   int chunk_id)
1588 {
1589         struct yaffs_dev *dev = obj->my_dev;
1590         int i;
1591         if (dev->param.n_caches > 0) {
1592                 for (i = 0; i < dev->param.n_caches; i++) {
1593                         if (dev->cache[i].object == obj &&
1594                             dev->cache[i].chunk_id == chunk_id) {
1595                                 dev->cache_hits++;
1596
1597                                 return &dev->cache[i];
1598                         }
1599                 }
1600         }
1601         return NULL;
1602 }
1603
1604 /* Mark the chunk for the least recently used algorithym */
1605 static void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache,
1606                             int is_write)
1607 {
1608
1609         if (dev->param.n_caches > 0) {
1610                 if (dev->cache_last_use < 0 || dev->cache_last_use > 100000000) {
1611                         /* Reset the cache usages */
1612                         int i;
1613                         for (i = 1; i < dev->param.n_caches; i++)
1614                                 dev->cache[i].last_use = 0;
1615
1616                         dev->cache_last_use = 0;
1617                 }
1618
1619                 dev->cache_last_use++;
1620
1621                 cache->last_use = dev->cache_last_use;
1622
1623                 if (is_write)
1624                         cache->dirty = 1;
1625         }
1626 }
1627
1628 /* Invalidate a single cache page.
1629  * Do this when a whole page gets written,
1630  * ie the short cache for this page is no longer valid.
1631  */
1632 static void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id)
1633 {
1634         if (object->my_dev->param.n_caches > 0) {
1635                 struct yaffs_cache *cache =
1636                     yaffs_find_chunk_cache(object, chunk_id);
1637
1638                 if (cache)
1639                         cache->object = NULL;
1640         }
1641 }
1642
1643 /* Invalidate all the cache pages associated with this object
1644  * Do this whenever ther file is deleted or resized.
1645  */
1646 static void yaffs_invalidate_whole_cache(struct yaffs_obj *in)
1647 {
1648         int i;
1649         struct yaffs_dev *dev = in->my_dev;
1650
1651         if (dev->param.n_caches > 0) {
1652                 /* Invalidate it. */
1653                 for (i = 0; i < dev->param.n_caches; i++) {
1654                         if (dev->cache[i].object == in)
1655                                 dev->cache[i].object = NULL;
1656                 }
1657         }
1658 }
1659
1660 static void yaffs_unhash_obj(struct yaffs_obj *obj)
1661 {
1662         int bucket;
1663         struct yaffs_dev *dev = obj->my_dev;
1664
1665         /* If it is still linked into the bucket list, free from the list */
1666         if (!list_empty(&obj->hash_link)) {
1667                 list_del_init(&obj->hash_link);
1668                 bucket = yaffs_hash_fn(obj->obj_id);
1669                 dev->obj_bucket[bucket].count--;
1670         }
1671 }
1672
1673 /*  FreeObject frees up a Object and puts it back on the free list */
1674 static void yaffs_free_obj(struct yaffs_obj *obj)
1675 {
1676         struct yaffs_dev *dev = obj->my_dev;
1677
1678         T(YAFFS_TRACE_OS,
1679           (TSTR("FreeObject %p inode %p" TENDSTR), obj, obj->my_inode));
1680
1681         if (!obj)
1682                 YBUG();
1683         if (obj->parent)
1684                 YBUG();
1685         if (!list_empty(&obj->siblings))
1686                 YBUG();
1687
1688         if (obj->my_inode) {
1689                 /* We're still hooked up to a cached inode.
1690                  * Don't delete now, but mark for later deletion
1691                  */
1692                 obj->defered_free = 1;
1693                 return;
1694         }
1695
1696         yaffs_unhash_obj(obj);
1697
1698         yaffs_free_raw_obj(dev, obj);
1699         dev->n_obj--;
1700         dev->checkpoint_blocks_required = 0;    /* force recalculation */
1701 }
1702
1703 void yaffs_handle_defered_free(struct yaffs_obj *obj)
1704 {
1705         if (obj->defered_free)
1706                 yaffs_free_obj(obj);
1707 }
1708
1709 static int yaffs_generic_obj_del(struct yaffs_obj *in)
1710 {
1711
1712         /* First off, invalidate the file's data in the cache, without flushing. */
1713         yaffs_invalidate_whole_cache(in);
1714
1715         if (in->my_dev->param.is_yaffs2 && (in->parent != in->my_dev->del_dir)) {
1716                 /* Move to the unlinked directory so we have a record that it was deleted. */
1717                 yaffs_change_obj_name(in, in->my_dev->del_dir, _Y("deleted"), 0,
1718                                       0);
1719
1720         }
1721
1722         yaffs_remove_obj_from_dir(in);
1723         yaffs_chunk_del(in->my_dev, in->hdr_chunk, 1, __LINE__);
1724         in->hdr_chunk = 0;
1725
1726         yaffs_free_obj(in);
1727         return YAFFS_OK;
1728
1729 }
1730
1731 static void yaffs_soft_del_file(struct yaffs_obj *obj)
1732 {
1733         if (obj->deleted &&
1734             obj->variant_type == YAFFS_OBJECT_TYPE_FILE && !obj->soft_del) {
1735                 if (obj->n_data_chunks <= 0) {
1736                         /* Empty file with no duplicate object headers, just delete it immediately */
1737                         yaffs_free_tnode(obj->my_dev,
1738                                          obj->variant.file_variant.top);
1739                         obj->variant.file_variant.top = NULL;
1740                         T(YAFFS_TRACE_TRACING,
1741                           (TSTR("yaffs: Deleting empty file %d" TENDSTR),
1742                            obj->obj_id));
1743                         yaffs_generic_obj_del(obj);
1744                 } else {
1745                         yaffs_soft_del_worker(obj,
1746                                               obj->variant.file_variant.top,
1747                                               obj->variant.
1748                                               file_variant.top_level, 0);
1749                         obj->soft_del = 1;
1750                 }
1751         }
1752 }
1753
1754 /* Pruning removes any part of the file structure tree that is beyond the
1755  * bounds of the file (ie that does not point to chunks).
1756  *
1757  * A file should only get pruned when its size is reduced.
1758  *
1759  * Before pruning, the chunks must be pulled from the tree and the
1760  * level 0 tnode entries must be zeroed out.
1761  * Could also use this for file deletion, but that's probably better handled
1762  * by a special case.
1763  *
1764  * This function is recursive. For levels > 0 the function is called again on
1765  * any sub-tree. For level == 0 we just check if the sub-tree has data.
1766  * If there is no data in a subtree then it is pruned.
1767  */
1768
1769 static struct yaffs_tnode *yaffs_prune_worker(struct yaffs_dev *dev,
1770                                               struct yaffs_tnode *tn, u32 level,
1771                                               int del0)
1772 {
1773         int i;
1774         int has_data;
1775
1776         if (tn) {
1777                 has_data = 0;
1778
1779                 if (level > 0) {
1780                         for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) {
1781                                 if (tn->internal[i]) {
1782                                         tn->internal[i] =
1783                                             yaffs_prune_worker(dev,
1784                                                                tn->internal[i],
1785                                                                level - 1,
1786                                                                (i ==
1787                                                                 0) ? del0 : 1);
1788                                 }
1789
1790                                 if (tn->internal[i])
1791                                         has_data++;
1792                         }
1793                 } else {
1794                         int tnode_size_u32 = dev->tnode_size / sizeof(u32);
1795                         u32 *map = (u32 *) tn;
1796
1797                         for (i = 0; !has_data && i < tnode_size_u32; i++) {
1798                                 if (map[i])
1799                                         has_data++;
1800                         }
1801                 }
1802
1803                 if (has_data == 0 && del0) {
1804                         /* Free and return NULL */
1805
1806                         yaffs_free_tnode(dev, tn);
1807                         tn = NULL;
1808                 }
1809
1810         }
1811
1812         return tn;
1813
1814 }
1815
1816 static int yaffs_prune_tree(struct yaffs_dev *dev,
1817                             struct yaffs_file_var *file_struct)
1818 {
1819         int i;
1820         int has_data;
1821         int done = 0;
1822         struct yaffs_tnode *tn;
1823
1824         if (file_struct->top_level > 0) {
1825                 file_struct->top =
1826                     yaffs_prune_worker(dev, file_struct->top,
1827                                        file_struct->top_level, 0);
1828
1829                 /* Now we have a tree with all the non-zero branches NULL but the height
1830                  * is the same as it was.
1831                  * Let's see if we can trim internal tnodes to shorten the tree.
1832                  * We can do this if only the 0th element in the tnode is in use
1833                  * (ie all the non-zero are NULL)
1834                  */
1835
1836                 while (file_struct->top_level && !done) {
1837                         tn = file_struct->top;
1838
1839                         has_data = 0;
1840                         for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) {
1841                                 if (tn->internal[i])
1842                                         has_data++;
1843                         }
1844
1845                         if (!has_data) {
1846                                 file_struct->top = tn->internal[0];
1847                                 file_struct->top_level--;
1848                                 yaffs_free_tnode(dev, tn);
1849                         } else {
1850                                 done = 1;
1851                         }
1852                 }
1853         }
1854
1855         return YAFFS_OK;
1856 }
1857
1858 /*-------------------- End of File Structure functions.-------------------*/
1859
1860 /* AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */
1861 static struct yaffs_obj *yaffs_alloc_empty_obj(struct yaffs_dev *dev)
1862 {
1863         struct yaffs_obj *obj = yaffs_alloc_raw_obj(dev);
1864
1865         if (obj) {
1866                 dev->n_obj++;
1867
1868                 /* Now sweeten it up... */
1869
1870                 memset(obj, 0, sizeof(struct yaffs_obj));
1871                 obj->being_created = 1;
1872
1873                 obj->my_dev = dev;
1874                 obj->hdr_chunk = 0;
1875                 obj->variant_type = YAFFS_OBJECT_TYPE_UNKNOWN;
1876                 INIT_LIST_HEAD(&(obj->hard_links));
1877                 INIT_LIST_HEAD(&(obj->hash_link));
1878                 INIT_LIST_HEAD(&obj->siblings);
1879
1880                 /* Now make the directory sane */
1881                 if (dev->root_dir) {
1882                         obj->parent = dev->root_dir;
1883                         list_add(&(obj->siblings),
1884                                  &dev->root_dir->variant.dir_variant.children);
1885                 }
1886
1887                 /* Add it to the lost and found directory.
1888                  * NB Can't put root or lost-n-found in lost-n-found so
1889                  * check if lost-n-found exists first
1890                  */
1891                 if (dev->lost_n_found)
1892                         yaffs_add_obj_to_dir(dev->lost_n_found, obj);
1893
1894                 obj->being_created = 0;
1895         }
1896
1897         dev->checkpoint_blocks_required = 0;    /* force recalculation */
1898
1899         return obj;
1900 }
1901
1902 static int yaffs_find_nice_bucket(struct yaffs_dev *dev)
1903 {
1904         int i;
1905         int l = 999;
1906         int lowest = 999999;
1907
1908         /* Search for the shortest list or one that
1909          * isn't too long.
1910          */
1911
1912         for (i = 0; i < 10 && lowest > 4; i++) {
1913                 dev->bucket_finder++;
1914                 dev->bucket_finder %= YAFFS_NOBJECT_BUCKETS;
1915                 if (dev->obj_bucket[dev->bucket_finder].count < lowest) {
1916                         lowest = dev->obj_bucket[dev->bucket_finder].count;
1917                         l = dev->bucket_finder;
1918                 }
1919
1920         }
1921
1922         return l;
1923 }
1924
1925 static int yaffs_new_obj_id(struct yaffs_dev *dev)
1926 {
1927         int bucket = yaffs_find_nice_bucket(dev);
1928
1929         /* Now find an object value that has not already been taken
1930          * by scanning the list.
1931          */
1932
1933         int found = 0;
1934         struct list_head *i;
1935
1936         u32 n = (u32) bucket;
1937
1938         /* yaffs_check_obj_hash_sane();  */
1939
1940         while (!found) {
1941                 found = 1;
1942                 n += YAFFS_NOBJECT_BUCKETS;
1943                 if (1 || dev->obj_bucket[bucket].count > 0) {
1944                         list_for_each(i, &dev->obj_bucket[bucket].list) {
1945                                 /* If there is already one in the list */
1946                                 if (i && list_entry(i, struct yaffs_obj,
1947                                                     hash_link)->obj_id == n) {
1948                                         found = 0;
1949                                 }
1950                         }
1951                 }
1952         }
1953
1954         return n;
1955 }
1956
1957 static void yaffs_hash_obj(struct yaffs_obj *in)
1958 {
1959         int bucket = yaffs_hash_fn(in->obj_id);
1960         struct yaffs_dev *dev = in->my_dev;
1961
1962         list_add(&in->hash_link, &dev->obj_bucket[bucket].list);
1963         dev->obj_bucket[bucket].count++;
1964 }
1965
1966 struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number)
1967 {
1968         int bucket = yaffs_hash_fn(number);
1969         struct list_head *i;
1970         struct yaffs_obj *in;
1971
1972         list_for_each(i, &dev->obj_bucket[bucket].list) {
1973                 /* Look if it is in the list */
1974                 if (i) {
1975                         in = list_entry(i, struct yaffs_obj, hash_link);
1976                         if (in->obj_id == number) {
1977
1978                                 /* Don't tell the VFS about this one if it is defered free */
1979                                 if (in->defered_free)
1980                                         return NULL;
1981
1982                                 return in;
1983                         }
1984                 }
1985         }
1986
1987         return NULL;
1988 }
1989
1990 struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int number,
1991                                 enum yaffs_obj_type type)
1992 {
1993         struct yaffs_obj *the_obj = NULL;
1994         struct yaffs_tnode *tn = NULL;
1995
1996         if (number < 0)
1997                 number = yaffs_new_obj_id(dev);
1998
1999         if (type == YAFFS_OBJECT_TYPE_FILE) {
2000                 tn = yaffs_get_tnode(dev);
2001                 if (!tn)
2002                         return NULL;
2003         }
2004
2005         the_obj = yaffs_alloc_empty_obj(dev);
2006         if (!the_obj) {
2007                 if (tn)
2008                         yaffs_free_tnode(dev, tn);
2009                 return NULL;
2010         }
2011
2012         if (the_obj) {
2013                 the_obj->fake = 0;
2014                 the_obj->rename_allowed = 1;
2015                 the_obj->unlink_allowed = 1;
2016                 the_obj->obj_id = number;
2017                 yaffs_hash_obj(the_obj);
2018                 the_obj->variant_type = type;
2019                 yaffs_load_current_time(the_obj, 1, 1);
2020
2021                 switch (type) {
2022                 case YAFFS_OBJECT_TYPE_FILE:
2023                         the_obj->variant.file_variant.file_size = 0;
2024                         the_obj->variant.file_variant.scanned_size = 0;
2025                         the_obj->variant.file_variant.shrink_size = ~0; /* max */
2026                         the_obj->variant.file_variant.top_level = 0;
2027                         the_obj->variant.file_variant.top = tn;
2028                         break;
2029                 case YAFFS_OBJECT_TYPE_DIRECTORY:
2030                         INIT_LIST_HEAD(&the_obj->variant.dir_variant.children);
2031                         INIT_LIST_HEAD(&the_obj->variant.dir_variant.dirty);
2032                         break;
2033                 case YAFFS_OBJECT_TYPE_SYMLINK:
2034                 case YAFFS_OBJECT_TYPE_HARDLINK:
2035                 case YAFFS_OBJECT_TYPE_SPECIAL:
2036                         /* No action required */
2037                         break;
2038                 case YAFFS_OBJECT_TYPE_UNKNOWN:
2039                         /* todo this should not happen */
2040                         break;
2041                 }
2042         }
2043
2044         return the_obj;
2045 }
2046
2047 static struct yaffs_obj *yaffs_create_fake_dir(struct yaffs_dev *dev,
2048                                                int number, u32 mode)
2049 {
2050
2051         struct yaffs_obj *obj =
2052             yaffs_new_obj(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
2053         if (obj) {
2054                 obj->fake = 1;  /* it is fake so it might have no NAND presence... */
2055                 obj->rename_allowed = 0;        /* ... and we're not allowed to rename it... */
2056                 obj->unlink_allowed = 0;        /* ... or unlink it */
2057                 obj->deleted = 0;
2058                 obj->unlinked = 0;
2059                 obj->yst_mode = mode;
2060                 obj->my_dev = dev;
2061                 obj->hdr_chunk = 0;     /* Not a valid chunk. */
2062         }
2063
2064         return obj;
2065
2066 }
2067
2068
2069 static void yaffs_init_tnodes_and_objs(struct yaffs_dev *dev)
2070 {
2071         int i;
2072
2073         dev->n_obj = 0;
2074         dev->n_tnodes = 0;
2075
2076         yaffs_init_raw_tnodes_and_objs(dev);
2077
2078         for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
2079                 INIT_LIST_HEAD(&dev->obj_bucket[i].list);
2080                 dev->obj_bucket[i].count = 0;
2081         }
2082 }
2083
2084 struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev,
2085                                                  int number,
2086                                                  enum yaffs_obj_type type)
2087 {
2088         struct yaffs_obj *the_obj = NULL;
2089
2090         if (number > 0)
2091                 the_obj = yaffs_find_by_number(dev, number);
2092
2093         if (!the_obj)
2094                 the_obj = yaffs_new_obj(dev, number, type);
2095
2096         return the_obj;
2097
2098 }
2099
2100 YCHAR *yaffs_clone_str(const YCHAR * str)
2101 {
2102         YCHAR *new_str = NULL;
2103         int len;
2104
2105         if (!str)
2106                 str = _Y("");
2107
2108         len = strnlen(str, YAFFS_MAX_ALIAS_LENGTH);
2109         new_str = kmalloc((len + 1) * sizeof(YCHAR), GFP_NOFS);
2110         if (new_str) {
2111                 strncpy(new_str, str, len);
2112                 new_str[len] = 0;
2113         }
2114         return new_str;
2115
2116 }
2117 /*
2118  *yaffs_update_parent() handles fixing a directories mtime and ctime when a new
2119  * link (ie. name) is created or deleted in the directory.
2120  *
2121  * ie.
2122  *   create dir/a : update dir's mtime/ctime
2123  *   rm dir/a:   update dir's mtime/ctime
2124  *   modify dir/a: don't update dir's mtimme/ctime
2125  *
2126  * This can be handled immediately or defered. Defering helps reduce the number
2127  * of updates when many files in a directory are changed within a brief period.
2128  *
2129  * If the directory updating is defered then yaffs_update_dirty_dirs must be
2130  * called periodically.
2131  */
2132
2133 static void yaffs_update_parent(struct yaffs_obj *obj)
2134 {
2135         struct yaffs_dev *dev;
2136         if (!obj)
2137                 return;
2138         dev = obj->my_dev;
2139         obj->dirty = 1;
2140         yaffs_load_current_time(obj, 0, 1);
2141         if (dev->param.defered_dir_update) {
2142                 struct list_head *link = &obj->variant.dir_variant.dirty;
2143
2144                 if (list_empty(link)) {
2145                         list_add(link, &dev->dirty_dirs);
2146                         T(YAFFS_TRACE_BACKGROUND,
2147                           (TSTR("Added object %d to dirty directories" TENDSTR),
2148                            obj->obj_id));
2149                 }
2150
2151         } else {
2152                 yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
2153         }
2154 }
2155
2156 void yaffs_update_dirty_dirs(struct yaffs_dev *dev)
2157 {
2158         struct list_head *link;
2159         struct yaffs_obj *obj;
2160         struct yaffs_dir_var *d_s;
2161         union yaffs_obj_var *o_v;
2162
2163         T(YAFFS_TRACE_BACKGROUND, (TSTR("Update dirty directories" TENDSTR)));
2164
2165         while (!list_empty(&dev->dirty_dirs)) {
2166                 link = dev->dirty_dirs.next;
2167                 list_del_init(link);
2168
2169                 d_s = list_entry(link, struct yaffs_dir_var, dirty);
2170                 o_v = list_entry(d_s, union yaffs_obj_var, dir_variant);
2171                 obj = list_entry(o_v, struct yaffs_obj, variant);
2172
2173                 T(YAFFS_TRACE_BACKGROUND,
2174                   (TSTR("Update directory %d" TENDSTR), obj->obj_id));
2175
2176                 if (obj->dirty)
2177                         yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
2178         }
2179 }
2180
2181 /*
2182  * Mknod (create) a new object.
2183  * equiv_obj only has meaning for a hard link;
2184  * alias_str only has meaning for a symlink.
2185  * rdev only has meaning for devices (a subset of special objects)
2186  */
2187
2188 static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type,
2189                                           struct yaffs_obj *parent,
2190                                           const YCHAR * name,
2191                                           u32 mode,
2192                                           u32 uid,
2193                                           u32 gid,
2194                                           struct yaffs_obj *equiv_obj,
2195                                           const YCHAR * alias_str, u32 rdev)
2196 {
2197         struct yaffs_obj *in;
2198         YCHAR *str = NULL;
2199
2200         struct yaffs_dev *dev = parent->my_dev;
2201
2202         /* Check if the entry exists. If it does then fail the call since we don't want a dup. */
2203         if (yaffs_find_by_name(parent, name))
2204                 return NULL;
2205
2206         if (type == YAFFS_OBJECT_TYPE_SYMLINK) {
2207                 str = yaffs_clone_str(alias_str);
2208                 if (!str)
2209                         return NULL;
2210         }
2211
2212         in = yaffs_new_obj(dev, -1, type);
2213
2214         if (!in) {
2215                 if (str)
2216                         kfree(str);
2217                 return NULL;
2218         }
2219
2220         if (in) {
2221                 in->hdr_chunk = 0;
2222                 in->valid = 1;
2223                 in->variant_type = type;
2224
2225                 in->yst_mode = mode;
2226
2227                 yaffs_attribs_init(in, gid, uid, rdev);
2228
2229                 in->n_data_chunks = 0;
2230
2231                 yaffs_set_obj_name(in, name);
2232                 in->dirty = 1;
2233
2234                 yaffs_add_obj_to_dir(parent, in);
2235
2236                 in->my_dev = parent->my_dev;
2237
2238                 switch (type) {
2239                 case YAFFS_OBJECT_TYPE_SYMLINK:
2240                         in->variant.symlink_variant.alias = str;
2241                         break;
2242                 case YAFFS_OBJECT_TYPE_HARDLINK:
2243                         in->variant.hardlink_variant.equiv_obj = equiv_obj;
2244                         in->variant.hardlink_variant.equiv_id =
2245                             equiv_obj->obj_id;
2246                         list_add(&in->hard_links, &equiv_obj->hard_links);
2247                         break;
2248                 case YAFFS_OBJECT_TYPE_FILE:
2249                 case YAFFS_OBJECT_TYPE_DIRECTORY:
2250                 case YAFFS_OBJECT_TYPE_SPECIAL:
2251                 case YAFFS_OBJECT_TYPE_UNKNOWN:
2252                         /* do nothing */
2253                         break;
2254                 }
2255
2256                 if (yaffs_update_oh(in, name, 0, 0, 0, NULL) < 0) {
2257                         /* Could not create the object header, fail the creation */
2258                         yaffs_del_obj(in);
2259                         in = NULL;
2260                 }
2261
2262                 yaffs_update_parent(parent);
2263         }
2264
2265         return in;
2266 }
2267
2268 struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
2269                                     const YCHAR * name, u32 mode, u32 uid,
2270                                     u32 gid)
2271 {
2272         return yaffs_create_obj(YAFFS_OBJECT_TYPE_FILE, parent, name, mode,
2273                                 uid, gid, NULL, NULL, 0);
2274 }
2275
2276 struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR * name,
2277                                    u32 mode, u32 uid, u32 gid)
2278 {
2279         return yaffs_create_obj(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name,
2280                                 mode, uid, gid, NULL, NULL, 0);
2281 }
2282
2283 struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent,
2284                                        const YCHAR * name, u32 mode, u32 uid,
2285                                        u32 gid, u32 rdev)
2286 {
2287         return yaffs_create_obj(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode,
2288                                 uid, gid, NULL, NULL, rdev);
2289 }
2290
2291 struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent,
2292                                        const YCHAR * name, u32 mode, u32 uid,
2293                                        u32 gid, const YCHAR * alias)
2294 {
2295         return yaffs_create_obj(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode,
2296                                 uid, gid, NULL, alias, 0);
2297 }
2298
2299 /* yaffs_link_obj returns the object id of the equivalent object.*/
2300 struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR * name,
2301                                  struct yaffs_obj *equiv_obj)
2302 {
2303         /* Get the real object in case we were fed a hard link as an equivalent object */
2304         equiv_obj = yaffs_get_equivalent_obj(equiv_obj);
2305
2306         if (yaffs_create_obj
2307             (YAFFS_OBJECT_TYPE_HARDLINK, parent, name, 0, 0, 0,
2308              equiv_obj, NULL, 0)) {
2309                 return equiv_obj;
2310         } else {
2311                 return NULL;
2312         }
2313
2314 }
2315
2316
2317
2318 /*------------------------- Block Management and Page Allocation ----------------*/
2319
2320 static int yaffs_init_blocks(struct yaffs_dev *dev)
2321 {
2322         int n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
2323
2324         dev->block_info = NULL;
2325         dev->chunk_bits = NULL;
2326
2327         dev->alloc_block = -1;  /* force it to get a new one */
2328
2329         /* If the first allocation strategy fails, thry the alternate one */
2330         dev->block_info =
2331                 kmalloc(n_blocks * sizeof(struct yaffs_block_info), GFP_NOFS);
2332         if (!dev->block_info) {
2333                 dev->block_info =
2334                     vmalloc(n_blocks * sizeof(struct yaffs_block_info));
2335                 dev->block_info_alt = 1;
2336         } else {
2337                 dev->block_info_alt = 0;
2338         }
2339
2340         if (dev->block_info) {
2341                 /* Set up dynamic blockinfo stuff. Round up bytes. */
2342                 dev->chunk_bit_stride = (dev->param.chunks_per_block + 7) / 8;
2343                 dev->chunk_bits =
2344                         kmalloc(dev->chunk_bit_stride * n_blocks, GFP_NOFS);
2345                 if (!dev->chunk_bits) {
2346                         dev->chunk_bits =
2347                             vmalloc(dev->chunk_bit_stride * n_blocks);
2348                         dev->chunk_bits_alt = 1;
2349                 } else {
2350                         dev->chunk_bits_alt = 0;
2351                 }
2352         }
2353
2354         if (dev->block_info && dev->chunk_bits) {
2355                 memset(dev->block_info, 0,
2356                        n_blocks * sizeof(struct yaffs_block_info));
2357                 memset(dev->chunk_bits, 0, dev->chunk_bit_stride * n_blocks);
2358                 return YAFFS_OK;
2359         }
2360
2361         return YAFFS_FAIL;
2362 }
2363
2364 static void yaffs_deinit_blocks(struct yaffs_dev *dev)
2365 {
2366         if (dev->block_info_alt && dev->block_info)
2367                 vfree(dev->block_info);
2368         else if (dev->block_info)
2369                 kfree(dev->block_info);
2370
2371         dev->block_info_alt = 0;
2372
2373         dev->block_info = NULL;
2374
2375         if (dev->chunk_bits_alt && dev->chunk_bits)
2376                 vfree(dev->chunk_bits);
2377         else if (dev->chunk_bits)
2378                 kfree(dev->chunk_bits);
2379         dev->chunk_bits_alt = 0;
2380         dev->chunk_bits = NULL;
2381 }
2382
2383 void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no)
2384 {
2385         struct yaffs_block_info *bi = yaffs_get_block_info(dev, block_no);
2386
2387         int erased_ok = 0;
2388
2389         /* If the block is still healthy erase it and mark as clean.
2390          * If the block has had a data failure, then retire it.
2391          */
2392
2393         T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
2394           (TSTR("yaffs_block_became_dirty block %d state %d %s" TENDSTR),
2395            block_no, bi->block_state,
2396            (bi->needs_retiring) ? "needs retiring" : ""));
2397
2398         yaffs2_clear_oldest_dirty_seq(dev, bi);
2399
2400         bi->block_state = YAFFS_BLOCK_STATE_DIRTY;
2401
2402         /* If this is the block being garbage collected then stop gc'ing this block */
2403         if (block_no == dev->gc_block)
2404                 dev->gc_block = 0;
2405
2406         /* If this block is currently the best candidate for gc then drop as a candidate */
2407         if (block_no == dev->gc_dirtiest) {
2408                 dev->gc_dirtiest = 0;
2409                 dev->gc_pages_in_use = 0;
2410         }
2411
2412         if (!bi->needs_retiring) {
2413                 yaffs2_checkpt_invalidate(dev);
2414                 erased_ok = yaffs_erase_block(dev, block_no);
2415                 if (!erased_ok) {
2416                         dev->n_erase_failures++;
2417                         T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
2418                           (TSTR("**>> Erasure failed %d" TENDSTR), block_no));
2419                 }
2420         }
2421
2422         if (erased_ok &&
2423             ((yaffs_trace_mask & YAFFS_TRACE_ERASE)
2424              || !yaffs_skip_verification(dev))) {
2425                 int i;
2426                 for (i = 0; i < dev->param.chunks_per_block; i++) {
2427                         if (!yaffs_check_chunk_erased
2428                             (dev, block_no * dev->param.chunks_per_block + i)) {
2429                                 T(YAFFS_TRACE_ERROR,
2430                                   (TSTR
2431                                    (">>Block %d erasure supposedly OK, but chunk %d not erased"
2432                                     TENDSTR), block_no, i));
2433                         }
2434                 }
2435         }
2436
2437         if (erased_ok) {
2438                 /* Clean it up... */
2439                 bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
2440                 bi->seq_number = 0;
2441                 dev->n_erased_blocks++;
2442                 bi->pages_in_use = 0;
2443                 bi->soft_del_pages = 0;
2444                 bi->has_shrink_hdr = 0;
2445                 bi->skip_erased_check = 1;      /* This is clean, so no need to check */
2446                 bi->gc_prioritise = 0;
2447                 yaffs_clear_chunk_bits(dev, block_no);
2448
2449                 T(YAFFS_TRACE_ERASE,
2450                   (TSTR("Erased block %d" TENDSTR), block_no));
2451         } else {
2452                 dev->n_free_chunks -= dev->param.chunks_per_block;      /* We lost a block of free space */
2453
2454                 yaffs_retire_block(dev, block_no);
2455                 T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
2456                   (TSTR("**>> Block %d retired" TENDSTR), block_no));
2457         }
2458 }
2459
2460
2461
2462 static int yaffs_gc_block(struct yaffs_dev *dev, int block, int whole_block)
2463 {
2464         int old_chunk;
2465         int new_chunk;
2466         int mark_flash;
2467         int ret_val = YAFFS_OK;
2468         int i;
2469         int is_checkpt_block;
2470         int matching_chunk;
2471         int max_copies;
2472
2473         int chunks_before = yaffs_get_erased_chunks(dev);
2474         int chunks_after;
2475
2476         struct yaffs_ext_tags tags;
2477
2478         struct yaffs_block_info *bi = yaffs_get_block_info(dev, block);
2479
2480         struct yaffs_obj *object;
2481
2482         is_checkpt_block = (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT);
2483
2484         T(YAFFS_TRACE_TRACING,
2485           (TSTR
2486            ("Collecting block %d, in use %d, shrink %d, whole_block %d"
2487             TENDSTR), block, bi->pages_in_use, bi->has_shrink_hdr,
2488            whole_block));
2489
2490         /*yaffs_verify_free_chunks(dev); */
2491
2492         if (bi->block_state == YAFFS_BLOCK_STATE_FULL)
2493                 bi->block_state = YAFFS_BLOCK_STATE_COLLECTING;
2494
2495         bi->has_shrink_hdr = 0; /* clear the flag so that the block can erase */
2496
2497         dev->gc_disable = 1;
2498
2499         if (is_checkpt_block || !yaffs_still_some_chunks(dev, block)) {
2500                 T(YAFFS_TRACE_TRACING,
2501                   (TSTR
2502                    ("Collecting block %d that has no chunks in use" TENDSTR),
2503                    block));
2504                 yaffs_block_became_dirty(dev, block);
2505         } else {
2506
2507                 u8 *buffer = yaffs_get_temp_buffer(dev, __LINE__);
2508
2509                 yaffs_verify_blk(dev, bi, block);
2510
2511                 max_copies = (whole_block) ? dev->param.chunks_per_block : 5;
2512                 old_chunk = block * dev->param.chunks_per_block + dev->gc_chunk;
2513
2514                 for ( /* init already done */ ;
2515                      ret_val == YAFFS_OK &&
2516                      dev->gc_chunk < dev->param.chunks_per_block &&
2517                      (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) &&
2518                      max_copies > 0; dev->gc_chunk++, old_chunk++) {
2519                         if (yaffs_check_chunk_bit(dev, block, dev->gc_chunk)) {
2520
2521                                 /* This page is in use and might need to be copied off */
2522
2523                                 max_copies--;
2524
2525                                 mark_flash = 1;
2526
2527                                 yaffs_init_tags(&tags);
2528
2529                                 yaffs_rd_chunk_tags_nand(dev, old_chunk,
2530                                                          buffer, &tags);
2531
2532                                 object = yaffs_find_by_number(dev, tags.obj_id);
2533
2534                                 T(YAFFS_TRACE_GC_DETAIL,
2535                                   (TSTR
2536                                    ("Collecting chunk in block %d, %d %d %d "
2537                                     TENDSTR), dev->gc_chunk, tags.obj_id,
2538                                    tags.chunk_id, tags.n_bytes));
2539
2540                                 if (object && !yaffs_skip_verification(dev)) {
2541                                         if (tags.chunk_id == 0)
2542                                                 matching_chunk =
2543                                                     object->hdr_chunk;
2544                                         else if (object->soft_del)
2545                                                 matching_chunk = old_chunk;     /* Defeat the test */
2546                                         else
2547                                                 matching_chunk =
2548                                                     yaffs_find_chunk_in_file
2549                                                     (object, tags.chunk_id,
2550                                                      NULL);
2551
2552                                         if (old_chunk != matching_chunk)
2553                                                 T(YAFFS_TRACE_ERROR,
2554                                                   (TSTR
2555                                                    ("gc: page in gc mismatch: %d %d %d %d"
2556                                                     TENDSTR), old_chunk,
2557                                                    matching_chunk, tags.obj_id,
2558                                                    tags.chunk_id));
2559
2560                                 }
2561
2562                                 if (!object) {
2563                                         T(YAFFS_TRACE_ERROR,
2564                                           (TSTR
2565                                            ("page %d in gc has no object: %d %d %d "
2566                                             TENDSTR), old_chunk,
2567                                            tags.obj_id, tags.chunk_id,
2568                                            tags.n_bytes));
2569                                 }
2570
2571                                 if (object &&
2572                                     object->deleted &&
2573                                     object->soft_del && tags.chunk_id != 0) {
2574                                         /* Data chunk in a soft deleted file, throw it away
2575                                          * It's a soft deleted data chunk,
2576                                          * No need to copy this, just forget about it and
2577                                          * fix up the object.
2578                                          */
2579
2580                                         /* Free chunks already includes softdeleted chunks.
2581                                          * How ever this chunk is going to soon be really deleted
2582                                          * which will increment free chunks.
2583                                          * We have to decrement free chunks so this works out properly.
2584                                          */
2585                                         dev->n_free_chunks--;
2586                                         bi->soft_del_pages--;
2587
2588                                         object->n_data_chunks--;
2589
2590                                         if (object->n_data_chunks <= 0) {
2591                                                 /* remeber to clean up the object */
2592                                                 dev->gc_cleanup_list[dev->
2593                                                                      n_clean_ups]
2594                                                     = tags.obj_id;
2595                                                 dev->n_clean_ups++;
2596                                         }
2597                                         mark_flash = 0;
2598                                 } else if (0) {
2599                                         /* Todo object && object->deleted && object->n_data_chunks == 0 */
2600                                         /* Deleted object header with no data chunks.
2601                                          * Can be discarded and the file deleted.
2602                                          */
2603                                         object->hdr_chunk = 0;
2604                                         yaffs_free_tnode(object->my_dev,
2605                                                          object->
2606                                                          variant.file_variant.
2607                                                          top);
2608                                         object->variant.file_variant.top = NULL;
2609                                         yaffs_generic_obj_del(object);
2610
2611                                 } else if (object) {
2612                                         /* It's either a data chunk in a live file or
2613                                          * an ObjectHeader, so we're interested in it.
2614                                          * NB Need to keep the ObjectHeaders of deleted files
2615                                          * until the whole file has been deleted off
2616                                          */
2617                                         tags.serial_number++;
2618
2619                                         dev->n_gc_copies++;
2620
2621                                         if (tags.chunk_id == 0) {
2622                                                 /* It is an object Id,
2623                                                  * We need to nuke the shrinkheader flags first
2624                                                  * Also need to clean up shadowing.
2625                                                  * We no longer want the shrink_header flag since its work is done
2626                                                  * and if it is left in place it will mess up scanning.
2627                                                  */
2628
2629                                                 struct yaffs_obj_hdr *oh;
2630                                                 oh = (struct yaffs_obj_hdr *)
2631                                                     buffer;
2632
2633                                                 oh->is_shrink = 0;
2634                                                 tags.extra_is_shrink = 0;
2635
2636                                                 oh->shadows_obj = 0;
2637                                                 oh->inband_shadowed_obj_id = 0;
2638                                                 tags.extra_shadows = 0;
2639
2640                                                 /* Update file size */
2641                                                 if (object->variant_type ==
2642                                                     YAFFS_OBJECT_TYPE_FILE) {
2643                                                         oh->file_size =
2644                                                             object->variant.
2645                                                             file_variant.
2646                                                             file_size;
2647                                                         tags.extra_length =
2648                                                             oh->file_size;
2649                                                 }
2650
2651                                                 yaffs_verify_oh(object, oh,
2652                                                                 &tags, 1);
2653                                                 new_chunk =
2654                                                     yaffs_write_new_chunk(dev,
2655                                                                           (u8 *)
2656                                                                           oh,
2657                                                                           &tags,
2658                                                                           1);
2659                                         } else {
2660                                                 new_chunk =
2661                                                     yaffs_write_new_chunk(dev,
2662                                                                           buffer,
2663                                                                           &tags,
2664                                                                           1);
2665                                         }
2666
2667                                         if (new_chunk < 0) {
2668                                                 ret_val = YAFFS_FAIL;
2669                                         } else {
2670
2671                                                 /* Ok, now fix up the Tnodes etc. */
2672
2673                                                 if (tags.chunk_id == 0) {
2674                                                         /* It's a header */
2675                                                         object->hdr_chunk =
2676                                                             new_chunk;
2677                                                         object->serial =
2678                                                             tags.serial_number;
2679                                                 } else {
2680                                                         /* It's a data chunk */
2681                                                         int ok;
2682                                                         ok = yaffs_put_chunk_in_file(object, tags.chunk_id, new_chunk, 0);
2683                                                 }
2684                                         }
2685                                 }
2686
2687                                 if (ret_val == YAFFS_OK)
2688                                         yaffs_chunk_del(dev, old_chunk,
2689                                                         mark_flash, __LINE__);
2690
2691                         }
2692                 }
2693
2694                 yaffs_release_temp_buffer(dev, buffer, __LINE__);
2695
2696         }
2697
2698         yaffs_verify_collected_blk(dev, bi, block);
2699
2700         if (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) {
2701                 /*
2702                  * The gc did not complete. Set block state back to FULL
2703                  * because checkpointing does not restore gc.
2704                  */
2705                 bi->block_state = YAFFS_BLOCK_STATE_FULL;
2706         } else {
2707                 /* The gc completed. */
2708                 /* Do any required cleanups */
2709                 for (i = 0; i < dev->n_clean_ups; i++) {
2710                         /* Time to delete the file too */
2711                         object =
2712                             yaffs_find_by_number(dev, dev->gc_cleanup_list[i]);
2713                         if (object) {
2714                                 yaffs_free_tnode(dev,
2715                                                  object->variant.
2716                                                  file_variant.top);
2717                                 object->variant.file_variant.top = NULL;
2718                                 T(YAFFS_TRACE_GC,
2719                                   (TSTR
2720                                    ("yaffs: About to finally delete object %d"
2721                                     TENDSTR), object->obj_id));
2722                                 yaffs_generic_obj_del(object);
2723                                 object->my_dev->n_deleted_files--;
2724                         }
2725
2726                 }
2727
2728                 chunks_after = yaffs_get_erased_chunks(dev);
2729                 if (chunks_before >= chunks_after) {
2730                         T(YAFFS_TRACE_GC,
2731                           (TSTR
2732                            ("gc did not increase free chunks before %d after %d"
2733                             TENDSTR), chunks_before, chunks_after));
2734                 }
2735                 dev->gc_block = 0;
2736                 dev->gc_chunk = 0;
2737                 dev->n_clean_ups = 0;
2738         }
2739
2740         dev->gc_disable = 0;
2741
2742         return ret_val;
2743 }
2744
2745 /*
2746  * FindBlockForgarbageCollection is used to select the dirtiest block (or close enough)
2747  * for garbage collection.
2748  */
2749
2750 static unsigned yaffs_find_gc_block(struct yaffs_dev *dev,
2751                                     int aggressive, int background)
2752 {
2753         int i;
2754         int iterations;
2755         unsigned selected = 0;
2756         int prioritised = 0;
2757         int prioritised_exist = 0;
2758         struct yaffs_block_info *bi;
2759         int threshold;
2760
2761         /* First let's see if we need to grab a prioritised block */
2762         if (dev->has_pending_prioritised_gc && !aggressive) {
2763                 dev->gc_dirtiest = 0;
2764                 bi = dev->block_info;
2765                 for (i = dev->internal_start_block;
2766                      i <= dev->internal_end_block && !selected; i++) {
2767
2768                         if (bi->gc_prioritise) {
2769                                 prioritised_exist = 1;
2770                                 if (bi->block_state == YAFFS_BLOCK_STATE_FULL &&
2771                                     yaffs_block_ok_for_gc(dev, bi)) {
2772                                         selected = i;
2773                                         prioritised = 1;
2774                                 }
2775                         }
2776                         bi++;
2777                 }
2778
2779                 /*
2780                  * If there is a prioritised block and none was selected then
2781                  * this happened because there is at least one old dirty block gumming
2782                  * up the works. Let's gc the oldest dirty block.
2783                  */
2784
2785                 if (prioritised_exist &&
2786                     !selected && dev->oldest_dirty_block > 0)
2787                         selected = dev->oldest_dirty_block;
2788
2789                 if (!prioritised_exist) /* None found, so we can clear this */
2790                         dev->has_pending_prioritised_gc = 0;
2791         }
2792
2793         /* If we're doing aggressive GC then we are happy to take a less-dirty block, and
2794          * search harder.
2795          * else (we're doing a leasurely gc), then we only bother to do this if the
2796          * block has only a few pages in use.
2797          */
2798
2799         if (!selected) {
2800                 int pages_used;
2801                 int n_blocks =
2802                     dev->internal_end_block - dev->internal_start_block + 1;
2803                 if (aggressive) {
2804                         threshold = dev->param.chunks_per_block;
2805                         iterations = n_blocks;
2806                 } else {
2807                         int max_threshold;
2808
2809                         if (background)
2810                                 max_threshold = dev->param.chunks_per_block / 2;
2811                         else
2812                                 max_threshold = dev->param.chunks_per_block / 8;
2813
2814                         if (max_threshold < YAFFS_GC_PASSIVE_THRESHOLD)
2815                                 max_threshold = YAFFS_GC_PASSIVE_THRESHOLD;
2816
2817                         threshold = background ? (dev->gc_not_done + 2) * 2 : 0;
2818                         if (threshold < YAFFS_GC_PASSIVE_THRESHOLD)
2819                                 threshold = YAFFS_GC_PASSIVE_THRESHOLD;
2820                         if (threshold > max_threshold)
2821                                 threshold = max_threshold;
2822
2823                         iterations = n_blocks / 16 + 1;
2824                         if (iterations > 100)
2825                                 iterations = 100;
2826                 }
2827
2828                 for (i = 0;
2829                      i < iterations &&
2830                      (dev->gc_dirtiest < 1 ||
2831                       dev->gc_pages_in_use > YAFFS_GC_GOOD_ENOUGH); i++) {
2832                         dev->gc_block_finder++;
2833                         if (dev->gc_block_finder < dev->internal_start_block ||
2834                             dev->gc_block_finder > dev->internal_end_block)
2835                                 dev->gc_block_finder =
2836                                     dev->internal_start_block;
2837
2838                         bi = yaffs_get_block_info(dev, dev->gc_block_finder);
2839
2840                         pages_used = bi->pages_in_use - bi->soft_del_pages;
2841
2842                         if (bi->block_state == YAFFS_BLOCK_STATE_FULL &&
2843                             pages_used < dev->param.chunks_per_block &&
2844                             (dev->gc_dirtiest < 1
2845                              || pages_used < dev->gc_pages_in_use)
2846                             && yaffs_block_ok_for_gc(dev, bi)) {
2847                                 dev->gc_dirtiest = dev->gc_block_finder;
2848                                 dev->gc_pages_in_use = pages_used;
2849                         }
2850                 }
2851
2852                 if (dev->gc_dirtiest > 0 && dev->gc_pages_in_use <= threshold)
2853                         selected = dev->gc_dirtiest;
2854         }
2855
2856         /*
2857          * If nothing has been selected for a while, try selecting the oldest dirty
2858          * because that's gumming up the works.
2859          */
2860
2861         if (!selected && dev->param.is_yaffs2 &&
2862             dev->gc_not_done >= (background ? 10 : 20)) {
2863                 yaffs2_find_oldest_dirty_seq(dev);
2864                 if (dev->oldest_dirty_block > 0) {
2865                         selected = dev->oldest_dirty_block;
2866                         dev->gc_dirtiest = selected;
2867                         dev->oldest_dirty_gc_count++;
2868                         bi = yaffs_get_block_info(dev, selected);
2869                         dev->gc_pages_in_use =
2870                             bi->pages_in_use - bi->soft_del_pages;
2871                 } else {
2872                         dev->gc_not_done = 0;
2873                 }
2874         }
2875
2876         if (selected) {
2877                 T(YAFFS_TRACE_GC,
2878                   (TSTR
2879                    ("GC Selected block %d with %d free, prioritised:%d"
2880                     TENDSTR), selected,
2881                    dev->param.chunks_per_block - dev->gc_pages_in_use,
2882                    prioritised));
2883
2884                 dev->n_gc_blocks++;
2885                 if (background)
2886                         dev->bg_gcs++;
2887
2888                 dev->gc_dirtiest = 0;
2889                 dev->gc_pages_in_use = 0;
2890                 dev->gc_not_done = 0;
2891                 if (dev->refresh_skip > 0)
2892                         dev->refresh_skip--;
2893         } else {
2894                 dev->gc_not_done++;
2895                 T(YAFFS_TRACE_GC,
2896                   (TSTR
2897                    ("GC none: finder %d skip %d threshold %d dirtiest %d using %d oldest %d%s"
2898                     TENDSTR), dev->gc_block_finder, dev->gc_not_done, threshold,
2899                    dev->gc_dirtiest, dev->gc_pages_in_use,
2900                    dev->oldest_dirty_block, background ? " bg" : ""));
2901         }
2902
2903         return selected;
2904 }
2905
2906 /* New garbage collector
2907  * If we're very low on erased blocks then we do aggressive garbage collection
2908  * otherwise we do "leasurely" garbage collection.
2909  * Aggressive gc looks further (whole array) and will accept less dirty blocks.
2910  * Passive gc only inspects smaller areas and will only accept more dirty blocks.
2911  *
2912  * The idea is to help clear out space in a more spread-out manner.
2913  * Dunno if it really does anything useful.
2914  */
2915 static int yaffs_check_gc(struct yaffs_dev *dev, int background)
2916 {
2917         int aggressive = 0;
2918         int gc_ok = YAFFS_OK;
2919         int max_tries = 0;
2920         int min_erased;
2921         int erased_chunks;
2922         int checkpt_block_adjust;
2923
2924         if (dev->param.gc_control && (dev->param.gc_control(dev) & 1) == 0)
2925                 return YAFFS_OK;
2926
2927         if (dev->gc_disable) {
2928                 /* Bail out so we don't get recursive gc */
2929                 return YAFFS_OK;
2930         }
2931
2932         /* This loop should pass the first time.
2933          * We'll only see looping here if the collection does not increase space.
2934          */
2935
2936         do {
2937                 max_tries++;
2938
2939                 checkpt_block_adjust = yaffs_calc_checkpt_blocks_required(dev);
2940
2941                 min_erased =
2942                     dev->param.n_reserved_blocks + checkpt_block_adjust + 1;
2943                 erased_chunks =
2944                     dev->n_erased_blocks * dev->param.chunks_per_block;
2945
2946                 /* If we need a block soon then do aggressive gc. */
2947                 if (dev->n_erased_blocks < min_erased)
2948                         aggressive = 1;
2949                 else {
2950                         if (!background
2951                             && erased_chunks > (dev->n_free_chunks / 4))
2952                                 break;
2953
2954                         if (dev->gc_skip > 20)
2955                                 dev->gc_skip = 20;
2956                         if (erased_chunks < dev->n_free_chunks / 2 ||
2957                             dev->gc_skip < 1 || background)
2958                                 aggressive = 0;
2959                         else {
2960                                 dev->gc_skip--;
2961                                 break;
2962                         }
2963                 }
2964
2965                 dev->gc_skip = 5;
2966
2967                 /* If we don't already have a block being gc'd then see if we should start another */
2968
2969                 if (dev->gc_block < 1 && !aggressive) {
2970                         dev->gc_block = yaffs2_find_refresh_block(dev);
2971                         dev->gc_chunk = 0;
2972                         dev->n_clean_ups = 0;
2973                 }
2974                 if (dev->gc_block < 1) {
2975                         dev->gc_block =
2976                             yaffs_find_gc_block(dev, aggressive, background);
2977                         dev->gc_chunk = 0;
2978                         dev->n_clean_ups = 0;
2979                 }
2980
2981                 if (dev->gc_block > 0) {
2982                         dev->all_gcs++;
2983                         if (!aggressive)
2984                                 dev->passive_gc_count++;
2985
2986                         T(YAFFS_TRACE_GC,
2987                           (TSTR
2988                            ("yaffs: GC n_erased_blocks %d aggressive %d"
2989                             TENDSTR), dev->n_erased_blocks, aggressive));
2990
2991                         gc_ok = yaffs_gc_block(dev, dev->gc_block, aggressive);
2992                 }
2993
2994                 if (dev->n_erased_blocks < (dev->param.n_reserved_blocks)
2995                     && dev->gc_block > 0) {
2996                         T(YAFFS_TRACE_GC,
2997                           (TSTR
2998                            ("yaffs: GC !!!no reclaim!!! n_erased_blocks %d after try %d block %d"
2999                             TENDSTR), dev->n_erased_blocks, max_tries,
3000                            dev->gc_block));
3001                 }
3002         } while ((dev->n_erased_blocks < dev->param.n_reserved_blocks) &&
3003                  (dev->gc_block > 0) && (max_tries < 2));
3004
3005         return aggressive ? gc_ok : YAFFS_OK;
3006 }
3007
3008 /*
3009  * yaffs_bg_gc()
3010  * Garbage collects. Intended to be called from a background thread.
3011  * Returns non-zero if at least half the free chunks are erased.
3012  */
3013 int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency)
3014 {
3015         int erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block;
3016
3017         T(YAFFS_TRACE_BACKGROUND, (TSTR("Background gc %u" TENDSTR), urgency));
3018
3019         yaffs_check_gc(dev, 1);
3020         return erased_chunks > dev->n_free_chunks / 2;
3021 }
3022
3023 /*-------------------- Data file manipulation -----------------*/
3024
3025 static int yaffs_rd_data_obj(struct yaffs_obj *in, int inode_chunk, u8 * buffer)
3026 {
3027         int nand_chunk = yaffs_find_chunk_in_file(in, inode_chunk, NULL);
3028
3029         if (nand_chunk >= 0)
3030                 return yaffs_rd_chunk_tags_nand(in->my_dev, nand_chunk,
3031                                                 buffer, NULL);
3032         else {
3033                 T(YAFFS_TRACE_NANDACCESS,
3034                   (TSTR("Chunk %d not found zero instead" TENDSTR),
3035                    nand_chunk));
3036                 /* get sane (zero) data if you read a hole */
3037                 memset(buffer, 0, in->my_dev->data_bytes_per_chunk);
3038                 return 0;
3039         }
3040
3041 }
3042
3043 void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash,
3044                      int lyn)
3045 {
3046         int block;
3047         int page;
3048         struct yaffs_ext_tags tags;
3049         struct yaffs_block_info *bi;
3050
3051         if (chunk_id <= 0)
3052                 return;
3053
3054         dev->n_deletions++;
3055         block = chunk_id / dev->param.chunks_per_block;
3056         page = chunk_id % dev->param.chunks_per_block;
3057
3058         if (!yaffs_check_chunk_bit(dev, block, page))
3059                 T(YAFFS_TRACE_VERIFY,
3060                   (TSTR("Deleting invalid chunk %d" TENDSTR), chunk_id));
3061
3062         bi = yaffs_get_block_info(dev, block);
3063
3064         yaffs2_update_oldest_dirty_seq(dev, block, bi);
3065
3066         T(YAFFS_TRACE_DELETION,
3067           (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunk_id));
3068
3069         if (!dev->param.is_yaffs2 && mark_flash &&
3070             bi->block_state != YAFFS_BLOCK_STATE_COLLECTING) {
3071
3072                 yaffs_init_tags(&tags);
3073
3074                 tags.is_deleted = 1;
3075
3076                 yaffs_wr_chunk_tags_nand(dev, chunk_id, NULL, &tags);
3077                 yaffs_handle_chunk_update(dev, chunk_id, &tags);
3078         } else {
3079                 dev->n_unmarked_deletions++;
3080         }
3081
3082         /* Pull out of the management area.
3083          * If the whole block became dirty, this will kick off an erasure.
3084          */
3085         if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING ||
3086             bi->block_state == YAFFS_BLOCK_STATE_FULL ||
3087             bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
3088             bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) {
3089                 dev->n_free_chunks++;
3090
3091                 yaffs_clear_chunk_bit(dev, block, page);
3092
3093                 bi->pages_in_use--;
3094
3095                 if (bi->pages_in_use == 0 &&
3096                     !bi->has_shrink_hdr &&
3097                     bi->block_state != YAFFS_BLOCK_STATE_ALLOCATING &&
3098                     bi->block_state != YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
3099                         yaffs_block_became_dirty(dev, block);
3100                 }
3101
3102         }
3103
3104 }
3105
3106 static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
3107                              const u8 * buffer, int n_bytes, int use_reserve)
3108 {
3109         /* Find old chunk Need to do this to get serial number
3110          * Write new one and patch into tree.
3111          * Invalidate old tags.
3112          */
3113
3114         int prev_chunk_id;
3115         struct yaffs_ext_tags prev_tags;
3116
3117         int new_chunk_id;
3118         struct yaffs_ext_tags new_tags;
3119
3120         struct yaffs_dev *dev = in->my_dev;
3121
3122         yaffs_check_gc(dev, 0);
3123
3124         /* Get the previous chunk at this location in the file if it exists.
3125          * If it does not exist then put a zero into the tree. This creates
3126          * the tnode now, rather than later when it is harder to clean up.
3127          */
3128         prev_chunk_id = yaffs_find_chunk_in_file(in, inode_chunk, &prev_tags);
3129         if (prev_chunk_id < 1 &&
3130             !yaffs_put_chunk_in_file(in, inode_chunk, 0, 0))
3131                 return 0;
3132
3133         /* Set up new tags */
3134         yaffs_init_tags(&new_tags);
3135
3136         new_tags.chunk_id = inode_chunk;
3137         new_tags.obj_id = in->obj_id;
3138         new_tags.serial_number =
3139             (prev_chunk_id > 0) ? prev_tags.serial_number + 1 : 1;
3140         new_tags.n_bytes = n_bytes;
3141
3142         if (n_bytes < 1 || n_bytes > dev->param.total_bytes_per_chunk) {
3143                 T(YAFFS_TRACE_ERROR,
3144                   (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR),
3145                    n_bytes));
3146                 YBUG();
3147         }
3148
3149         new_chunk_id =
3150             yaffs_write_new_chunk(dev, buffer, &new_tags, use_reserve);
3151
3152         if (new_chunk_id > 0) {
3153                 yaffs_put_chunk_in_file(in, inode_chunk, new_chunk_id, 0);
3154
3155                 if (prev_chunk_id > 0)
3156                         yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__);
3157
3158                 yaffs_verify_file_sane(in);
3159         }
3160         return new_chunk_id;
3161
3162 }
3163
3164
3165
3166 static int yaffs_do_xattrib_mod(struct yaffs_obj *obj, int set,
3167                                 const YCHAR * name, const void *value, int size,
3168                                 int flags)
3169 {
3170         struct yaffs_xattr_mod xmod;
3171
3172         int result;
3173
3174         xmod.set = set;
3175         xmod.name = name;
3176         xmod.data = value;
3177         xmod.size = size;
3178         xmod.flags = flags;
3179         xmod.result = -ENOSPC;
3180
3181         result = yaffs_update_oh(obj, NULL, 0, 0, 0, &xmod);
3182
3183         if (result > 0)
3184                 return xmod.result;
3185         else
3186                 return -ENOSPC;
3187 }
3188
3189 static int yaffs_apply_xattrib_mod(struct yaffs_obj *obj, char *buffer,
3190                                    struct yaffs_xattr_mod *xmod)
3191 {
3192         int retval = 0;
3193         int x_offs = sizeof(struct yaffs_obj_hdr);
3194         struct yaffs_dev *dev = obj->my_dev;
3195         int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr);
3196
3197         char *x_buffer = buffer + x_offs;
3198
3199         if (xmod->set)
3200                 retval =
3201                     nval_set(x_buffer, x_size, xmod->name, xmod->data,
3202                              xmod->size, xmod->flags);
3203         else
3204                 retval = nval_del(x_buffer, x_size, xmod->name);
3205
3206         obj->has_xattr = nval_hasvalues(x_buffer, x_size);
3207         obj->xattr_known = 1;
3208
3209         xmod->result = retval;
3210
3211         return retval;
3212 }
3213
3214 static int yaffs_do_xattrib_fetch(struct yaffs_obj *obj, const YCHAR * name,
3215                                   void *value, int size)
3216 {
3217         char *buffer = NULL;
3218         int result;
3219         struct yaffs_ext_tags tags;
3220         struct yaffs_dev *dev = obj->my_dev;
3221         int x_offs = sizeof(struct yaffs_obj_hdr);
3222         int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr);
3223
3224         char *x_buffer;
3225
3226         int retval = 0;
3227
3228         if (obj->hdr_chunk < 1)
3229                 return -ENODATA;
3230
3231         /* If we know that the object has no xattribs then don't do all the
3232          * reading and parsing.
3233          */
3234         if (obj->xattr_known && !obj->has_xattr) {
3235                 if (name)
3236                         return -ENODATA;
3237                 else
3238                         return 0;
3239         }
3240
3241         buffer = (char *)yaffs_get_temp_buffer(dev, __LINE__);
3242         if (!buffer)
3243                 return -ENOMEM;
3244
3245         result =
3246             yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, (u8 *) buffer, &tags);
3247
3248         if (result != YAFFS_OK)
3249                 retval = -ENOENT;
3250         else {
3251                 x_buffer = buffer + x_offs;
3252
3253                 if (!obj->xattr_known) {
3254                         obj->has_xattr = nval_hasvalues(x_buffer, x_size);
3255                         obj->xattr_known = 1;
3256                 }
3257
3258                 if (name)
3259                         retval = nval_get(x_buffer, x_size, name, value, size);
3260                 else
3261                         retval = nval_list(x_buffer, x_size, value, size);
3262         }
3263         yaffs_release_temp_buffer(dev, (u8 *) buffer, __LINE__);
3264         return retval;
3265 }
3266
3267 int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR * name,
3268                       const void *value, int size, int flags)
3269 {
3270         return yaffs_do_xattrib_mod(obj, 1, name, value, size, flags);
3271 }
3272
3273 int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR * name)
3274 {
3275         return yaffs_do_xattrib_mod(obj, 0, name, NULL, 0, 0);
3276 }
3277
3278 int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR * name, void *value,
3279                       int size)
3280 {
3281         return yaffs_do_xattrib_fetch(obj, name, value, size);
3282 }
3283
3284 int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size)
3285 {
3286         return yaffs_do_xattrib_fetch(obj, NULL, buffer, size);
3287 }
3288
3289 static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
3290 {
3291         u8 *chunk_data;
3292         struct yaffs_obj_hdr *oh;
3293         struct yaffs_dev *dev;
3294         struct yaffs_ext_tags tags;
3295         int result;
3296         int alloc_failed = 0;
3297
3298         if (!in)
3299                 return;
3300
3301         dev = in->my_dev;
3302
3303         if (in->lazy_loaded && in->hdr_chunk > 0) {
3304                 in->lazy_loaded = 0;
3305                 chunk_data = yaffs_get_temp_buffer(dev, __LINE__);
3306
3307                 result =
3308                     yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, chunk_data,
3309                                              &tags);
3310                 oh = (struct yaffs_obj_hdr *)chunk_data;
3311
3312                 in->yst_mode = oh->yst_mode;
3313                 yaffs_load_attribs(in, oh);
3314                 yaffs_set_obj_name_from_oh(in, oh);
3315
3316                 if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
3317                         in->variant.symlink_variant.alias =
3318                             yaffs_clone_str(oh->alias);
3319                         if (!in->variant.symlink_variant.alias)
3320                                 alloc_failed = 1;       /* Not returned to caller */
3321                 }
3322
3323                 yaffs_release_temp_buffer(dev, chunk_data, __LINE__);
3324         }
3325 }
3326
3327 static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR * name,
3328                                     const YCHAR * oh_name, int buff_size)
3329 {
3330 #ifdef CONFIG_YAFFS_AUTO_UNICODE
3331         if (dev->param.auto_unicode) {
3332                 if (*oh_name) {
3333                         /* It is an ASCII name, so do an ASCII to unicode conversion */
3334                         const char *ascii_oh_name = (const char *)oh_name;
3335                         int n = buff_size - 1;
3336                         while (n > 0 && *ascii_oh_name) {
3337                                 *name = *ascii_oh_name;
3338                                 name++;
3339                                 ascii_oh_name++;
3340                                 n--;
3341                         }
3342                 } else {
3343                         strncpy(name, oh_name + 1, buff_size - 1);
3344                 }
3345         } else {
3346 #else
3347         {
3348 #endif
3349                 strncpy(name, oh_name, buff_size - 1);
3350         }
3351 }
3352
3353 static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR * oh_name,
3354                                     const YCHAR * name)
3355 {
3356 #ifdef CONFIG_YAFFS_AUTO_UNICODE
3357
3358         int is_ascii;
3359         YCHAR *w;
3360
3361         if (dev->param.auto_unicode) {
3362
3363                 is_ascii = 1;
3364                 w = name;
3365
3366                 /* Figure out if the name will fit in ascii character set */
3367                 while (is_ascii && *w) {
3368                         if ((*w) & 0xff00)
3369                                 is_ascii = 0;
3370                         w++;
3371                 }
3372
3373                 if (is_ascii) {
3374                         /* It is an ASCII name, so do a unicode to ascii conversion */
3375                         char *ascii_oh_name = (char *)oh_name;
3376                         int n = YAFFS_MAX_NAME_LENGTH - 1;
3377                         while (n > 0 && *name) {
3378                                 *ascii_oh_name = *name;
3379                                 name++;
3380                                 ascii_oh_name++;
3381                                 n--;
3382                         }
3383                 } else {
3384                         /* It is a unicode name, so save starting at the second YCHAR */
3385                         *oh_name = 0;
3386                         strncpy(oh_name + 1, name,
3387                                       YAFFS_MAX_NAME_LENGTH - 2);
3388                 }
3389         } else {
3390 #else
3391         {
3392 #endif
3393                 strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1);
3394         }
3395
3396 }
3397
3398 /* UpdateObjectHeader updates the header on NAND for an object.
3399  * If name is not NULL, then that new name is used.
3400  */
3401 int yaffs_update_oh(struct yaffs_obj *in, const YCHAR * name, int force,
3402                     int is_shrink, int shadows, struct yaffs_xattr_mod *xmod)
3403 {
3404
3405         struct yaffs_block_info *bi;
3406
3407         struct yaffs_dev *dev = in->my_dev;
3408
3409         int prev_chunk_id;
3410         int ret_val = 0;
3411         int result = 0;
3412
3413         int new_chunk_id;
3414         struct yaffs_ext_tags new_tags;
3415         struct yaffs_ext_tags old_tags;
3416         const YCHAR *alias = NULL;
3417
3418         u8 *buffer = NULL;
3419         YCHAR old_name[YAFFS_MAX_NAME_LENGTH + 1];
3420
3421         struct yaffs_obj_hdr *oh = NULL;
3422
3423         strcpy(old_name, _Y("silly old name"));
3424
3425         if (!in->fake || in == dev->root_dir || /* The root_dir should also be saved */
3426             force || xmod) {
3427
3428                 yaffs_check_gc(dev, 0);
3429                 yaffs_check_obj_details_loaded(in);
3430
3431                 buffer = yaffs_get_temp_buffer(in->my_dev, __LINE__);
3432                 oh = (struct yaffs_obj_hdr *)buffer;
3433
3434                 prev_chunk_id = in->hdr_chunk;
3435
3436                 if (prev_chunk_id > 0) {
3437                         result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id,
3438                                                           buffer, &old_tags);
3439
3440                         yaffs_verify_oh(in, oh, &old_tags, 0);
3441
3442                         memcpy(old_name, oh->name, sizeof(oh->name));
3443                         memset(buffer, 0xFF, sizeof(struct yaffs_obj_hdr));
3444                 } else {
3445                         memset(buffer, 0xFF, dev->data_bytes_per_chunk);
3446                 }
3447
3448                 oh->type = in->variant_type;
3449                 oh->yst_mode = in->yst_mode;
3450                 oh->shadows_obj = oh->inband_shadowed_obj_id = shadows;
3451
3452                 yaffs_load_attribs_oh(oh, in);
3453
3454                 if (in->parent)
3455                         oh->parent_obj_id = in->parent->obj_id;
3456                 else
3457                         oh->parent_obj_id = 0;
3458
3459                 if (name && *name) {
3460                         memset(oh->name, 0, sizeof(oh->name));
3461                         yaffs_load_oh_from_name(dev, oh->name, name);
3462                 } else if (prev_chunk_id > 0) {
3463                         memcpy(oh->name, old_name, sizeof(oh->name));
3464                 } else {
3465                         memset(oh->name, 0, sizeof(oh->name));
3466                 }
3467
3468                 oh->is_shrink = is_shrink;
3469
3470                 switch (in->variant_type) {
3471                 case YAFFS_OBJECT_TYPE_UNKNOWN:
3472                         /* Should not happen */
3473                         break;
3474                 case YAFFS_OBJECT_TYPE_FILE:
3475                         oh->file_size =
3476                             (oh->parent_obj_id == YAFFS_OBJECTID_DELETED
3477                              || oh->parent_obj_id ==
3478                              YAFFS_OBJECTID_UNLINKED) ? 0 : in->
3479                             variant.file_variant.file_size;
3480                         break;
3481                 case YAFFS_OBJECT_TYPE_HARDLINK:
3482                         oh->equiv_id = in->variant.hardlink_variant.equiv_id;
3483                         break;
3484                 case YAFFS_OBJECT_TYPE_SPECIAL:
3485                         /* Do nothing */
3486                         break;
3487                 case YAFFS_OBJECT_TYPE_DIRECTORY:
3488                         /* Do nothing */
3489                         break;
3490                 case YAFFS_OBJECT_TYPE_SYMLINK:
3491                         alias = in->variant.symlink_variant.alias;
3492                         if (!alias)
3493                                 alias = _Y("no alias");
3494                         strncpy(oh->alias, alias, YAFFS_MAX_ALIAS_LENGTH);
3495                         oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
3496                         break;
3497                 }
3498
3499                 /* process any xattrib modifications */
3500                 if (xmod)
3501                         yaffs_apply_xattrib_mod(in, (char *)buffer, xmod);
3502
3503                 /* Tags */
3504                 yaffs_init_tags(&new_tags);
3505                 in->serial++;
3506                 new_tags.chunk_id = 0;
3507                 new_tags.obj_id = in->obj_id;
3508                 new_tags.serial_number = in->serial;
3509
3510                 /* Add extra info for file header */
3511
3512                 new_tags.extra_available = 1;
3513                 new_tags.extra_parent_id = oh->parent_obj_id;
3514                 new_tags.extra_length = oh->file_size;
3515                 new_tags.extra_is_shrink = oh->is_shrink;
3516                 new_tags.extra_equiv_id = oh->equiv_id;
3517                 new_tags.extra_shadows = (oh->shadows_obj > 0) ? 1 : 0;
3518                 new_tags.extra_obj_type = in->variant_type;
3519
3520                 yaffs_verify_oh(in, oh, &new_tags, 1);
3521
3522                 /* Create new chunk in NAND */
3523                 new_chunk_id =
3524                     yaffs_write_new_chunk(dev, buffer, &new_tags,
3525                                           (prev_chunk_id > 0) ? 1 : 0);
3526
3527                 if (new_chunk_id >= 0) {
3528
3529                         in->hdr_chunk = new_chunk_id;
3530
3531                         if (prev_chunk_id > 0) {
3532                                 yaffs_chunk_del(dev, prev_chunk_id, 1,
3533                                                 __LINE__);
3534                         }
3535
3536                         if (!yaffs_obj_cache_dirty(in))
3537                                 in->dirty = 0;
3538
3539                         /* If this was a shrink, then mark the block that the chunk lives on */
3540                         if (is_shrink) {
3541                                 bi = yaffs_get_block_info(in->my_dev,
3542                                                           new_chunk_id /
3543                                                           in->my_dev->param.
3544                                                           chunks_per_block);
3545                                 bi->has_shrink_hdr = 1;
3546                         }
3547
3548                 }
3549
3550                 ret_val = new_chunk_id;
3551
3552         }
3553
3554         if (buffer)
3555                 yaffs_release_temp_buffer(dev, buffer, __LINE__);
3556
3557         return ret_val;
3558 }
3559
3560 /*--------------------- File read/write ------------------------
3561  * Read and write have very similar structures.
3562  * In general the read/write has three parts to it
3563  * An incomplete chunk to start with (if the read/write is not chunk-aligned)
3564  * Some complete chunks
3565  * An incomplete chunk to end off with
3566  *
3567  * Curve-balls: the first chunk might also be the last chunk.
3568  */
3569
3570 int yaffs_file_rd(struct yaffs_obj *in, u8 * buffer, loff_t offset, int n_bytes)
3571 {
3572
3573         int chunk;
3574         u32 start;
3575         int n_copy;
3576         int n = n_bytes;
3577         int n_done = 0;
3578         struct yaffs_cache *cache;
3579
3580         struct yaffs_dev *dev;
3581
3582         dev = in->my_dev;
3583
3584         while (n > 0) {
3585                 /* chunk = offset / dev->data_bytes_per_chunk + 1; */
3586                 /* start = offset % dev->data_bytes_per_chunk; */
3587                 yaffs_addr_to_chunk(dev, offset, &chunk, &start);
3588                 chunk++;
3589
3590                 /* OK now check for the curveball where the start and end are in
3591                  * the same chunk.
3592                  */
3593                 if ((start + n) < dev->data_bytes_per_chunk)
3594                         n_copy = n;
3595                 else
3596                         n_copy = dev->data_bytes_per_chunk - start;
3597
3598                 cache = yaffs_find_chunk_cache(in, chunk);
3599
3600                 /* If the chunk is already in the cache or it is less than a whole chunk
3601                  * or we're using inband tags then use the cache (if there is caching)
3602                  * else bypass the cache.
3603                  */
3604                 if (cache || n_copy != dev->data_bytes_per_chunk
3605                     || dev->param.inband_tags) {
3606                         if (dev->param.n_caches > 0) {
3607
3608                                 /* If we can't find the data in the cache, then load it up. */
3609
3610                                 if (!cache) {
3611                                         cache =
3612                                             yaffs_grab_chunk_cache(in->my_dev);
3613                                         cache->object = in;
3614                                         cache->chunk_id = chunk;
3615                                         cache->dirty = 0;
3616                                         cache->locked = 0;
3617                                         yaffs_rd_data_obj(in, chunk,
3618                                                           cache->data);
3619                                         cache->n_bytes = 0;
3620                                 }
3621
3622                                 yaffs_use_cache(dev, cache, 0);
3623
3624                                 cache->locked = 1;
3625
3626                                 memcpy(buffer, &cache->data[start], n_copy);
3627
3628                                 cache->locked = 0;
3629                         } else {
3630                                 /* Read into the local buffer then copy.. */
3631
3632                                 u8 *local_buffer =
3633                                     yaffs_get_temp_buffer(dev, __LINE__);
3634                                 yaffs_rd_data_obj(in, chunk, local_buffer);
3635
3636                                 memcpy(buffer, &local_buffer[start], n_copy);
3637
3638                                 yaffs_release_temp_buffer(dev, local_buffer,
3639                                                           __LINE__);
3640                         }
3641
3642                 } else {
3643
3644                         /* A full chunk. Read directly into the supplied buffer. */
3645                         yaffs_rd_data_obj(in, chunk, buffer);
3646
3647                 }
3648
3649                 n -= n_copy;
3650                 offset += n_copy;
3651                 buffer += n_copy;
3652                 n_done += n_copy;
3653
3654         }
3655
3656         return n_done;
3657 }
3658
3659 int yaffs_do_file_wr(struct yaffs_obj *in, const u8 * buffer, loff_t offset,
3660                      int n_bytes, int write_trhrough)
3661 {
3662
3663         int chunk;
3664         u32 start;
3665         int n_copy;
3666         int n = n_bytes;
3667         int n_done = 0;
3668         int n_writeback;
3669         int start_write = offset;
3670         int chunk_written = 0;
3671         u32 n_bytes_read;
3672         u32 chunk_start;
3673
3674         struct yaffs_dev *dev;
3675
3676         dev = in->my_dev;
3677
3678         while (n > 0 && chunk_written >= 0) {
3679                 yaffs_addr_to_chunk(dev, offset, &chunk, &start);
3680
3681                 if (chunk * dev->data_bytes_per_chunk + start != offset ||
3682                     start >= dev->data_bytes_per_chunk) {
3683                         T(YAFFS_TRACE_ERROR,
3684                           (TSTR
3685                            ("AddrToChunk of offset %d gives chunk %d start %d"
3686                             TENDSTR), (int)offset, chunk, start));
3687                 }
3688                 chunk++;        /* File pos to chunk in file offset */
3689
3690                 /* OK now check for the curveball where the start and end are in
3691                  * the same chunk.
3692                  */
3693
3694                 if ((start + n) < dev->data_bytes_per_chunk) {
3695                         n_copy = n;
3696
3697                         /* Now folks, to calculate how many bytes to write back....
3698                          * If we're overwriting and not writing to then end of file then
3699                          * we need to write back as much as was there before.
3700                          */
3701
3702                         chunk_start = ((chunk - 1) * dev->data_bytes_per_chunk);
3703
3704                         if (chunk_start > in->variant.file_variant.file_size)
3705                                 n_bytes_read = 0;       /* Past end of file */
3706                         else
3707                                 n_bytes_read =
3708                                     in->variant.file_variant.file_size -
3709                                     chunk_start;
3710
3711                         if (n_bytes_read > dev->data_bytes_per_chunk)
3712                                 n_bytes_read = dev->data_bytes_per_chunk;
3713
3714                         n_writeback =
3715                             (n_bytes_read >
3716                              (start + n)) ? n_bytes_read : (start + n);
3717
3718                         if (n_writeback < 0
3719                             || n_writeback > dev->data_bytes_per_chunk)
3720                                 YBUG();
3721
3722                 } else {
3723                         n_copy = dev->data_bytes_per_chunk - start;
3724                         n_writeback = dev->data_bytes_per_chunk;
3725                 }
3726
3727                 if (n_copy != dev->data_bytes_per_chunk
3728                     || dev->param.inband_tags) {
3729                         /* An incomplete start or end chunk (or maybe both start and end chunk),
3730                          * or we're using inband tags, so we want to use the cache buffers.
3731                          */
3732                         if (dev->param.n_caches > 0) {
3733                                 struct yaffs_cache *cache;
3734                                 /* If we can't find the data in the cache, then load the cache */
3735                                 cache = yaffs_find_chunk_cache(in, chunk);
3736
3737                                 if (!cache
3738                                     && yaffs_check_alloc_available(dev, 1)) {
3739                                         cache = yaffs_grab_chunk_cache(dev);
3740                                         cache->object = in;
3741                                         cache->chunk_id = chunk;
3742                                         cache->dirty = 0;
3743                                         cache->locked = 0;
3744                                         yaffs_rd_data_obj(in, chunk,
3745                                                           cache->data);
3746                                 } else if (cache &&
3747                                            !cache->dirty &&
3748                                            !yaffs_check_alloc_available(dev,
3749                                                                         1)) {
3750                                         /* Drop the cache if it was a read cache item and
3751                                          * no space check has been made for it.
3752                                          */
3753                                         cache = NULL;
3754                                 }
3755
3756                                 if (cache) {
3757                                         yaffs_use_cache(dev, cache, 1);
3758                                         cache->locked = 1;
3759
3760                                         memcpy(&cache->data[start], buffer,
3761                                                n_copy);
3762
3763                                         cache->locked = 0;
3764                                         cache->n_bytes = n_writeback;
3765
3766                                         if (write_trhrough) {
3767                                                 chunk_written =
3768                                                     yaffs_wr_data_obj
3769                                                     (cache->object,
3770                                                      cache->chunk_id,
3771                                                      cache->data,
3772                                                      cache->n_bytes, 1);
3773                                                 cache->dirty = 0;
3774                                         }
3775
3776                                 } else {
3777                                         chunk_written = -1;     /* fail the write */
3778                                 }
3779                         } else {
3780                                 /* An incomplete start or end chunk (or maybe both start and end chunk)
3781                                  * Read into the local buffer then copy, then copy over and write back.
3782                                  */
3783
3784                                 u8 *local_buffer =
3785                                     yaffs_get_temp_buffer(dev, __LINE__);
3786
3787                                 yaffs_rd_data_obj(in, chunk, local_buffer);
3788
3789                                 memcpy(&local_buffer[start], buffer, n_copy);
3790
3791                                 chunk_written =
3792