1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
6 #include <linux/buffer_head.h>
8 #include <linux/mutex.h>
15 static DEFINE_SEMAPHORE(f_sem);
16 static DEFINE_SEMAPHORE(b_sem);
18 static struct buf_cache_t *FAT_cache_find(struct super_block *sb, sector_t sec)
21 struct buf_cache_t *bp, *hp;
22 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
25 (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1);
27 hp = &p_fs->FAT_cache_hash_list[off];
28 for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) {
29 if ((bp->drv == p_fs->drv) && (bp->sec == sec)) {
31 "[EXFAT] FAT_cache has no bh. It will make system panic.\n");
33 touch_buffer(bp->buf_bh);
40 static void push_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list)
42 bp->next = list->next;
44 list->next->prev = bp;
48 static void push_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list)
50 bp->prev = list->prev;
52 list->prev->next = bp;
56 static void move_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list)
58 bp->prev->next = bp->next;
59 bp->next->prev = bp->prev;
60 push_to_mru(bp, list);
63 static void move_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list)
65 bp->prev->next = bp->next;
66 bp->next->prev = bp->prev;
67 push_to_lru(bp, list);
70 static struct buf_cache_t *FAT_cache_get(struct super_block *sb, sector_t sec)
72 struct buf_cache_t *bp;
73 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
75 bp = p_fs->FAT_cache_lru_list.prev;
77 move_to_mru(bp, &p_fs->FAT_cache_lru_list);
81 static void FAT_cache_insert_hash(struct super_block *sb,
82 struct buf_cache_t *bp)
85 struct buf_cache_t *hp;
86 struct fs_info_t *p_fs;
88 p_fs = &(EXFAT_SB(sb)->fs_info);
90 (bp->sec >> p_fs->sectors_per_clu_bits)) &
91 (FAT_CACHE_HASH_SIZE - 1);
93 hp = &p_fs->FAT_cache_hash_list[off];
94 bp->hash_next = hp->hash_next;
96 hp->hash_next->hash_prev = bp;
100 static void FAT_cache_remove_hash(struct buf_cache_t *bp)
102 (bp->hash_prev)->hash_next = bp->hash_next;
103 (bp->hash_next)->hash_prev = bp->hash_prev;
106 static void buf_cache_insert_hash(struct super_block *sb,
107 struct buf_cache_t *bp)
110 struct buf_cache_t *hp;
111 struct fs_info_t *p_fs;
113 p_fs = &(EXFAT_SB(sb)->fs_info);
115 (bp->sec >> p_fs->sectors_per_clu_bits)) &
116 (BUF_CACHE_HASH_SIZE - 1);
118 hp = &p_fs->buf_cache_hash_list[off];
119 bp->hash_next = hp->hash_next;
121 hp->hash_next->hash_prev = bp;
125 static void buf_cache_remove_hash(struct buf_cache_t *bp)
127 (bp->hash_prev)->hash_next = bp->hash_next;
128 (bp->hash_next)->hash_prev = bp->hash_prev;
131 void buf_init(struct super_block *sb)
133 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
138 p_fs->FAT_cache_lru_list.next = &p_fs->FAT_cache_lru_list;
139 p_fs->FAT_cache_lru_list.prev = &p_fs->FAT_cache_lru_list;
141 for (i = 0; i < FAT_CACHE_SIZE; i++) {
142 p_fs->FAT_cache_array[i].drv = -1;
143 p_fs->FAT_cache_array[i].sec = ~0;
144 p_fs->FAT_cache_array[i].flag = 0;
145 p_fs->FAT_cache_array[i].buf_bh = NULL;
146 p_fs->FAT_cache_array[i].prev = NULL;
147 p_fs->FAT_cache_array[i].next = NULL;
148 push_to_mru(&p_fs->FAT_cache_array[i],
149 &p_fs->FAT_cache_lru_list);
152 p_fs->buf_cache_lru_list.next = &p_fs->buf_cache_lru_list;
153 p_fs->buf_cache_lru_list.prev = &p_fs->buf_cache_lru_list;
155 for (i = 0; i < BUF_CACHE_SIZE; i++) {
156 p_fs->buf_cache_array[i].drv = -1;
157 p_fs->buf_cache_array[i].sec = ~0;
158 p_fs->buf_cache_array[i].flag = 0;
159 p_fs->buf_cache_array[i].buf_bh = NULL;
160 p_fs->buf_cache_array[i].prev = NULL;
161 p_fs->buf_cache_array[i].next = NULL;
162 push_to_mru(&p_fs->buf_cache_array[i],
163 &p_fs->buf_cache_lru_list);
167 for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) {
168 p_fs->FAT_cache_hash_list[i].drv = -1;
169 p_fs->FAT_cache_hash_list[i].sec = ~0;
170 p_fs->FAT_cache_hash_list[i].hash_next =
171 &p_fs->FAT_cache_hash_list[i];
172 p_fs->FAT_cache_hash_list[i].hash_prev =
173 &p_fs->FAT_cache_hash_list[i];
176 for (i = 0; i < FAT_CACHE_SIZE; i++)
177 FAT_cache_insert_hash(sb, &p_fs->FAT_cache_array[i]);
179 for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) {
180 p_fs->buf_cache_hash_list[i].drv = -1;
181 p_fs->buf_cache_hash_list[i].sec = ~0;
182 p_fs->buf_cache_hash_list[i].hash_next =
183 &p_fs->buf_cache_hash_list[i];
184 p_fs->buf_cache_hash_list[i].hash_prev =
185 &p_fs->buf_cache_hash_list[i];
188 for (i = 0; i < BUF_CACHE_SIZE; i++)
189 buf_cache_insert_hash(sb, &p_fs->buf_cache_array[i]);
192 void buf_shutdown(struct super_block *sb)
196 static int __FAT_read(struct super_block *sb, u32 loc, u32 *content)
201 u8 *fat_sector, *fat_entry;
202 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
203 struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
205 if (p_fs->vol_type == FAT12) {
206 sec = p_fs->FAT1_start_sector +
207 ((loc + (loc >> 1)) >> p_bd->sector_size_bits);
208 off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
210 if (off == (p_bd->sector_size - 1)) {
211 fat_sector = FAT_getblk(sb, sec);
215 _content = (u32)fat_sector[off];
217 fat_sector = FAT_getblk(sb, ++sec);
221 _content |= (u32)fat_sector[0] << 8;
223 fat_sector = FAT_getblk(sb, sec);
227 fat_entry = &fat_sector[off];
228 _content = GET16(fat_entry);
234 _content &= 0x00000FFF;
236 if (_content >= CLUSTER_16(0x0FF8)) {
237 *content = CLUSTER_32(~0);
240 *content = CLUSTER_32(_content);
242 } else if (p_fs->vol_type == FAT16) {
243 sec = p_fs->FAT1_start_sector +
244 (loc >> (p_bd->sector_size_bits - 1));
245 off = (loc << 1) & p_bd->sector_size_mask;
247 fat_sector = FAT_getblk(sb, sec);
251 fat_entry = &fat_sector[off];
253 _content = GET16_A(fat_entry);
255 _content &= 0x0000FFFF;
257 if (_content >= CLUSTER_16(0xFFF8)) {
258 *content = CLUSTER_32(~0);
261 *content = CLUSTER_32(_content);
263 } else if (p_fs->vol_type == FAT32) {
264 sec = p_fs->FAT1_start_sector +
265 (loc >> (p_bd->sector_size_bits - 2));
266 off = (loc << 2) & p_bd->sector_size_mask;
268 fat_sector = FAT_getblk(sb, sec);
272 fat_entry = &fat_sector[off];
274 _content = GET32_A(fat_entry);
276 _content &= 0x0FFFFFFF;
278 if (_content >= CLUSTER_32(0x0FFFFFF8)) {
279 *content = CLUSTER_32(~0);
282 *content = CLUSTER_32(_content);
284 } else if (p_fs->vol_type == EXFAT) {
285 sec = p_fs->FAT1_start_sector +
286 (loc >> (p_bd->sector_size_bits - 2));
287 off = (loc << 2) & p_bd->sector_size_mask;
289 fat_sector = FAT_getblk(sb, sec);
293 fat_entry = &fat_sector[off];
294 _content = GET32_A(fat_entry);
296 if (_content >= CLUSTER_32(0xFFFFFFF8)) {
297 *content = CLUSTER_32(~0);
300 *content = CLUSTER_32(_content);
304 /* Unknown volume type, throw in the towel and go home */
305 *content = CLUSTER_32(~0);
311 * returns 0 on success
314 int FAT_read(struct super_block *sb, u32 loc, u32 *content)
319 ret = __FAT_read(sb, loc, content);
325 static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
329 u8 *fat_sector, *fat_entry;
330 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
331 struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
333 if (p_fs->vol_type == FAT12) {
334 content &= 0x00000FFF;
336 sec = p_fs->FAT1_start_sector +
337 ((loc + (loc >> 1)) >> p_bd->sector_size_bits);
338 off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
340 fat_sector = FAT_getblk(sb, sec);
344 if (loc & 1) { /* odd */
347 if (off == (p_bd->sector_size - 1)) {
348 fat_sector[off] = (u8)(content |
353 fat_sector = FAT_getblk(sb, ++sec);
357 fat_sector[0] = (u8)(content >> 8);
359 fat_entry = &fat_sector[off];
360 content |= GET16(fat_entry) & 0x000F;
362 SET16(fat_entry, content);
365 fat_sector[off] = (u8)(content);
367 if (off == (p_bd->sector_size - 1)) {
368 fat_sector[off] = (u8)(content);
371 fat_sector = FAT_getblk(sb, ++sec);
374 fat_sector[0] = (u8)((fat_sector[0] & 0xF0) |
377 fat_entry = &fat_sector[off];
378 content |= GET16(fat_entry) & 0xF000;
380 SET16(fat_entry, content);
385 else if (p_fs->vol_type == FAT16) {
386 content &= 0x0000FFFF;
388 sec = p_fs->FAT1_start_sector + (loc >>
389 (p_bd->sector_size_bits - 1));
390 off = (loc << 1) & p_bd->sector_size_mask;
392 fat_sector = FAT_getblk(sb, sec);
396 fat_entry = &fat_sector[off];
398 SET16_A(fat_entry, content);
399 } else if (p_fs->vol_type == FAT32) {
400 content &= 0x0FFFFFFF;
402 sec = p_fs->FAT1_start_sector + (loc >>
403 (p_bd->sector_size_bits - 2));
404 off = (loc << 2) & p_bd->sector_size_mask;
406 fat_sector = FAT_getblk(sb, sec);
410 fat_entry = &fat_sector[off];
412 content |= GET32_A(fat_entry) & 0xF0000000;
414 SET32_A(fat_entry, content);
415 } else { /* p_fs->vol_type == EXFAT */
416 sec = p_fs->FAT1_start_sector + (loc >>
417 (p_bd->sector_size_bits - 2));
418 off = (loc << 2) & p_bd->sector_size_mask;
420 fat_sector = FAT_getblk(sb, sec);
424 fat_entry = &fat_sector[off];
426 SET32_A(fat_entry, content);
433 int FAT_write(struct super_block *sb, u32 loc, u32 content)
438 ret = __FAT_write(sb, loc, content);
444 u8 *FAT_getblk(struct super_block *sb, sector_t sec)
446 struct buf_cache_t *bp;
447 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
449 bp = FAT_cache_find(sb, sec);
451 move_to_mru(bp, &p_fs->FAT_cache_lru_list);
452 return bp->buf_bh->b_data;
455 bp = FAT_cache_get(sb, sec);
457 FAT_cache_remove_hash(bp);
463 FAT_cache_insert_hash(sb, bp);
465 if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
466 FAT_cache_remove_hash(bp);
472 move_to_lru(bp, &p_fs->FAT_cache_lru_list);
476 return bp->buf_bh->b_data;
479 void FAT_modify(struct super_block *sb, sector_t sec)
481 struct buf_cache_t *bp;
483 bp = FAT_cache_find(sb, sec);
485 sector_write(sb, sec, bp->buf_bh, 0);
488 void FAT_release_all(struct super_block *sb)
490 struct buf_cache_t *bp;
491 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
495 bp = p_fs->FAT_cache_lru_list.next;
496 while (bp != &p_fs->FAT_cache_lru_list) {
497 if (bp->drv == p_fs->drv) {
503 __brelse(bp->buf_bh);
513 void FAT_sync(struct super_block *sb)
515 struct buf_cache_t *bp;
516 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
520 bp = p_fs->FAT_cache_lru_list.next;
521 while (bp != &p_fs->FAT_cache_lru_list) {
522 if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) {
523 sync_dirty_buffer(bp->buf_bh);
524 bp->flag &= ~(DIRTYBIT);
532 static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec)
535 struct buf_cache_t *bp, *hp;
536 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
538 off = (sec + (sec >> p_fs->sectors_per_clu_bits)) &
539 (BUF_CACHE_HASH_SIZE - 1);
541 hp = &p_fs->buf_cache_hash_list[off];
542 for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) {
543 if ((bp->drv == p_fs->drv) && (bp->sec == sec)) {
544 touch_buffer(bp->buf_bh);
551 static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec)
553 struct buf_cache_t *bp;
554 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
556 bp = p_fs->buf_cache_lru_list.prev;
557 while (bp->flag & LOCKBIT)
560 move_to_mru(bp, &p_fs->buf_cache_lru_list);
564 static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
566 struct buf_cache_t *bp;
567 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
569 bp = buf_cache_find(sb, sec);
571 move_to_mru(bp, &p_fs->buf_cache_lru_list);
572 return bp->buf_bh->b_data;
575 bp = buf_cache_get(sb, sec);
577 buf_cache_remove_hash(bp);
583 buf_cache_insert_hash(sb, bp);
585 if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
586 buf_cache_remove_hash(bp);
592 move_to_lru(bp, &p_fs->buf_cache_lru_list);
596 return bp->buf_bh->b_data;
599 u8 *buf_getblk(struct super_block *sb, sector_t sec)
604 buf = __buf_getblk(sb, sec);
610 void buf_modify(struct super_block *sb, sector_t sec)
612 struct buf_cache_t *bp;
616 bp = buf_cache_find(sb, sec);
618 sector_write(sb, sec, bp->buf_bh, 0);
620 WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
621 (unsigned long long)sec);
626 void buf_lock(struct super_block *sb, sector_t sec)
628 struct buf_cache_t *bp;
632 bp = buf_cache_find(sb, sec);
636 WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
637 (unsigned long long)sec);
642 void buf_unlock(struct super_block *sb, sector_t sec)
644 struct buf_cache_t *bp;
648 bp = buf_cache_find(sb, sec);
650 bp->flag &= ~(LOCKBIT);
652 WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
653 (unsigned long long)sec);
658 void buf_release(struct super_block *sb, sector_t sec)
660 struct buf_cache_t *bp;
661 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
665 bp = buf_cache_find(sb, sec);
672 __brelse(bp->buf_bh);
676 move_to_lru(bp, &p_fs->buf_cache_lru_list);
682 void buf_release_all(struct super_block *sb)
684 struct buf_cache_t *bp;
685 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
689 bp = p_fs->buf_cache_lru_list.next;
690 while (bp != &p_fs->buf_cache_lru_list) {
691 if (bp->drv == p_fs->drv) {
697 __brelse(bp->buf_bh);
707 void buf_sync(struct super_block *sb)
709 struct buf_cache_t *bp;
710 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
714 bp = p_fs->buf_cache_lru_list.next;
715 while (bp != &p_fs->buf_cache_lru_list) {
716 if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) {
717 sync_dirty_buffer(bp->buf_bh);
718 bp->flag &= ~(DIRTYBIT);