This source file includes following definitions.
- FAT_cache_find
- push_to_mru
- push_to_lru
- move_to_mru
- move_to_lru
- FAT_cache_get
- FAT_cache_insert_hash
- FAT_cache_remove_hash
- buf_cache_insert_hash
- buf_cache_remove_hash
- buf_init
- buf_shutdown
- __FAT_read
- FAT_read
- __FAT_write
- FAT_write
- FAT_getblk
- FAT_modify
- FAT_release_all
- FAT_sync
- buf_cache_find
- buf_cache_get
- __buf_getblk
- buf_getblk
- buf_modify
- buf_lock
- buf_unlock
- buf_release
- buf_release_all
- buf_sync
1
2
3
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
15 static DEFINE_SEMAPHORE(f_sem);
16 static DEFINE_SEMAPHORE(b_sem);
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 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
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
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 buf_shutdown(struct super_block *sb)
193 {
194 }
195
196 static int __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 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;
209
210 if (off == (p_bd->sector_size - 1)) {
211 fat_sector = FAT_getblk(sb, sec);
212 if (!fat_sector)
213 return -1;
214
215 _content = (u32)fat_sector[off];
216
217 fat_sector = FAT_getblk(sb, ++sec);
218 if (!fat_sector)
219 return -1;
220
221 _content |= (u32)fat_sector[0] << 8;
222 } else {
223 fat_sector = FAT_getblk(sb, sec);
224 if (!fat_sector)
225 return -1;
226
227 fat_entry = &fat_sector[off];
228 _content = GET16(fat_entry);
229 }
230
231 if (loc & 1)
232 _content >>= 4;
233
234 _content &= 0x00000FFF;
235
236 if (_content >= CLUSTER_16(0x0FF8)) {
237 *content = CLUSTER_32(~0);
238 return 0;
239 }
240 *content = CLUSTER_32(_content);
241 return 0;
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;
246
247 fat_sector = FAT_getblk(sb, sec);
248 if (!fat_sector)
249 return -1;
250
251 fat_entry = &fat_sector[off];
252
253 _content = GET16_A(fat_entry);
254
255 _content &= 0x0000FFFF;
256
257 if (_content >= CLUSTER_16(0xFFF8)) {
258 *content = CLUSTER_32(~0);
259 return 0;
260 }
261 *content = CLUSTER_32(_content);
262 return 0;
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;
267
268 fat_sector = FAT_getblk(sb, sec);
269 if (!fat_sector)
270 return -1;
271
272 fat_entry = &fat_sector[off];
273
274 _content = GET32_A(fat_entry);
275
276 _content &= 0x0FFFFFFF;
277
278 if (_content >= CLUSTER_32(0x0FFFFFF8)) {
279 *content = CLUSTER_32(~0);
280 return 0;
281 }
282 *content = CLUSTER_32(_content);
283 return 0;
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;
288
289 fat_sector = FAT_getblk(sb, sec);
290 if (!fat_sector)
291 return -1;
292
293 fat_entry = &fat_sector[off];
294 _content = GET32_A(fat_entry);
295
296 if (_content >= CLUSTER_32(0xFFFFFFF8)) {
297 *content = CLUSTER_32(~0);
298 return 0;
299 }
300 *content = CLUSTER_32(_content);
301 return 0;
302 }
303
304
305 *content = CLUSTER_32(~0);
306 return 0;
307 }
308
309
310
311
312
313
314 int FAT_read(struct super_block *sb, u32 loc, u32 *content)
315 {
316 s32 ret;
317
318 down(&f_sem);
319 ret = __FAT_read(sb, loc, content);
320 up(&f_sem);
321
322 return ret;
323 }
324
325 static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
326 {
327 s32 off;
328 sector_t sec;
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);
332
333 if (p_fs->vol_type == FAT12) {
334 content &= 0x00000FFF;
335
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;
339
340 fat_sector = FAT_getblk(sb, sec);
341 if (!fat_sector)
342 return -1;
343
344 if (loc & 1) {
345 content <<= 4;
346
347 if (off == (p_bd->sector_size - 1)) {
348 fat_sector[off] = (u8)(content |
349 (fat_sector[off] &
350 0x0F));
351 FAT_modify(sb, sec);
352
353 fat_sector = FAT_getblk(sb, ++sec);
354 if (!fat_sector)
355 return -1;
356
357 fat_sector[0] = (u8)(content >> 8);
358 } else {
359 fat_entry = &fat_sector[off];
360 content |= GET16(fat_entry) & 0x000F;
361
362 SET16(fat_entry, content);
363 }
364 } else {
365 fat_sector[off] = (u8)(content);
366
367 if (off == (p_bd->sector_size - 1)) {
368 fat_sector[off] = (u8)(content);
369 FAT_modify(sb, sec);
370
371 fat_sector = FAT_getblk(sb, ++sec);
372 if (!fat_sector)
373 return -1;
374 fat_sector[0] = (u8)((fat_sector[0] & 0xF0) |
375 (content >> 8));
376 } else {
377 fat_entry = &fat_sector[off];
378 content |= GET16(fat_entry) & 0xF000;
379
380 SET16(fat_entry, content);
381 }
382 }
383 }
384
385 else if (p_fs->vol_type == FAT16) {
386 content &= 0x0000FFFF;
387
388 sec = p_fs->FAT1_start_sector + (loc >>
389 (p_bd->sector_size_bits - 1));
390 off = (loc << 1) & p_bd->sector_size_mask;
391
392 fat_sector = FAT_getblk(sb, sec);
393 if (!fat_sector)
394 return -1;
395
396 fat_entry = &fat_sector[off];
397
398 SET16_A(fat_entry, content);
399 } else if (p_fs->vol_type == FAT32) {
400 content &= 0x0FFFFFFF;
401
402 sec = p_fs->FAT1_start_sector + (loc >>
403 (p_bd->sector_size_bits - 2));
404 off = (loc << 2) & p_bd->sector_size_mask;
405
406 fat_sector = FAT_getblk(sb, sec);
407 if (!fat_sector)
408 return -1;
409
410 fat_entry = &fat_sector[off];
411
412 content |= GET32_A(fat_entry) & 0xF0000000;
413
414 SET32_A(fat_entry, content);
415 } else {
416 sec = p_fs->FAT1_start_sector + (loc >>
417 (p_bd->sector_size_bits - 2));
418 off = (loc << 2) & p_bd->sector_size_mask;
419
420 fat_sector = FAT_getblk(sb, sec);
421 if (!fat_sector)
422 return -1;
423
424 fat_entry = &fat_sector[off];
425
426 SET32_A(fat_entry, content);
427 }
428
429 FAT_modify(sb, sec);
430 return 0;
431 }
432
433 int FAT_write(struct super_block *sb, u32 loc, u32 content)
434 {
435 s32 ret;
436
437 down(&f_sem);
438 ret = __FAT_write(sb, loc, content);
439 up(&f_sem);
440
441 return ret;
442 }
443
444 u8 *FAT_getblk(struct super_block *sb, sector_t sec)
445 {
446 struct buf_cache_t *bp;
447 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
448
449 bp = FAT_cache_find(sb, sec);
450 if (bp) {
451 move_to_mru(bp, &p_fs->FAT_cache_lru_list);
452 return bp->buf_bh->b_data;
453 }
454
455 bp = FAT_cache_get(sb, sec);
456
457 FAT_cache_remove_hash(bp);
458
459 bp->drv = p_fs->drv;
460 bp->sec = sec;
461 bp->flag = 0;
462
463 FAT_cache_insert_hash(sb, bp);
464
465 if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
466 FAT_cache_remove_hash(bp);
467 bp->drv = -1;
468 bp->sec = ~0;
469 bp->flag = 0;
470 bp->buf_bh = NULL;
471
472 move_to_lru(bp, &p_fs->FAT_cache_lru_list);
473 return NULL;
474 }
475
476 return bp->buf_bh->b_data;
477 }
478
479 void FAT_modify(struct super_block *sb, sector_t sec)
480 {
481 struct buf_cache_t *bp;
482
483 bp = FAT_cache_find(sb, sec);
484 if (bp)
485 sector_write(sb, sec, bp->buf_bh, 0);
486 }
487
488 void FAT_release_all(struct super_block *sb)
489 {
490 struct buf_cache_t *bp;
491 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
492
493 down(&f_sem);
494
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) {
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 bp = bp->next;
508 }
509
510 up(&f_sem);
511 }
512
513 void FAT_sync(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 down(&f_sem);
519
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);
525 }
526 bp = bp->next;
527 }
528
529 up(&f_sem);
530 }
531
532 static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec)
533 {
534 s32 off;
535 struct buf_cache_t *bp, *hp;
536 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
537
538 off = (sec + (sec >> p_fs->sectors_per_clu_bits)) &
539 (BUF_CACHE_HASH_SIZE - 1);
540
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);
545 return bp;
546 }
547 }
548 return NULL;
549 }
550
551 static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec)
552 {
553 struct buf_cache_t *bp;
554 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
555
556 bp = p_fs->buf_cache_lru_list.prev;
557 while (bp->flag & LOCKBIT)
558 bp = bp->prev;
559
560 move_to_mru(bp, &p_fs->buf_cache_lru_list);
561 return bp;
562 }
563
564 static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
565 {
566 struct buf_cache_t *bp;
567 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
568
569 bp = buf_cache_find(sb, sec);
570 if (bp) {
571 move_to_mru(bp, &p_fs->buf_cache_lru_list);
572 return bp->buf_bh->b_data;
573 }
574
575 bp = buf_cache_get(sb, sec);
576
577 buf_cache_remove_hash(bp);
578
579 bp->drv = p_fs->drv;
580 bp->sec = sec;
581 bp->flag = 0;
582
583 buf_cache_insert_hash(sb, bp);
584
585 if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
586 buf_cache_remove_hash(bp);
587 bp->drv = -1;
588 bp->sec = ~0;
589 bp->flag = 0;
590 bp->buf_bh = NULL;
591
592 move_to_lru(bp, &p_fs->buf_cache_lru_list);
593 return NULL;
594 }
595
596 return bp->buf_bh->b_data;
597 }
598
599 u8 *buf_getblk(struct super_block *sb, sector_t sec)
600 {
601 u8 *buf;
602
603 down(&b_sem);
604 buf = __buf_getblk(sb, sec);
605 up(&b_sem);
606
607 return buf;
608 }
609
610 void buf_modify(struct super_block *sb, sector_t sec)
611 {
612 struct buf_cache_t *bp;
613
614 down(&b_sem);
615
616 bp = buf_cache_find(sb, sec);
617 if (likely(bp))
618 sector_write(sb, sec, bp->buf_bh, 0);
619
620 WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
621 (unsigned long long)sec);
622
623 up(&b_sem);
624 }
625
626 void buf_lock(struct super_block *sb, sector_t sec)
627 {
628 struct buf_cache_t *bp;
629
630 down(&b_sem);
631
632 bp = buf_cache_find(sb, sec);
633 if (likely(bp))
634 bp->flag |= LOCKBIT;
635
636 WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
637 (unsigned long long)sec);
638
639 up(&b_sem);
640 }
641
642 void buf_unlock(struct super_block *sb, sector_t sec)
643 {
644 struct buf_cache_t *bp;
645
646 down(&b_sem);
647
648 bp = buf_cache_find(sb, sec);
649 if (likely(bp))
650 bp->flag &= ~(LOCKBIT);
651
652 WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
653 (unsigned long long)sec);
654
655 up(&b_sem);
656 }
657
658 void buf_release(struct super_block *sb, sector_t sec)
659 {
660 struct buf_cache_t *bp;
661 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
662
663 down(&b_sem);
664
665 bp = buf_cache_find(sb, sec);
666 if (likely(bp)) {
667 bp->drv = -1;
668 bp->sec = ~0;
669 bp->flag = 0;
670
671 if (bp->buf_bh) {
672 __brelse(bp->buf_bh);
673 bp->buf_bh = NULL;
674 }
675
676 move_to_lru(bp, &p_fs->buf_cache_lru_list);
677 }
678
679 up(&b_sem);
680 }
681
682 void buf_release_all(struct super_block *sb)
683 {
684 struct buf_cache_t *bp;
685 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
686
687 down(&b_sem);
688
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) {
692 bp->drv = -1;
693 bp->sec = ~0;
694 bp->flag = 0;
695
696 if (bp->buf_bh) {
697 __brelse(bp->buf_bh);
698 bp->buf_bh = NULL;
699 }
700 }
701 bp = bp->next;
702 }
703
704 up(&b_sem);
705 }
706
707 void buf_sync(struct super_block *sb)
708 {
709 struct buf_cache_t *bp;
710 struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
711
712 down(&b_sem);
713
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);
719 }
720 bp = bp->next;
721 }
722
723 up(&b_sem);
724 }