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_MUTEX(f_mutex);
16 static DEFINE_MUTEX(b_mutex);
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 exfat_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 exfat_buf_shutdown(struct super_block *sb)
196 static int __exfat_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 sec = p_fs->FAT1_start_sector +
206 (loc >> (p_bd->sector_size_bits - 2));
207 off = (loc << 2) & p_bd->sector_size_mask;
209 fat_sector = exfat_fat_getblk(sb, sec);
213 fat_entry = &fat_sector[off];
214 _content = GET32_A(fat_entry);
216 if (_content >= CLUSTER_32(0xFFFFFFF8)) {
217 *content = CLUSTER_32(~0);
220 *content = CLUSTER_32(_content);
226 * returns 0 on success
229 int exfat_fat_read(struct super_block *sb, u32 loc, u32 *content)
233 mutex_lock(&f_mutex);
234 ret = __exfat_fat_read(sb, loc, content);
235 mutex_unlock(&f_mutex);
240 static s32 __exfat_fat_write(struct super_block *sb, u32 loc, u32 content)
244 u8 *fat_sector, *fat_entry;
245 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
246 struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
248 sec = p_fs->FAT1_start_sector + (loc >>
249 (p_bd->sector_size_bits - 2));
250 off = (loc << 2) & p_bd->sector_size_mask;
252 fat_sector = exfat_fat_getblk(sb, sec);
256 fat_entry = &fat_sector[off];
258 SET32_A(fat_entry, content);
260 exfat_fat_modify(sb, sec);
264 int exfat_fat_write(struct super_block *sb, u32 loc, u32 content)
268 mutex_lock(&f_mutex);
269 ret = __exfat_fat_write(sb, loc, content);
270 mutex_unlock(&f_mutex);
275 u8 *exfat_fat_getblk(struct super_block *sb, sector_t sec)
277 struct buf_cache_t *bp;
278 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
280 bp = FAT_cache_find(sb, sec);
282 move_to_mru(bp, &p_fs->FAT_cache_lru_list);
283 return bp->buf_bh->b_data;
286 bp = FAT_cache_get(sb, sec);
288 FAT_cache_remove_hash(bp);
294 FAT_cache_insert_hash(sb, bp);
296 if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) {
297 FAT_cache_remove_hash(bp);
303 move_to_lru(bp, &p_fs->FAT_cache_lru_list);
307 return bp->buf_bh->b_data;
310 void exfat_fat_modify(struct super_block *sb, sector_t sec)
312 struct buf_cache_t *bp;
314 bp = FAT_cache_find(sb, sec);
316 sector_write(sb, sec, bp->buf_bh, 0);
319 void exfat_fat_release_all(struct super_block *sb)
321 struct buf_cache_t *bp;
322 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
324 mutex_lock(&f_mutex);
326 bp = p_fs->FAT_cache_lru_list.next;
327 while (bp != &p_fs->FAT_cache_lru_list) {
328 if (bp->drv == p_fs->drv) {
334 __brelse(bp->buf_bh);
341 mutex_unlock(&f_mutex);
344 void exfat_fat_sync(struct super_block *sb)
346 struct buf_cache_t *bp;
347 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
349 mutex_lock(&f_mutex);
351 bp = p_fs->FAT_cache_lru_list.next;
352 while (bp != &p_fs->FAT_cache_lru_list) {
353 if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) {
354 sync_dirty_buffer(bp->buf_bh);
355 bp->flag &= ~(DIRTYBIT);
360 mutex_unlock(&f_mutex);
363 static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec)
366 struct buf_cache_t *bp, *hp;
367 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
369 off = (sec + (sec >> p_fs->sectors_per_clu_bits)) &
370 (BUF_CACHE_HASH_SIZE - 1);
372 hp = &p_fs->buf_cache_hash_list[off];
373 for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) {
374 if ((bp->drv == p_fs->drv) && (bp->sec == sec)) {
375 touch_buffer(bp->buf_bh);
382 static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec)
384 struct buf_cache_t *bp;
385 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
387 bp = p_fs->buf_cache_lru_list.prev;
388 while (bp->flag & LOCKBIT)
391 move_to_mru(bp, &p_fs->buf_cache_lru_list);
395 static u8 *__exfat_buf_getblk(struct super_block *sb, sector_t sec)
397 struct buf_cache_t *bp;
398 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
400 bp = buf_cache_find(sb, sec);
402 move_to_mru(bp, &p_fs->buf_cache_lru_list);
403 return bp->buf_bh->b_data;
406 bp = buf_cache_get(sb, sec);
408 buf_cache_remove_hash(bp);
414 buf_cache_insert_hash(sb, bp);
416 if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) {
417 buf_cache_remove_hash(bp);
423 move_to_lru(bp, &p_fs->buf_cache_lru_list);
427 return bp->buf_bh->b_data;
430 u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec)
434 mutex_lock(&b_mutex);
435 buf = __exfat_buf_getblk(sb, sec);
436 mutex_unlock(&b_mutex);
441 void exfat_buf_modify(struct super_block *sb, sector_t sec)
443 struct buf_cache_t *bp;
445 mutex_lock(&b_mutex);
447 bp = buf_cache_find(sb, sec);
449 sector_write(sb, sec, bp->buf_bh, 0);
451 WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
452 (unsigned long long)sec);
454 mutex_unlock(&b_mutex);
457 void exfat_buf_lock(struct super_block *sb, sector_t sec)
459 struct buf_cache_t *bp;
461 mutex_lock(&b_mutex);
463 bp = buf_cache_find(sb, sec);
467 WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
468 (unsigned long long)sec);
470 mutex_unlock(&b_mutex);
473 void exfat_buf_unlock(struct super_block *sb, sector_t sec)
475 struct buf_cache_t *bp;
477 mutex_lock(&b_mutex);
479 bp = buf_cache_find(sb, sec);
481 bp->flag &= ~(LOCKBIT);
483 WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
484 (unsigned long long)sec);
486 mutex_unlock(&b_mutex);
489 void exfat_buf_release(struct super_block *sb, sector_t sec)
491 struct buf_cache_t *bp;
492 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
494 mutex_lock(&b_mutex);
496 bp = buf_cache_find(sb, sec);
503 __brelse(bp->buf_bh);
507 move_to_lru(bp, &p_fs->buf_cache_lru_list);
510 mutex_unlock(&b_mutex);
513 void exfat_buf_release_all(struct super_block *sb)
515 struct buf_cache_t *bp;
516 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
518 mutex_lock(&b_mutex);
520 bp = p_fs->buf_cache_lru_list.next;
521 while (bp != &p_fs->buf_cache_lru_list) {
522 if (bp->drv == p_fs->drv) {
528 __brelse(bp->buf_bh);
535 mutex_unlock(&b_mutex);
538 void exfat_buf_sync(struct super_block *sb)
540 struct buf_cache_t *bp;
541 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
543 mutex_lock(&b_mutex);
545 bp = p_fs->buf_cache_lru_list.next;
546 while (bp != &p_fs->buf_cache_lru_list) {
547 if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) {
548 sync_dirty_buffer(bp->buf_bh);
549 bp->flag &= ~(DIRTYBIT);
554 mutex_unlock(&b_mutex);