4 * Written 1992,1993 by Werner Almesberger
6 * Mar 1999. AV. Changed cache, so that it uses the starting cluster instead
8 * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
11 #include <linux/msdos_fs.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
15 #include <linux/stat.h>
16 #include <linux/fat_cvf.h>
21 # define PRINTK(x) printk x
26 static struct fat_cache
*fat_cache
,cache
[FAT_CACHE
];
28 /* Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
29 new_value is != -1, that FAT entry is replaced by it. */
31 int fat_access(struct super_block
*sb
,int nr
,int new_value
)
33 return MSDOS_SB(sb
)->cvf_format
->fat_access(sb
,nr
,new_value
);
36 int fat_bmap(struct inode
*inode
,int sector
)
38 return MSDOS_SB(inode
->i_sb
)->cvf_format
->cvf_bmap(inode
,sector
);
41 int default_fat_access(struct super_block
*sb
,int nr
,int new_value
)
43 struct buffer_head
*bh
,*bh2
,*c_bh
,*c_bh2
;
44 unsigned char *p_first
,*p_last
;
45 int copy
,first
,last
,next
,b
;
47 if ((unsigned) (nr
-2) >= MSDOS_SB(sb
)->clusters
)
49 if (MSDOS_SB(sb
)->fat_bits
== 32) {
51 } else if (MSDOS_SB(sb
)->fat_bits
== 16) {
57 b
= MSDOS_SB(sb
)->fat_start
+ (first
>> SECTOR_BITS
);
58 if (!(bh
= fat_bread(sb
, b
))) {
59 printk("bread in fat_access failed\n");
62 if ((first
>> SECTOR_BITS
) == (last
>> SECTOR_BITS
)) {
65 if (!(bh2
= fat_bread(sb
, b
+1))) {
67 printk("2nd bread in fat_access failed\n");
71 if (MSDOS_SB(sb
)->fat_bits
== 32) {
72 p_first
= p_last
= NULL
; /* GCC needs that stuff */
73 next
= CF_LE_L(((unsigned long *) bh
->b_data
)[(first
&
74 (SECTOR_SIZE
-1)) >> 2]);
75 /* Fscking Microsoft marketing department. Their "32" is 28. */
77 if (next
>= 0xffffff7) next
= -1;
78 PRINTK(("fat_bread: 0x%x, nr=0x%x, first=0x%x, next=0x%d\n", b
, nr
, first
, next
));
80 } else if (MSDOS_SB(sb
)->fat_bits
== 16) {
81 p_first
= p_last
= NULL
; /* GCC needs that stuff */
82 next
= CF_LE_W(((unsigned short *) bh
->b_data
)[(first
&
83 (SECTOR_SIZE
-1)) >> 1]);
84 if (next
>= 0xfff7) next
= -1;
86 p_first
= &((unsigned char *) bh
->b_data
)[first
& (SECTOR_SIZE
-1)];
87 p_last
= &((unsigned char *) bh2
->b_data
)[(first
+1) &
89 if (nr
& 1) next
= ((*p_first
>> 4) | (*p_last
<< 4)) & 0xfff;
90 else next
= (*p_first
+(*p_last
<< 8)) & 0xfff;
91 if (next
>= 0xff7) next
= -1;
93 if (new_value
!= -1) {
94 if (MSDOS_SB(sb
)->fat_bits
== 32) {
95 ((unsigned long *) bh
->b_data
)[(first
& (SECTOR_SIZE
-1)) >>
96 2] = CT_LE_L(new_value
);
97 } else if (MSDOS_SB(sb
)->fat_bits
== 16) {
98 ((unsigned short *) bh
->b_data
)[(first
& (SECTOR_SIZE
-1)) >>
99 1] = CT_LE_W(new_value
);
102 *p_first
= (*p_first
& 0xf) | (new_value
<< 4);
103 *p_last
= new_value
>> 4;
106 *p_first
= new_value
& 0xff;
107 *p_last
= (*p_last
& 0xf0) | (new_value
>> 8);
109 fat_mark_buffer_dirty(sb
, bh2
, 1);
111 fat_mark_buffer_dirty(sb
, bh
, 1);
112 for (copy
= 1; copy
< MSDOS_SB(sb
)->fats
; copy
++) {
113 b
= MSDOS_SB(sb
)->fat_start
+ (first
>> SECTOR_BITS
) +
114 MSDOS_SB(sb
)->fat_length
* copy
;
115 if (!(c_bh
= fat_bread(sb
, b
)))
117 memcpy(c_bh
->b_data
,bh
->b_data
,SECTOR_SIZE
);
118 fat_mark_buffer_dirty(sb
, c_bh
, 1);
120 if (!(c_bh2
= fat_bread(sb
, b
+1))) {
121 fat_brelse(sb
, c_bh
);
124 memcpy(c_bh2
->b_data
,bh2
->b_data
,SECTOR_SIZE
);
125 fat_brelse(sb
, c_bh2
);
127 fat_brelse(sb
, c_bh
);
137 void fat_cache_init(void)
139 static int initialized
= 0;
142 if (initialized
) return;
143 fat_cache
= &cache
[0];
144 for (count
= 0; count
< FAT_CACHE
; count
++) {
145 cache
[count
].device
= 0;
146 cache
[count
].next
= count
== FAT_CACHE
-1 ? NULL
:
153 void fat_cache_lookup(struct inode
*inode
,int cluster
,int *f_clu
,int *d_clu
)
155 struct fat_cache
*walk
;
156 int first
= MSDOS_I(inode
)->i_start
;
160 for (walk
= fat_cache
; walk
; walk
= walk
->next
)
161 if (inode
->i_dev
== walk
->device
162 && walk
->start_cluster
== first
163 && walk
->file_cluster
<= cluster
164 && walk
->file_cluster
> *f_clu
) {
165 *d_clu
= walk
->disk_cluster
;
167 printk("cache hit: %d (%d)\n",walk
->file_cluster
,*d_clu
);
169 if ((*f_clu
= walk
->file_cluster
) == cluster
) return;
172 printk("cache miss\n");
178 static void list_cache(void)
180 struct fat_cache
*walk
;
182 for (walk
= fat_cache
; walk
; walk
= walk
->next
) {
184 printk("<%s,%d>(%d,%d) ", kdevname(walk
->device
),
185 walk
->start_cluster
, walk
->file_cluster
,
194 void fat_cache_add(struct inode
*inode
,int f_clu
,int d_clu
)
196 struct fat_cache
*walk
,*last
;
197 int first
= MSDOS_I(inode
)->i_start
;
200 for (walk
= fat_cache
; walk
->next
; walk
= (last
= walk
)->next
)
201 if (inode
->i_dev
== walk
->device
202 && walk
->start_cluster
== first
203 && walk
->file_cluster
== f_clu
) {
204 if (walk
->disk_cluster
!= d_clu
) {
205 printk("FAT cache corruption inode=%ld\n",
207 fat_cache_inval_inode(inode
);
211 if (last
== NULL
) return;
212 last
->next
= walk
->next
;
213 walk
->next
= fat_cache
;
220 walk
->device
= inode
->i_dev
;
221 walk
->start_cluster
= first
;
222 walk
->file_cluster
= f_clu
;
223 walk
->disk_cluster
= d_clu
;
225 walk
->next
= fat_cache
;
233 /* Cache invalidation occurs rarely, thus the LRU chain is not updated. It
234 fixes itself after a while. */
236 void fat_cache_inval_inode(struct inode
*inode
)
238 struct fat_cache
*walk
;
239 int first
= MSDOS_I(inode
)->i_start
;
241 for (walk
= fat_cache
; walk
; walk
= walk
->next
)
242 if (walk
->device
== inode
->i_dev
243 && walk
->start_cluster
== first
)
248 void fat_cache_inval_dev(kdev_t device
)
250 struct fat_cache
*walk
;
252 for (walk
= fat_cache
; walk
; walk
= walk
->next
)
253 if (walk
->device
== device
)
258 int fat_get_cluster(struct inode
*inode
,int cluster
)
262 if (!(nr
= MSDOS_I(inode
)->i_start
)) return 0;
263 if (!cluster
) return nr
;
265 for (fat_cache_lookup(inode
,cluster
,&count
,&nr
); count
< cluster
;
267 if ((nr
= fat_access(inode
->i_sb
,nr
,-1)) == -1) return 0;
270 fat_cache_add(inode
,cluster
,nr
);
274 int default_fat_bmap(struct inode
*inode
,int sector
)
276 struct msdos_sb_info
*sb
=MSDOS_SB(inode
->i_sb
);
279 if ((sb
->fat_bits
!= 32) &&
280 (inode
->i_ino
== MSDOS_ROOT_INO
|| (S_ISDIR(inode
->i_mode
) &&
281 !MSDOS_I(inode
)->i_start
))) {
282 if (sector
>= sb
->dir_entries
>> MSDOS_DPS_BITS
)
284 return sector
+sb
->dir_start
;
286 if (sector
>= (MSDOS_I(inode
)->i_realsize
>>9))
288 cluster
= sector
/sb
->cluster_size
;
289 offset
= sector
% sb
->cluster_size
;
290 if (!(cluster
= fat_get_cluster(inode
,cluster
))) return 0;
291 return (cluster
-2)*sb
->cluster_size
+sb
->data_start
+offset
;
295 /* Free all clusters after the skip'th cluster. Doesn't use the cache,
296 because this way we get an additional sanity check. */
298 int fat_free(struct inode
*inode
,int skip
)
302 if (!(nr
= MSDOS_I(inode
)->i_start
)) return 0;
306 if ((nr
= fat_access(inode
->i_sb
,nr
,-1)) == -1) return 0;
308 printk("fat_free: skipped EOF\n");
313 fat_access(inode
->i_sb
,last
,EOF_FAT(inode
->i_sb
));
314 fat_cache_inval_inode(inode
);
316 fat_cache_inval_inode(inode
);
317 MSDOS_I(inode
)->i_start
= 0;
318 MSDOS_I(inode
)->i_logstart
= 0;
319 mark_inode_dirty(inode
);
321 lock_fat(inode
->i_sb
);
323 if (!(nr
= fat_access(inode
->i_sb
,nr
,0))) {
324 fat_fs_panic(inode
->i_sb
,"fat_free: deleting beyond EOF");
327 if (MSDOS_SB(inode
->i_sb
)->free_clusters
!= -1) {
328 MSDOS_SB(inode
->i_sb
)->free_clusters
++;
329 if (MSDOS_SB(inode
->i_sb
)->fat_bits
== 32) {
330 fat_clusters_flush(inode
->i_sb
);
333 inode
->i_blocks
-= MSDOS_SB(inode
->i_sb
)->cluster_size
;
335 unlock_fat(inode
->i_sb
);