MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / fs / fat / prince-fat / fat-patch / cache.c
blob179cf62c4665590dc1a9af39e992b9ec130cd65c
1 /*
2 * linux/fs/fat/cache.c
4 * Written 1992,1993 by Werner Almesberger
6 * Mar 1999. AV. Changed cache, so that it uses the starting cluster instead
7 * of inode number.
8 * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
9 */
11 #include <linux/fs.h>
12 #include <linux/msdos_fs.h>
13 #include <linux/buffer_head.h>
14 //prince debug
15 //#define MAXFATHEADTEST 1000000
17 #if 0
18 #define debug_pr(fmt, args...) printk(fmt, ##args)
19 #else
20 #define debug_pr(fmt, args...)
21 #endif
23 /* this must be > 0. */
24 #define FAT_MAX_CACHE 8
26 struct fat_cache {
27 struct list_head cache_list;
28 int nr_contig; /* number of contiguous clusters */
29 int fcluster; /* cluster number in the file. */
30 int dcluster; /* cluster number on disk. */
33 static inline int fat_max_cache(struct inode *inode)
35 return FAT_MAX_CACHE;
38 static kmem_cache_t *fat_cache_cachep;
40 static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
42 struct fat_cache *cache = (struct fat_cache *)foo;
44 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
45 SLAB_CTOR_CONSTRUCTOR)
46 INIT_LIST_HEAD(&cache->cache_list);
49 int __init fat_cache_init(void)
51 fat_cache_cachep = kmem_cache_create("fat_cache",
52 sizeof(struct fat_cache),
53 0, SLAB_RECLAIM_ACCOUNT,
54 init_once, NULL);
55 if (fat_cache_cachep == NULL)
56 return -ENOMEM;
57 return 0;
60 void __exit fat_cache_destroy(void)
62 if (kmem_cache_destroy(fat_cache_cachep))
63 printk(KERN_INFO "fat_cache: not all structures were freed\n");
66 static inline struct fat_cache *fat_cache_alloc(struct inode *inode)
68 return kmem_cache_alloc(fat_cache_cachep, SLAB_KERNEL);
71 static inline void fat_cache_free(struct fat_cache *cache)
73 BUG_ON(!list_empty(&cache->cache_list));
74 kmem_cache_free(fat_cache_cachep, cache);
77 static inline void fat_cache_update_lru(struct inode *inode,
78 struct fat_cache *cache)
80 if (MSDOS_I(inode)->cache_lru.next != &cache->cache_list)
81 list_move(&cache->cache_list, &MSDOS_I(inode)->cache_lru);
84 static int fat_cache_lookup(struct inode *inode, int fclus,
85 struct fat_cache *cache,
86 int *cached_fclus, int *cached_dclus)
88 static struct fat_cache nohit = { .fcluster = 0, };
90 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
91 struct fat_cache *hit = &nohit, *p;
92 int offset = -1;
94 spin_lock(&sbi->cache_lock);
95 debug_pr("FAT: %s, fclus %d", __FUNCTION__, fclus);
96 list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) {
97 if (p->fcluster <= fclus && hit->fcluster < p->fcluster) {
98 hit = p;
99 debug_pr(", fclus %d, dclus %d, cont %d",
100 p->fcluster, p->dcluster, p->nr_contig);
101 if ((hit->fcluster + hit->nr_contig) < fclus) {
102 offset = hit->nr_contig;
103 debug_pr(" (off %d, hit)", offset);
104 } else {
105 offset = fclus - hit->fcluster;
106 debug_pr(" (off %d, full hit)", offset);
107 break;
111 if (hit != &nohit) {
112 fat_cache_update_lru(inode, hit);
113 *cache = *hit;
114 *cached_fclus = cache->fcluster + offset;
115 *cached_dclus = cache->dcluster + offset;
117 debug_pr("\n");
118 spin_unlock(&sbi->cache_lock);
120 return offset;
123 static struct fat_cache *fat_cache_merge(struct inode *inode,
124 struct fat_cache *new)
126 struct fat_cache *p, *hit = NULL;
128 list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) {
129 if (p->fcluster == new->fcluster) {
130 BUG_ON(p->dcluster != new->dcluster);
131 debug_pr("FAT: %s: merged fclus %d, dclus %d, "
132 "cur cont %d => new cont %d\n", __FUNCTION__,
133 p->fcluster, p->dcluster, p->nr_contig,
134 new->nr_contig);
135 if (new->nr_contig > p->nr_contig)
136 p->nr_contig = new->nr_contig;
137 hit = p;
138 break;
141 return hit;
144 static void fat_cache_add(struct inode *inode, struct fat_cache *new)
146 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
147 struct fat_cache *cache, *tmp;
149 debug_pr("FAT: %s: fclus %d, dclus %d, cont %d\n", __FUNCTION__,
150 new->fcluster, new->dcluster, new->nr_contig);
152 if (new->fcluster == -1) /* dummy cache */
153 return;
155 spin_lock(&sbi->cache_lock);
156 cache = fat_cache_merge(inode, new);
157 if (cache == NULL) {
158 if (MSDOS_I(inode)->nr_caches < fat_max_cache(inode)) {
159 MSDOS_I(inode)->nr_caches++;
160 spin_unlock(&sbi->cache_lock);
162 tmp = fat_cache_alloc(inode);
163 spin_lock(&sbi->cache_lock);
164 cache = fat_cache_merge(inode, new);
165 if (cache != NULL) {
166 MSDOS_I(inode)->nr_caches--;
167 fat_cache_free(tmp);
168 goto out;
170 cache = tmp;
171 } else {
172 struct list_head *p = MSDOS_I(inode)->cache_lru.prev;
173 cache = list_entry(p, struct fat_cache, cache_list);
175 cache->fcluster = new->fcluster;
176 cache->dcluster = new->dcluster;
177 cache->nr_contig = new->nr_contig;
179 out:
180 fat_cache_update_lru(inode, cache);
182 debug_pr("FAT: ");
183 list_for_each_entry(cache, &MSDOS_I(inode)->cache_lru, cache_list) {
184 debug_pr("(fclus %d, dclus %d, cont %d), ",
185 cache->fcluster, cache->dcluster, cache->nr_contig);
187 debug_pr("\n");
188 spin_unlock(&sbi->cache_lock);
192 * Cache invalidation occurs rarely, thus the LRU chain is not updated. It
193 * fixes itself after a while.
195 static void __fat_cache_inval_inode(struct inode *inode)
197 struct msdos_inode_info *i = MSDOS_I(inode);
198 struct fat_cache *cache;
199 while (!list_empty(&i->cache_lru)) {
200 cache = list_entry(i->cache_lru.next, struct fat_cache, cache_list);
201 list_del_init(&cache->cache_list);
202 MSDOS_I(inode)->nr_caches--;
203 fat_cache_free(cache);
205 debug_pr("FAT: %s\n", __FUNCTION__);
208 void fat_cache_inval_inode(struct inode *inode)
210 spin_lock(&MSDOS_SB(inode->i_sb)->cache_lock);
211 __fat_cache_inval_inode(inode);
212 spin_unlock(&MSDOS_SB(inode->i_sb)->cache_lock);
215 //prince add debug end
217 int __fat_access(struct super_block *sb, int nr, int new_value)
219 struct msdos_sb_info *sbi = MSDOS_SB(sb);
220 struct buffer_head *bh, *bh2, *c_bh, *c_bh2;
221 unsigned char *p_first, *p_last;
222 int copy, first, last, next, b;
224 if (sbi->fat_bits == 32) {
225 first = last = nr*4;
226 } else if (sbi->fat_bits == 16) {
227 first = last = nr*2;
228 } else {
229 first = nr*3/2;
230 last = first+1;
232 b = sbi->fat_start + (first >> sb->s_blocksize_bits);
233 if (!(bh = sb_bread(sb, b))) {
234 printk(KERN_ERR "FAT: bread(block %d) in"
235 " fat_access failed\n", b);
236 return -EIO;
238 if ((first >> sb->s_blocksize_bits) == (last >> sb->s_blocksize_bits)) {
239 bh2 = bh;
240 } else {
241 if (!(bh2 = sb_bread(sb, b + 1))) {
242 brelse(bh);
243 printk(KERN_ERR "FAT: bread(block %d) in"
244 " fat_access failed\n", b + 1);
245 return -EIO;
248 if (sbi->fat_bits == 32) {
249 p_first = p_last = NULL; // GCC needs that stuff
250 next = CF_LE_L(((__le32 *) bh->b_data)[(first &
251 (sb->s_blocksize - 1)) >> 2]);
252 // Fscking Microsoft marketing department. Their "32" is 28.
253 next &= 0x0fffffff;
254 } else if (sbi->fat_bits == 16) {
255 p_first = p_last = NULL; // GCC needs that stuff
256 next = CF_LE_W(((__le16 *) bh->b_data)[(first &
257 (sb->s_blocksize - 1)) >> 1]);
258 } else {
259 p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)];
260 p_last = &((__u8 *)bh2->b_data)[(first + 1) & (sb->s_blocksize - 1)];
261 if (nr & 1)
262 next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
263 else
264 next = (*p_first+(*p_last << 8)) & 0xfff;
266 if (new_value != -1) {
267 if (sbi->fat_bits == 32) {
268 ((__le32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
269 = CT_LE_L(new_value);
270 } else if (sbi->fat_bits == 16) {
271 ((__le16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
272 = CT_LE_W(new_value);
273 } else {
274 if (nr & 1) {
275 *p_first = (*p_first & 0xf) | (new_value << 4);
276 *p_last = new_value >> 4;
278 else {
279 *p_first = new_value & 0xff;
280 *p_last = (*p_last & 0xf0) | (new_value >> 8);
282 mark_buffer_dirty(bh2);
284 mark_buffer_dirty(bh);
285 for (copy = 1; copy < sbi->fats; copy++) {
286 b = sbi->fat_start + (first >> sb->s_blocksize_bits)
287 + sbi->fat_length * copy;
288 if (!(c_bh = sb_bread(sb, b)))
289 break;
290 if (bh != bh2) {
291 if (!(c_bh2 = sb_bread(sb, b+1))) {
292 brelse(c_bh);
293 break;
295 memcpy(c_bh2->b_data, bh2->b_data, sb->s_blocksize);
296 mark_buffer_dirty(c_bh2);
297 brelse(c_bh2);
299 memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize);
300 mark_buffer_dirty(c_bh);
301 brelse(c_bh);
304 brelse(bh);
305 if (bh != bh2)
306 brelse(bh2);
307 return next;
311 * Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
312 * new_value is != -1, that FAT entry is replaced by it.
314 int fat_access(struct super_block *sb, int nr, int new_value)
316 int next;
317 next = -EIO;
319 //prince debug
320 //int count;
322 //prince debug
323 //recheck:
326 if (nr < 2 || MSDOS_SB(sb)->clusters + 2 <= nr) {
327 //prince debug
328 //count++;
329 //if ( count <= MAXFATHEADTEST )
330 // goto recheck;
332 fat_fs_panic(sb, "invalid access to FAT (entry 0x%08x)", nr);
333 goto out;
335 if (new_value == FAT_ENT_EOF)
336 new_value = EOF_FAT(sb);
338 next = __fat_access(sb, nr, new_value);
339 if (next < 0)
340 goto out;
341 if (next >= BAD_FAT(sb))
342 next = FAT_ENT_EOF;
343 out:
344 return next;
347 /*===========prince delete debug
348 void fat_cache_init(struct super_block *sb)
350 struct msdos_sb_info *sbi = MSDOS_SB(sb);
351 int count;
353 spin_lock_init(&sbi->cache_lock);
355 for (count = 0; count < FAT_CACHE_NR - 1; count++) {
356 sbi->cache_array[count].start_cluster = 0;
357 sbi->cache_array[count].next = &sbi->cache_array[count + 1];
359 sbi->cache_array[count].start_cluster = 0;
360 sbi->cache_array[count].next = NULL;
361 sbi->cache = sbi->cache_array;
364 static void
365 fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu)
367 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
368 struct fat_cache *walk;
369 int first;
371 BUG_ON(cluster == 0);
373 first = MSDOS_I(inode)->i_start;
374 if (!first)
375 return;
377 spin_lock(&sbi->cache_lock);
379 if (MSDOS_I(inode)->disk_cluster &&
380 MSDOS_I(inode)->file_cluster <= cluster) {
381 *d_clu = MSDOS_I(inode)->disk_cluster;
382 *f_clu = MSDOS_I(inode)->file_cluster;
385 for (walk = sbi->cache; walk; walk = walk->next) {
386 if (walk->start_cluster == first
387 && walk->file_cluster <= cluster
388 && walk->file_cluster > *f_clu) {
389 *d_clu = walk->disk_cluster;
390 *f_clu = walk->file_cluster;
391 #ifdef DEBUG
392 printk("cache hit: %d (%d)\n", *f_clu, *d_clu);
393 #endif
394 if (*f_clu == cluster)
395 goto out;
398 #ifdef DEBUG
399 printk("cache miss\n");
400 #endif
401 out:
402 spin_unlock(&sbi->cache_lock);
405 #ifdef DEBUG
406 static void list_cache(struct super_block *sb)
408 struct msdos_sb_info *sbi = MSDOS_SB(sb);
409 struct fat_cache *walk;
411 for (walk = sbi->cache; walk; walk = walk->next) {
412 if (walk->start_cluster)
413 printk("<%s,%d>(%d,%d) ", sb->s_id,
414 walk->start_cluster, walk->file_cluster,
415 walk->disk_cluster);
416 else
417 printk("-- ");
419 printk("\n");
421 #endif
424 // Cache invalidation occurs rarely, thus the LRU chain is not updated. It
425 // fixes itself after a while.
426 ===========prince delete debug*/
427 //prince delete debug
428 //static void __fat_cache_inval_inode(struct inode *inode)
429 //prince add debug begin
430 static inline int cache_contiguous(struct fat_cache *cache, int dclus)
431 //prince add debug end
433 /*=====prince delete debug begin
434 struct fat_cache *walk;
435 int first = MSDOS_I(inode)->i_start;
436 MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0;
437 for (walk = MSDOS_SB(inode->i_sb)->cache; walk; walk = walk->next)
438 if (walk->start_cluster == first)
439 walk->start_cluster = 0;
440 ========prince delete debug end */
441 //prince add debug begin
442 cache->nr_contig++;
443 return ((cache->dcluster + cache->nr_contig) == dclus);
444 //prince add debug end
448 /*=====prince delete debug begin
449 void fat_cache_inval_inode(struct inode *inode)
450 ==============================*/
451 //prince add debug begin
452 static inline void cache_init(struct fat_cache *cache, int fclus, int dclus)
453 //prince add debug end
455 /*======prince delete debug begin
456 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
457 spin_lock(&sbi->cache_lock);
458 __fat_cache_inval_inode(inode);
459 spin_unlock(&sbi->cache_lock);
462 void fat_cache_add(struct inode *inode, int f_clu, int d_clu)
464 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
465 struct fat_cache *walk, *last;
466 int first, prev_f_clu, prev_d_clu;
468 if (f_clu == 0)
469 return;
470 first = MSDOS_I(inode)->i_start;
471 if (!first)
472 return;
474 last = NULL;
475 spin_lock(&sbi->cache_lock);
477 if (MSDOS_I(inode)->file_cluster == f_clu)
478 goto out;
479 else {
480 prev_f_clu = MSDOS_I(inode)->file_cluster;
481 prev_d_clu = MSDOS_I(inode)->disk_cluster;
482 MSDOS_I(inode)->file_cluster = f_clu;
483 MSDOS_I(inode)->disk_cluster = d_clu;
484 if (prev_f_clu == 0)
485 goto out;
486 f_clu = prev_f_clu;
487 d_clu = prev_d_clu;
490 for (walk = sbi->cache; walk->next; walk = (last = walk)->next) {
491 if (walk->start_cluster == first &&
492 walk->file_cluster == f_clu) {
493 if (walk->disk_cluster != d_clu) {
494 printk(KERN_ERR "FAT: cache corruption "
495 "(i_pos %lld)\n", MSDOS_I(inode)->i_pos);
496 __fat_cache_inval_inode(inode);
497 goto out;
499 if (last == NULL)
500 goto out;
502 // update LRU
503 last->next = walk->next;
504 walk->next = sbi->cache;
505 sbi->cache = walk;
506 #ifdef DEBUG
507 list_cache();
508 #endif
509 goto out;
512 walk->start_cluster = first;
513 walk->file_cluster = f_clu;
514 walk->disk_cluster = d_clu;
515 last->next = NULL;
516 walk->next = sbi->cache;
517 sbi->cache = walk;
518 #ifdef DEBUG
519 list_cache();
520 #endif
521 out:
522 spin_unlock(&sbi->cache_lock);
523 ===prince delete debug end*/
524 //prince add debug begin
525 cache->fcluster = fclus;
526 cache->dcluster = dclus;
527 cache->nr_contig = 0;
528 //prince add debug end
531 int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
533 struct super_block *sb = inode->i_sb;
534 const int limit = sb->s_maxbytes >> MSDOS_SB(sb)->cluster_bits;
535 //prince add debug begin
536 struct fat_cache cache;
537 //prince add debug end
538 int nr;
541 BUG_ON(MSDOS_I(inode)->i_start == 0);
543 *fclus = 0;
544 *dclus = MSDOS_I(inode)->i_start;
545 if (cluster == 0)
546 return 0;
547 /*==prince delete debug begin
548 fat_cache_lookup(inode, cluster, fclus, dclus);
549 ====prince delete debug end=*/
550 //prince add debug begin
551 if (fat_cache_lookup(inode, cluster, &cache, fclus, dclus) < 0)
552 cache_init(&cache, -1, -1); /* dummy, always not contiguous */
554 //prince add debug end
555 while (*fclus < cluster) {
556 /* prevent the infinite loop of cluster chain */
557 if (*fclus > limit) {
558 fat_fs_panic(sb, "%s: detected the cluster chain loop"
559 " (i_pos %lld)", __FUNCTION__,
560 MSDOS_I(inode)->i_pos);
561 return -EIO;
564 nr = fat_access(sb, *dclus, -1);
565 if (nr < 0)
566 return nr;
567 else if (nr == FAT_ENT_FREE) {
568 fat_fs_panic(sb, "%s: invalid cluster chain"
569 " (i_pos %lld)", __FUNCTION__,
570 MSDOS_I(inode)->i_pos);
571 return -EIO;
572 } else if (nr == FAT_ENT_EOF) {
573 /*===prince delete debug begin
574 fat_cache_add(inode, *fclus, *dclus);
575 =====prince delete debug end*/
576 //pricce add debug begin
577 fat_cache_add(inode, &cache);
578 //prince add debug end
579 return FAT_ENT_EOF;
581 (*fclus)++;
582 *dclus = nr;
583 //prince add debug begin
584 if (!cache_contiguous(&cache, *dclus))
585 cache_init(&cache, *fclus, *dclus);
586 //prince add debug end
589 /*==prince delete debug begin
590 fat_cache_add(inode, *fclus, *dclus);
591 ====prince delete debug end*/
592 //prince add debug begin
593 fat_cache_add(inode, &cache);
594 //prince add debug end
595 return 0;
598 static int fat_bmap_cluster(struct inode *inode, int cluster)
600 struct super_block *sb = inode->i_sb;
601 int ret, fclus, dclus;
603 if (MSDOS_I(inode)->i_start == 0)
604 return 0;
606 ret = fat_get_cluster(inode, cluster, &fclus, &dclus);
607 if (ret < 0)
608 return ret;
609 else if (ret == FAT_ENT_EOF) {
610 fat_fs_panic(sb, "%s: request beyond EOF (i_pos %lld)",
611 __FUNCTION__, MSDOS_I(inode)->i_pos);
612 return -EIO;
614 return dclus;
617 int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys)
619 struct super_block *sb = inode->i_sb;
620 struct msdos_sb_info *sbi = MSDOS_SB(sb);
621 sector_t last_block;
622 int cluster, offset;
624 *phys = 0;
625 if ((sbi->fat_bits != 32) &&
626 (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
627 !MSDOS_I(inode)->i_start))) {
628 if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits))
629 *phys = sector + sbi->dir_start;
630 return 0;
632 last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1))
633 >> sb->s_blocksize_bits;
634 if (sector >= last_block)
635 return 0;
637 cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
638 offset = sector & (sbi->sec_per_clus - 1);
639 cluster = fat_bmap_cluster(inode, cluster);
640 if (cluster < 0)
641 return cluster;
642 else if (cluster) {
643 *phys = ((sector_t)cluster - 2) * sbi->sec_per_clus
644 + sbi->data_start + offset;
646 return 0;
649 /* Free all clusters after the skip'th cluster. */
650 int fat_free(struct inode *inode, int skip)
652 struct super_block *sb = inode->i_sb;
653 int nr, ret, fclus, dclus;
655 //prince debug
656 //int count;
658 if (MSDOS_I(inode)->i_start == 0)
659 return 0;
661 if (skip) {
662 ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
663 if (ret < 0)
664 return ret;
665 else if (ret == FAT_ENT_EOF)
666 return 0;
668 nr = fat_access(sb, dclus, -1);
669 if (nr == FAT_ENT_EOF)
670 return 0;
671 else if (nr > 0) {
673 * write a new EOF, and get the remaining cluster
674 * chain for freeing.
676 nr = fat_access(sb, dclus, FAT_ENT_EOF);
678 if (nr < 0)
679 return nr;
681 fat_cache_inval_inode(inode);
682 } else {
683 fat_cache_inval_inode(inode);
685 nr = MSDOS_I(inode)->i_start;
686 MSDOS_I(inode)->i_start = 0;
687 MSDOS_I(inode)->i_logstart = 0;
688 mark_inode_dirty(inode);
691 lock_fat(sb);
692 do {
693 //prince debug
694 //recheck:
695 nr = fat_access(sb, nr, FAT_ENT_FREE);
696 if (nr < 0)
697 goto error;
698 else if (nr == FAT_ENT_FREE) {
699 //prince debug
700 //count++;
701 //if ( count <= MAXFATHEADTEST )
702 // goto recheck;
704 fat_fs_panic(sb, "%s: deleting beyond EOF (i_pos %lld)",
705 __FUNCTION__, MSDOS_I(inode)->i_pos);
706 nr = -EIO;
707 goto error;
709 if (MSDOS_SB(sb)->free_clusters != -1)
710 MSDOS_SB(sb)->free_clusters++;
711 inode->i_blocks -= MSDOS_SB(sb)->cluster_size >> 9;
712 } while (nr != FAT_ENT_EOF);
713 fat_clusters_flush(sb);
714 nr = 0;
715 error:
716 unlock_fat(sb);
718 return nr;