Merge tag 'drm/tegra/for-5.6-rc1-fixes' of git://anongit.freedesktop.org/tegra/linux...
[platform/kernel/linux-starfive.git] / drivers / staging / exfat / exfat_cache.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
4  */
5
6 #include <linux/buffer_head.h>
7 #include <linux/fs.h>
8 #include <linux/mutex.h>
9 #include "exfat.h"
10
11 #define LOCKBIT         0x01
12 #define DIRTYBIT        0x02
13
14 /* Local variables */
15 static DEFINE_MUTEX(f_mutex);
16 static DEFINE_MUTEX(b_mutex);
17
18 static struct buf_cache_t *FAT_cache_find(struct super_block *sb, sector_t sec)
19 {
20         s32 off;
21         struct buf_cache_t *bp, *hp;
22         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
23
24         off = (sec +
25                (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1);
26
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)) {
30                         WARN(!bp->buf_bh,
31                              "[EXFAT] FAT_cache has no bh. It will make system panic.\n");
32
33                         touch_buffer(bp->buf_bh);
34                         return bp;
35                 }
36         }
37         return NULL;
38 }
39
40 static void push_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list)
41 {
42         bp->next = list->next;
43         bp->prev = list;
44         list->next->prev = bp;
45         list->next = bp;
46 }
47
48 static void push_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list)
49 {
50         bp->prev = list->prev;
51         bp->next = list;
52         list->prev->next = bp;
53         list->prev = bp;
54 }
55
56 static void move_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list)
57 {
58         bp->prev->next = bp->next;
59         bp->next->prev = bp->prev;
60         push_to_mru(bp, list);
61 }
62
63 static void move_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list)
64 {
65         bp->prev->next = bp->next;
66         bp->next->prev = bp->prev;
67         push_to_lru(bp, list);
68 }
69
70 static struct buf_cache_t *FAT_cache_get(struct super_block *sb, sector_t sec)
71 {
72         struct buf_cache_t *bp;
73         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
74
75         bp = p_fs->FAT_cache_lru_list.prev;
76
77         move_to_mru(bp, &p_fs->FAT_cache_lru_list);
78         return bp;
79 }
80
81 static void FAT_cache_insert_hash(struct super_block *sb,
82                                   struct buf_cache_t *bp)
83 {
84         s32 off;
85         struct buf_cache_t *hp;
86         struct fs_info_t *p_fs;
87
88         p_fs = &(EXFAT_SB(sb)->fs_info);
89         off = (bp->sec +
90                (bp->sec >> p_fs->sectors_per_clu_bits)) &
91                 (FAT_CACHE_HASH_SIZE - 1);
92
93         hp = &p_fs->FAT_cache_hash_list[off];
94         bp->hash_next = hp->hash_next;
95         bp->hash_prev = hp;
96         hp->hash_next->hash_prev = bp;
97         hp->hash_next = bp;
98 }
99
100 static void FAT_cache_remove_hash(struct buf_cache_t *bp)
101 {
102         (bp->hash_prev)->hash_next = bp->hash_next;
103         (bp->hash_next)->hash_prev = bp->hash_prev;
104 }
105
106 static void buf_cache_insert_hash(struct super_block *sb,
107                                   struct buf_cache_t *bp)
108 {
109         s32 off;
110         struct buf_cache_t *hp;
111         struct fs_info_t *p_fs;
112
113         p_fs = &(EXFAT_SB(sb)->fs_info);
114         off = (bp->sec +
115                (bp->sec >> p_fs->sectors_per_clu_bits)) &
116                 (BUF_CACHE_HASH_SIZE - 1);
117
118         hp = &p_fs->buf_cache_hash_list[off];
119         bp->hash_next = hp->hash_next;
120         bp->hash_prev = hp;
121         hp->hash_next->hash_prev = bp;
122         hp->hash_next = bp;
123 }
124
125 static void buf_cache_remove_hash(struct buf_cache_t *bp)
126 {
127         (bp->hash_prev)->hash_next = bp->hash_next;
128         (bp->hash_next)->hash_prev = bp->hash_prev;
129 }
130
131 void exfat_buf_init(struct super_block *sb)
132 {
133         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
134
135         int i;
136
137         /* LRU list */
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;
140
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);
150         }
151
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;
154
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);
164         }
165
166         /* HASH 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];
174         }
175
176         for (i = 0; i < FAT_CACHE_SIZE; i++)
177                 FAT_cache_insert_hash(sb, &p_fs->FAT_cache_array[i]);
178
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];
186         }
187
188         for (i = 0; i < BUF_CACHE_SIZE; i++)
189                 buf_cache_insert_hash(sb, &p_fs->buf_cache_array[i]);
190 }
191
192 void exfat_buf_shutdown(struct super_block *sb)
193 {
194 }
195
196 static int __exfat_fat_read(struct super_block *sb, u32 loc, u32 *content)
197 {
198         s32 off;
199         u32 _content;
200         sector_t sec;
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);
204
205         sec = p_fs->FAT1_start_sector +
206                 (loc >> (p_bd->sector_size_bits - 2));
207         off = (loc << 2) & p_bd->sector_size_mask;
208
209         fat_sector = exfat_fat_getblk(sb, sec);
210         if (!fat_sector)
211                 return -1;
212
213         fat_entry = &fat_sector[off];
214         _content = GET32_A(fat_entry);
215
216         if (_content >= CLUSTER_32(0xFFFFFFF8)) {
217                 *content = CLUSTER_32(~0);
218                 return 0;
219         }
220         *content = CLUSTER_32(_content);
221         return 0;
222 }
223
224 /* in : sb, loc
225  * out: content
226  * returns 0 on success
227  *            -1 on error
228  */
229 int exfat_fat_read(struct super_block *sb, u32 loc, u32 *content)
230 {
231         s32 ret;
232
233         mutex_lock(&f_mutex);
234         ret = __exfat_fat_read(sb, loc, content);
235         mutex_unlock(&f_mutex);
236
237         return ret;
238 }
239
240 static s32 __exfat_fat_write(struct super_block *sb, u32 loc, u32 content)
241 {
242         s32 off;
243         sector_t sec;
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);
247
248         sec = p_fs->FAT1_start_sector + (loc >>
249                                          (p_bd->sector_size_bits - 2));
250         off = (loc << 2) & p_bd->sector_size_mask;
251
252         fat_sector = exfat_fat_getblk(sb, sec);
253         if (!fat_sector)
254                 return -1;
255
256         fat_entry = &fat_sector[off];
257
258         SET32_A(fat_entry, content);
259
260         exfat_fat_modify(sb, sec);
261         return 0;
262 }
263
264 int exfat_fat_write(struct super_block *sb, u32 loc, u32 content)
265 {
266         s32 ret;
267
268         mutex_lock(&f_mutex);
269         ret = __exfat_fat_write(sb, loc, content);
270         mutex_unlock(&f_mutex);
271
272         return ret;
273 }
274
275 u8 *exfat_fat_getblk(struct super_block *sb, sector_t sec)
276 {
277         struct buf_cache_t *bp;
278         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
279
280         bp = FAT_cache_find(sb, sec);
281         if (bp) {
282                 move_to_mru(bp, &p_fs->FAT_cache_lru_list);
283                 return bp->buf_bh->b_data;
284         }
285
286         bp = FAT_cache_get(sb, sec);
287
288         FAT_cache_remove_hash(bp);
289
290         bp->drv = p_fs->drv;
291         bp->sec = sec;
292         bp->flag = 0;
293
294         FAT_cache_insert_hash(sb, bp);
295
296         if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) {
297                 FAT_cache_remove_hash(bp);
298                 bp->drv = -1;
299                 bp->sec = ~0;
300                 bp->flag = 0;
301                 bp->buf_bh = NULL;
302
303                 move_to_lru(bp, &p_fs->FAT_cache_lru_list);
304                 return NULL;
305         }
306
307         return bp->buf_bh->b_data;
308 }
309
310 void exfat_fat_modify(struct super_block *sb, sector_t sec)
311 {
312         struct buf_cache_t *bp;
313
314         bp = FAT_cache_find(sb, sec);
315         if (bp)
316                 sector_write(sb, sec, bp->buf_bh, 0);
317 }
318
319 void exfat_fat_release_all(struct super_block *sb)
320 {
321         struct buf_cache_t *bp;
322         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
323
324         mutex_lock(&f_mutex);
325
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) {
329                         bp->drv = -1;
330                         bp->sec = ~0;
331                         bp->flag = 0;
332
333                         if (bp->buf_bh) {
334                                 __brelse(bp->buf_bh);
335                                 bp->buf_bh = NULL;
336                         }
337                 }
338                 bp = bp->next;
339         }
340
341         mutex_unlock(&f_mutex);
342 }
343
344 void exfat_fat_sync(struct super_block *sb)
345 {
346         struct buf_cache_t *bp;
347         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
348
349         mutex_lock(&f_mutex);
350
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);
356                 }
357                 bp = bp->next;
358         }
359
360         mutex_unlock(&f_mutex);
361 }
362
363 static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec)
364 {
365         s32 off;
366         struct buf_cache_t *bp, *hp;
367         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
368
369         off = (sec + (sec >> p_fs->sectors_per_clu_bits)) &
370                 (BUF_CACHE_HASH_SIZE - 1);
371
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);
376                         return bp;
377                 }
378         }
379         return NULL;
380 }
381
382 static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec)
383 {
384         struct buf_cache_t *bp;
385         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
386
387         bp = p_fs->buf_cache_lru_list.prev;
388         while (bp->flag & LOCKBIT)
389                 bp = bp->prev;
390
391         move_to_mru(bp, &p_fs->buf_cache_lru_list);
392         return bp;
393 }
394
395 static u8 *__exfat_buf_getblk(struct super_block *sb, sector_t sec)
396 {
397         struct buf_cache_t *bp;
398         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
399
400         bp = buf_cache_find(sb, sec);
401         if (bp) {
402                 move_to_mru(bp, &p_fs->buf_cache_lru_list);
403                 return bp->buf_bh->b_data;
404         }
405
406         bp = buf_cache_get(sb, sec);
407
408         buf_cache_remove_hash(bp);
409
410         bp->drv = p_fs->drv;
411         bp->sec = sec;
412         bp->flag = 0;
413
414         buf_cache_insert_hash(sb, bp);
415
416         if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) {
417                 buf_cache_remove_hash(bp);
418                 bp->drv = -1;
419                 bp->sec = ~0;
420                 bp->flag = 0;
421                 bp->buf_bh = NULL;
422
423                 move_to_lru(bp, &p_fs->buf_cache_lru_list);
424                 return NULL;
425         }
426
427         return bp->buf_bh->b_data;
428 }
429
430 u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec)
431 {
432         u8 *buf;
433
434         mutex_lock(&b_mutex);
435         buf = __exfat_buf_getblk(sb, sec);
436         mutex_unlock(&b_mutex);
437
438         return buf;
439 }
440
441 void exfat_buf_modify(struct super_block *sb, sector_t sec)
442 {
443         struct buf_cache_t *bp;
444
445         mutex_lock(&b_mutex);
446
447         bp = buf_cache_find(sb, sec);
448         if (likely(bp))
449                 sector_write(sb, sec, bp->buf_bh, 0);
450
451         WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
452              (unsigned long long)sec);
453
454         mutex_unlock(&b_mutex);
455 }
456
457 void exfat_buf_lock(struct super_block *sb, sector_t sec)
458 {
459         struct buf_cache_t *bp;
460
461         mutex_lock(&b_mutex);
462
463         bp = buf_cache_find(sb, sec);
464         if (likely(bp))
465                 bp->flag |= LOCKBIT;
466
467         WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
468              (unsigned long long)sec);
469
470         mutex_unlock(&b_mutex);
471 }
472
473 void exfat_buf_unlock(struct super_block *sb, sector_t sec)
474 {
475         struct buf_cache_t *bp;
476
477         mutex_lock(&b_mutex);
478
479         bp = buf_cache_find(sb, sec);
480         if (likely(bp))
481                 bp->flag &= ~(LOCKBIT);
482
483         WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
484              (unsigned long long)sec);
485
486         mutex_unlock(&b_mutex);
487 }
488
489 void exfat_buf_release(struct super_block *sb, sector_t sec)
490 {
491         struct buf_cache_t *bp;
492         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
493
494         mutex_lock(&b_mutex);
495
496         bp = buf_cache_find(sb, sec);
497         if (likely(bp)) {
498                 bp->drv = -1;
499                 bp->sec = ~0;
500                 bp->flag = 0;
501
502                 if (bp->buf_bh) {
503                         __brelse(bp->buf_bh);
504                         bp->buf_bh = NULL;
505                 }
506
507                 move_to_lru(bp, &p_fs->buf_cache_lru_list);
508         }
509
510         mutex_unlock(&b_mutex);
511 }
512
513 void exfat_buf_release_all(struct super_block *sb)
514 {
515         struct buf_cache_t *bp;
516         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
517
518         mutex_lock(&b_mutex);
519
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) {
523                         bp->drv = -1;
524                         bp->sec = ~0;
525                         bp->flag = 0;
526
527                         if (bp->buf_bh) {
528                                 __brelse(bp->buf_bh);
529                                 bp->buf_bh = NULL;
530                         }
531                 }
532                 bp = bp->next;
533         }
534
535         mutex_unlock(&b_mutex);
536 }
537
538 void exfat_buf_sync(struct super_block *sb)
539 {
540         struct buf_cache_t *bp;
541         struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
542
543         mutex_lock(&b_mutex);
544
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);
550                 }
551                 bp = bp->next;
552         }
553
554         mutex_unlock(&b_mutex);
555 }