CD exfat support for Tomato. https://github.com/dorimanx/exfat-nofuse.
[tomato.git] / release / src-rt / linux / linux-2.6 / fs / exfat / exfat_cache.c
blob05c613653010c3f19c05d992e9e0693ba7d58f36
1 /*
2  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
3  *
4  *  This program is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU General Public License
6  *  as published by the Free Software Foundation; either version 2
7  *  of the License, or (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
19 /************************************************************************/
20 /*                                                                      */
21 /*  PROJECT : exFAT & FAT12/16/32 File System                           */
22 /*  FILE    : exfat_cache.c                                             */
23 /*  PURPOSE : exFAT Cache Manager                                       */
24 /*            (FAT Cache & Buffer Cache)                                */
25 /*                                                                      */
26 /*----------------------------------------------------------------------*/
27 /*  NOTES                                                               */
28 /*                                                                      */
29 /*----------------------------------------------------------------------*/
30 /*  REVISION HISTORY (Ver 0.9)                                          */
31 /*                                                                      */
32 /*  - 2010.11.15 [Sung-Kwan Kim] : first writing                        */
33 /*                                                                      */
34 /************************************************************************/
36 #include "exfat_config.h"
37 #include "exfat_global.h"
38 #include "exfat_data.h"
40 #include "exfat_cache.h"
41 #include "exfat_super.h"
42 #include "exfat.h"
44 /*----------------------------------------------------------------------*/
45 /*  Global Variable Definitions                                         */
46 /*----------------------------------------------------------------------*/
48 extern FS_STRUCT_T      fs_struct[];
50 #define sm_P(s)
51 #define sm_V(s)
53 static INT32 __FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content);
54 static INT32 __FAT_write(struct super_block *sb, UINT32 loc, UINT32 content);
56 static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, UINT32 sec);
57 static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, UINT32 sec);
58 static void FAT_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp);
59 static void FAT_cache_remove_hash(BUF_CACHE_T *bp);
61 static UINT8 *__buf_getblk(struct super_block *sb, UINT32 sec);
63 static BUF_CACHE_T *buf_cache_find(struct super_block *sb, UINT32 sec);
64 static BUF_CACHE_T *buf_cache_get(struct super_block *sb, UINT32 sec);
65 static void buf_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp);
66 static void buf_cache_remove_hash(BUF_CACHE_T *bp);
68 static void push_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list);
69 static void push_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list);
70 static void move_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list);
71 static void move_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list);
73 /*======================================================================*/
74 /*  Cache Initialization Functions                                      */
75 /*======================================================================*/
77 INT32 buf_init(struct super_block *sb)
79         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
81         INT32 i;
83         /* LRU list */
84         p_fs->FAT_cache_lru_list.next = p_fs->FAT_cache_lru_list.prev = &p_fs->FAT_cache_lru_list;
86         for (i = 0; i < FAT_CACHE_SIZE; i++) {
87                 p_fs->FAT_cache_array[i].drv = -1;
88                 p_fs->FAT_cache_array[i].sec = ~0;
89                 p_fs->FAT_cache_array[i].flag = 0;
90                 p_fs->FAT_cache_array[i].buf_bh = NULL;
91                 p_fs->FAT_cache_array[i].prev = p_fs->FAT_cache_array[i].next = NULL;
92                 push_to_mru(&(p_fs->FAT_cache_array[i]), &p_fs->FAT_cache_lru_list);
93         }
95         p_fs->buf_cache_lru_list.next = p_fs->buf_cache_lru_list.prev = &p_fs->buf_cache_lru_list;
97         for (i = 0; i < BUF_CACHE_SIZE; i++) {
98                 p_fs->buf_cache_array[i].drv = -1;
99                 p_fs->buf_cache_array[i].sec = ~0;
100                 p_fs->buf_cache_array[i].flag = 0;
101                 p_fs->buf_cache_array[i].buf_bh = NULL;
102                 p_fs->buf_cache_array[i].prev = p_fs->buf_cache_array[i].next = NULL;
103                 push_to_mru(&(p_fs->buf_cache_array[i]), &p_fs->buf_cache_lru_list);
104         }
106         /* HASH list */
107         for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) {
108                 p_fs->FAT_cache_hash_list[i].drv = -1;
109                 p_fs->FAT_cache_hash_list[i].sec = ~0;
110                 p_fs->FAT_cache_hash_list[i].hash_next = p_fs->FAT_cache_hash_list[i].hash_prev = &(p_fs->FAT_cache_hash_list[i]);
111         }
113         for (i = 0; i < FAT_CACHE_SIZE; i++) {
114                 FAT_cache_insert_hash(sb, &(p_fs->FAT_cache_array[i]));
115         }
117         for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) {
118                 p_fs->buf_cache_hash_list[i].drv = -1;
119                 p_fs->buf_cache_hash_list[i].sec = ~0;
120                 p_fs->buf_cache_hash_list[i].hash_next = p_fs->buf_cache_hash_list[i].hash_prev = &(p_fs->buf_cache_hash_list[i]);
121         }
123         for (i = 0; i < BUF_CACHE_SIZE; i++) {
124                 buf_cache_insert_hash(sb, &(p_fs->buf_cache_array[i]));
125         }
127         return(FFS_SUCCESS);
128 } /* end of buf_init */
130 INT32 buf_shutdown(struct super_block *sb)
132         return(FFS_SUCCESS);
133 } /* end of buf_shutdown */
135 /*======================================================================*/
136 /*  FAT Read/Write Functions                                            */
137 /*======================================================================*/
139 /* in : sb, loc
140   * out: content
141   * returns 0 on success
142   *            -1 on error
143   */
144 INT32 FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content)
146         INT32 ret;
148         sm_P(&f_sem);
150         ret = __FAT_read(sb, loc, content);
152         sm_V(&f_sem);
154         return(ret);
155 } /* end of FAT_read */
157 INT32 FAT_write(struct super_block *sb, UINT32 loc, UINT32 content)
159         INT32 ret;
161         sm_P(&f_sem);
163         ret = __FAT_write(sb, loc, content);
165         sm_V(&f_sem);
167         return(ret);
168 } /* end of FAT_write */
170 static INT32 __FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content)
172         INT32 off;
173         UINT32 sec, _content;
174         UINT8 *fat_sector, *fat_entry;
175         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
176         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
178         if (p_fs->vol_type == FAT12) {
179                 sec = p_fs->FAT1_start_sector + ((loc + (loc >> 1)) >> p_bd->sector_size_bits);
180                 off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
182                 if (off == (p_bd->sector_size-1)) {
183                         fat_sector = FAT_getblk(sb, sec);
184                         if (!fat_sector)
185                                 return -1;
187                         _content  = (UINT32) fat_sector[off];
189                         fat_sector = FAT_getblk(sb, ++sec);
190                         if (!fat_sector)
191                                 return -1;
193                         _content |= (UINT32) fat_sector[0] << 8;
194                 } else {
195                         fat_sector = FAT_getblk(sb, sec);
196                         if (!fat_sector)
197                                 return -1;
199                         fat_entry = &(fat_sector[off]);
200                         _content = GET16(fat_entry);
201                 }
203                 if (loc & 1) _content >>= 4;
205                 _content &= 0x00000FFF;
207                 if (_content >= CLUSTER_16(0x0FF8)) {
208                         *content = CLUSTER_32(~0);
209                         return 0;
210                 } else {
211                         *content = CLUSTER_32(_content);
212                         return 0;
213                 }
214         } else if (p_fs->vol_type == FAT16) {
215                 sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-1));
216                 off = (loc << 1) & p_bd->sector_size_mask;
218                 fat_sector = FAT_getblk(sb, sec);
219                 if (!fat_sector)
220                         return -1;
222                 fat_entry = &(fat_sector[off]);
224                 _content = GET16_A(fat_entry);
226                 _content &= 0x0000FFFF;
228                 if (_content >= CLUSTER_16(0xFFF8)) {
229                         *content = CLUSTER_32(~0);
230                         return 0;
231                 } else {
232                         *content = CLUSTER_32(_content);
233                         return 0;
234                 }
235         } else if (p_fs->vol_type == FAT32) {
236                 sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2));
237                 off = (loc << 2) & p_bd->sector_size_mask;
239                 fat_sector = FAT_getblk(sb, sec);
240                 if (!fat_sector)
241                         return -1;
243                 fat_entry = &(fat_sector[off]);
245                 _content = GET32_A(fat_entry);
247                 _content &= 0x0FFFFFFF;
249                 if (_content >= CLUSTER_32(0x0FFFFFF8)) {
250                         *content = CLUSTER_32(~0);
251                         return 0;
252                 } else {
253                         *content = CLUSTER_32(_content);
254                         return 0;
255                 }
256         } else {
257                 sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2));
258                 off = (loc << 2) & p_bd->sector_size_mask;
260                 fat_sector = FAT_getblk(sb, sec);
261                 if (!fat_sector)
262                         return -1;
264                 fat_entry = &(fat_sector[off]);
265                 _content = GET32_A(fat_entry);
267                 if (_content >= CLUSTER_32(0xFFFFFFF8)) {
268                         *content = CLUSTER_32(~0);
269                         return 0;
270                 } else {
271                         *content = CLUSTER_32(_content);
272                         return 0;
273                 }
274         }
276         *content = CLUSTER_32(~0);
277         return 0;
278 } /* end of __FAT_read */
280 static INT32 __FAT_write(struct super_block *sb, UINT32 loc, UINT32 content)
282         INT32 off;
283         UINT32 sec;
284         UINT8 *fat_sector, *fat_entry;
285         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
286         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
288         if (p_fs->vol_type == FAT12) {
290                 content &= 0x00000FFF;
292                 sec = p_fs->FAT1_start_sector + ((loc + (loc >> 1)) >> p_bd->sector_size_bits);
293                 off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
295                 fat_sector = FAT_getblk(sb, sec);
296                 if (!fat_sector)
297                         return -1;
299                 if (loc & 1) { /* odd */
301                         content <<= 4;
303                         if (off == (p_bd->sector_size-1)) {
304                                 fat_sector[off] = (UINT8)(content | (fat_sector[off] & 0x0F));
305                                 FAT_modify(sb, sec);
307                                 fat_sector = FAT_getblk(sb, ++sec);
308                                 if (!fat_sector)
309                                         return -1;
311                                 fat_sector[0] = (UINT8)(content >> 8);
312                         } else {
313                                 fat_entry = &(fat_sector[off]);
314                                 content |= GET16(fat_entry) & 0x000F;
316                                 SET16(fat_entry, content);
317                         }
318                 } else { /* even */
319                         fat_sector[off] = (UINT8)(content);
321                         if (off == (p_bd->sector_size-1)) {
322                                 fat_sector[off] = (UINT8)(content);
323                                 FAT_modify(sb, sec);
325                                 fat_sector = FAT_getblk(sb, ++sec);
326                                 fat_sector[0] = (UINT8)((fat_sector[0] & 0xF0) | (content >> 8));
327                         } else {
328                                 fat_entry = &(fat_sector[off]);
329                                 content |= GET16(fat_entry) & 0xF000;
331                                 SET16(fat_entry, content);
332                         }
333                 }
334         }
336         else if (p_fs->vol_type == FAT16) {
338                 content &= 0x0000FFFF;
340                 sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-1));
341                 off = (loc << 1) & p_bd->sector_size_mask;
343                 fat_sector = FAT_getblk(sb, sec);
344                 if (!fat_sector)
345                         return -1;
347                 fat_entry = &(fat_sector[off]);
349                 SET16_A(fat_entry, content);
350         }
352         else if (p_fs->vol_type == FAT32) {
354                 content &= 0x0FFFFFFF;
356                 sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2));
357                 off = (loc << 2) & p_bd->sector_size_mask;
359                 fat_sector = FAT_getblk(sb, sec);
360                 if (!fat_sector)
361                         return -1;
363                 fat_entry = &(fat_sector[off]);
365                 content |= GET32_A(fat_entry) & 0xF0000000;
367                 SET32_A(fat_entry, content);
368         }
370         else { /* p_fs->vol_type == EXFAT */
372                 sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2));
373                 off = (loc << 2) & p_bd->sector_size_mask;
375                 fat_sector = FAT_getblk(sb, sec);
376                 if (!fat_sector)
377                         return -1;
379                 fat_entry = &(fat_sector[off]);
381                 SET32_A(fat_entry, content);
382         }
384         FAT_modify(sb, sec);
385         return 0;
386 } /* end of __FAT_write */
388 UINT8 *FAT_getblk(struct super_block *sb, UINT32 sec)
390         BUF_CACHE_T *bp;
391         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
393         bp = FAT_cache_find(sb, sec);
394         if (bp != NULL) {
395                 move_to_mru(bp, &p_fs->FAT_cache_lru_list);
396                 return(bp->buf_bh->b_data);
397         }
399         bp = FAT_cache_get(sb, sec);
401         FAT_cache_remove_hash(bp);
403         bp->drv = p_fs->drv;
404         bp->sec = sec;
405         bp->flag = 0;
407         FAT_cache_insert_hash(sb, bp);
409         if (sector_read(sb, sec, &(bp->buf_bh), 1) != FFS_SUCCESS) {
410                 FAT_cache_remove_hash(bp);
411                 bp->drv = -1;
412                 bp->sec = ~0;
413                 bp->flag = 0;
414                 bp->buf_bh = NULL;
416                 move_to_lru(bp, &p_fs->FAT_cache_lru_list);
417                 return NULL;
418         }
420         return(bp->buf_bh->b_data);
421 } /* end of FAT_getblk */
423 void FAT_modify(struct super_block *sb, UINT32 sec)
425         BUF_CACHE_T *bp;
427         bp = FAT_cache_find(sb, sec);
428         if (bp != NULL) {
429                 sector_write(sb, sec, bp->buf_bh, 0);
430         }
431 } /* end of FAT_modify */
433 void FAT_release_all(struct super_block *sb)
435         BUF_CACHE_T *bp;
436         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
438         sm_P(&f_sem);
440         bp = p_fs->FAT_cache_lru_list.next;
441         while (bp != &p_fs->FAT_cache_lru_list) {
442                 if (bp->drv == p_fs->drv) {
443                         bp->drv = -1;
444                         bp->sec = ~0;
445                         bp->flag = 0;
447                         if(bp->buf_bh) {
448                                 __brelse(bp->buf_bh);
449                                 bp->buf_bh = NULL;
450                         }
451                 }
452                 bp = bp->next;
453         }
455         sm_V(&f_sem);
456 } /* end of FAT_release_all */
458 void FAT_sync(struct super_block *sb)
460         BUF_CACHE_T *bp;
461         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
463         sm_P(&f_sem);
465         bp = p_fs->FAT_cache_lru_list.next;
466         while (bp != &p_fs->FAT_cache_lru_list) {
467                 if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) {
468                         sync_dirty_buffer(bp->buf_bh);
469                         bp->flag &= ~(DIRTYBIT);
470                 }
471                 bp = bp->next;
472         }
474         sm_V(&f_sem);
475 } /* end of FAT_sync */
477 static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, UINT32 sec)
479         INT32 off;
480         BUF_CACHE_T *bp, *hp;
481         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
483         off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1);
485         hp = &(p_fs->FAT_cache_hash_list[off]);
486         for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) {
487                 if ((bp->drv == p_fs->drv) && (bp->sec == sec)) {
489                         WARN(!bp->buf_bh, "[EXFAT] FAT_cache has no bh. "
490                                           "It will make system panic.\n");
492                         touch_buffer(bp->buf_bh);
493                         return(bp);
494                 }
495         }
496         return(NULL);
497 } /* end of FAT_cache_find */
499 static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, UINT32 sec)
501         BUF_CACHE_T *bp;
502         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
504         bp = p_fs->FAT_cache_lru_list.prev;
507         move_to_mru(bp, &p_fs->FAT_cache_lru_list);
508         return(bp);
509 } /* end of FAT_cache_get */
511 static void FAT_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp)
513         INT32 off;
514         BUF_CACHE_T *hp;
515         FS_INFO_T *p_fs;
517         p_fs = &(EXFAT_SB(sb)->fs_info);
518         off = (bp->sec + (bp->sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE-1);
520         hp = &(p_fs->FAT_cache_hash_list[off]);
521         bp->hash_next = hp->hash_next;
522         bp->hash_prev = hp;
523         hp->hash_next->hash_prev = bp;
524         hp->hash_next = bp;
525 } /* end of FAT_cache_insert_hash */
527 static void FAT_cache_remove_hash(BUF_CACHE_T *bp)
529         (bp->hash_prev)->hash_next = bp->hash_next;
530         (bp->hash_next)->hash_prev = bp->hash_prev;
531 } /* end of FAT_cache_remove_hash */
533 /*======================================================================*/
534 /*  Buffer Read/Write Functions                                         */
535 /*======================================================================*/
537 UINT8 *buf_getblk(struct super_block *sb, UINT32 sec)
539         UINT8 *buf;
541         sm_P(&b_sem);
543         buf = __buf_getblk(sb, sec);
545         sm_V(&b_sem);
547         return(buf);
548 } /* end of buf_getblk */
550 static UINT8 *__buf_getblk(struct super_block *sb, UINT32 sec)
552         BUF_CACHE_T *bp;
553         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
555         bp = buf_cache_find(sb, sec);
556         if (bp != NULL) {
557                 move_to_mru(bp, &p_fs->buf_cache_lru_list);
558                 return(bp->buf_bh->b_data);
559         }
561         bp = buf_cache_get(sb, sec);
563         buf_cache_remove_hash(bp);
565         bp->drv = p_fs->drv;
566         bp->sec = sec;
567         bp->flag = 0;
569         buf_cache_insert_hash(sb, bp);
571         if (sector_read(sb, sec, &(bp->buf_bh), 1) != FFS_SUCCESS) {
572                 buf_cache_remove_hash(bp);
573                 bp->drv = -1;
574                 bp->sec = ~0;
575                 bp->flag = 0;
576                 bp->buf_bh = NULL;
578                 move_to_lru(bp, &p_fs->buf_cache_lru_list);
579                 return NULL;
580         }
582         return(bp->buf_bh->b_data);
584 } /* end of __buf_getblk */
586 void buf_modify(struct super_block *sb, UINT32 sec)
588         BUF_CACHE_T *bp;
590         sm_P(&b_sem);
592         bp = buf_cache_find(sb, sec);
593         if (likely(bp != NULL)) {
594                 sector_write(sb, sec, bp->buf_bh, 0);
595         }
597         WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec);
599         sm_V(&b_sem);
600 } /* end of buf_modify */
602 void buf_lock(struct super_block *sb, UINT32 sec)
604         BUF_CACHE_T *bp;
606         sm_P(&b_sem);
608         bp = buf_cache_find(sb, sec);
609         if (likely(bp != NULL)) bp->flag |= LOCKBIT;
611         WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec);
613         sm_V(&b_sem);
614 } /* end of buf_lock */
616 void buf_unlock(struct super_block *sb, UINT32 sec)
618         BUF_CACHE_T *bp;
620         sm_P(&b_sem);
622         bp = buf_cache_find(sb, sec);
623         if (likely(bp != NULL)) bp->flag &= ~(LOCKBIT);
625         WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec);
627         sm_V(&b_sem);
628 } /* end of buf_unlock */
630 void buf_release(struct super_block *sb, UINT32 sec)
632         BUF_CACHE_T *bp;
633         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
635         sm_P(&b_sem);
637         bp = buf_cache_find(sb, sec);
638         if (likely(bp != NULL)) {
639                 bp->drv = -1;
640                 bp->sec = ~0;
641                 bp->flag = 0;
643                 if(bp->buf_bh) {
644                         __brelse(bp->buf_bh);
645                         bp->buf_bh = NULL;
646                 }
648                 move_to_lru(bp, &p_fs->buf_cache_lru_list);
649         }
651         sm_V(&b_sem);
652 } /* end of buf_release */
654 void buf_release_all(struct super_block *sb)
656         BUF_CACHE_T *bp;
657         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
659         sm_P(&b_sem);
661         bp = p_fs->buf_cache_lru_list.next;
662         while (bp != &p_fs->buf_cache_lru_list) {
663                 if (bp->drv == p_fs->drv) {
664                         bp->drv = -1;
665                         bp->sec = ~0;
666                         bp->flag = 0;
668                         if(bp->buf_bh) {
669                                 __brelse(bp->buf_bh);
670                                 bp->buf_bh = NULL;
671                         }
672                 }
673                 bp = bp->next;
674         }
676         sm_V(&b_sem);
677 } /* end of buf_release_all */
679 void buf_sync(struct super_block *sb)
681         BUF_CACHE_T *bp;
682         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
684         sm_P(&b_sem);
686         bp = p_fs->buf_cache_lru_list.next;
687         while (bp != &p_fs->buf_cache_lru_list) {
688                 if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) {
689                         sync_dirty_buffer(bp->buf_bh);
690                         bp->flag &= ~(DIRTYBIT);
691                 }
692                 bp = bp->next;
693         }
695         sm_V(&b_sem);
696 } /* end of buf_sync */
698 static BUF_CACHE_T *buf_cache_find(struct super_block *sb, UINT32 sec)
700         INT32 off;
701         BUF_CACHE_T *bp, *hp;
702         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
704         off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & (BUF_CACHE_HASH_SIZE - 1);
706         hp = &(p_fs->buf_cache_hash_list[off]);
707         for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) {
708                 if ((bp->drv == p_fs->drv) && (bp->sec == sec)) {
709                         touch_buffer(bp->buf_bh);
710                         return(bp);
711                 }
712         }
713         return(NULL);
714 } /* end of buf_cache_find */
716 static BUF_CACHE_T *buf_cache_get(struct super_block *sb, UINT32 sec)
718         BUF_CACHE_T *bp;
719         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
721         bp = p_fs->buf_cache_lru_list.prev;
722         while (bp->flag & LOCKBIT) bp = bp->prev;
725         move_to_mru(bp, &p_fs->buf_cache_lru_list);
726         return(bp);
727 } /* end of buf_cache_get */
729 static void buf_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp)
731         INT32 off;
732         BUF_CACHE_T *hp;
733         FS_INFO_T *p_fs;
735         p_fs = &(EXFAT_SB(sb)->fs_info);
736         off = (bp->sec + (bp->sec >> p_fs->sectors_per_clu_bits)) & (BUF_CACHE_HASH_SIZE-1);
738         hp = &(p_fs->buf_cache_hash_list[off]);
739         bp->hash_next = hp->hash_next;
740         bp->hash_prev = hp;
741         hp->hash_next->hash_prev = bp;
742         hp->hash_next = bp;
743 } /* end of buf_cache_insert_hash */
745 static void buf_cache_remove_hash(BUF_CACHE_T *bp)
747         (bp->hash_prev)->hash_next = bp->hash_next;
748         (bp->hash_next)->hash_prev = bp->hash_prev;
749 } /* end of buf_cache_remove_hash */
751 /*======================================================================*/
752 /*  Local Function Definitions                                          */
753 /*======================================================================*/
755 static void push_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list)
757         bp->next = list->next;
758         bp->prev = list;
759         list->next->prev = bp;
760         list->next = bp;
761 } /* end of buf_cache_push_to_mru */
763 static void push_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list)
765         bp->prev = list->prev;
766         bp->next = list;
767         list->prev->next = bp;
768         list->prev = bp;
769 } /* end of buf_cache_push_to_lru */
771 static void move_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list)
773         bp->prev->next = bp->next;
774         bp->next->prev = bp->prev;
775         push_to_mru(bp, list);
776 } /* end of buf_cache_move_to_mru */
778 static void move_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list)
780         bp->prev->next = bp->next;
781         bp->next->prev = bp->prev;
782         push_to_lru(bp, list);
783 } /* end of buf_cache_move_to_lru */
785 /* end of exfat_cache.c */