1/* 2 * linux/fs/fat/cache.c 3 * 4 * Written 1992,1993 by Werner Almesberger 5 * 6 * Mar 1999. AV. Changed cache, so that it uses the starting cluster instead 7 * of inode number. 8 * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers. 9 */ 10 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> 17 18# define PRINTK(x) 19 20static struct fat_cache *fat_cache,cache[FAT_CACHE]; 21static spinlock_t fat_cache_lock = SPIN_LOCK_UNLOCKED; 22 23/* Returns the this'th FAT entry, -1 if it is an end-of-file entry. If 24 new_value is != -1, that FAT entry is replaced by it. */ 25 26int fat_access(struct super_block *sb,int nr,int new_value) 27{ 28 return MSDOS_SB(sb)->cvf_format->fat_access(sb,nr,new_value); 29} 30 31int fat_bmap(struct inode *inode,int sector) 32{ 33 return MSDOS_SB(inode->i_sb)->cvf_format->cvf_bmap(inode,sector); 34} 35 36int default_fat_access(struct super_block *sb,int nr,int new_value) 37{ 38 struct buffer_head *bh, *bh2, *c_bh, *c_bh2; 39 unsigned char *p_first, *p_last; 40 int copy, first, last, next, b; 41 42 if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters) 43 return 0; 44 if (MSDOS_SB(sb)->fat_bits == 32) { 45 first = last = nr*4; 46 } else if (MSDOS_SB(sb)->fat_bits == 16) { 47 first = last = nr*2; 48 } else { 49 first = nr*3/2; 50 last = first+1; 51 } 52 b = MSDOS_SB(sb)->fat_start + (first >> sb->s_blocksize_bits); 53 if (!(bh = fat_bread(sb, b))) { 54 printk("bread in fat_access failed\n"); 55 return 0; 56 } 57 if ((first >> sb->s_blocksize_bits) == (last >> sb->s_blocksize_bits)) { 58 bh2 = bh; 59 } else { 60 if (!(bh2 = fat_bread(sb, b+1))) { 61 fat_brelse(sb, bh); 62 printk("2nd bread in fat_access failed\n"); 63 return 0; 64 } 65 } 66 if (MSDOS_SB(sb)->fat_bits == 32) { 67 p_first = p_last = NULL; /* GCC needs that stuff */ 68 next = CF_LE_L(((__u32 *) bh->b_data)[(first & 69 (sb->s_blocksize - 1)) >> 2]); 70 /* Fscking Microsoft marketing department. Their "32" is 28. */ 71 next &= 0xfffffff; 72 if (next >= 0xffffff7) next = -1; 73 PRINTK(("fat_bread: 0x%x, nr=0x%x, first=0x%x, next=0x%x\n", b, nr, first, next)); 74 75 } else if (MSDOS_SB(sb)->fat_bits == 16) { 76 p_first = p_last = NULL; /* GCC needs that stuff */ 77 next = CF_LE_W(((__u16 *) bh->b_data)[(first & 78 (sb->s_blocksize - 1)) >> 1]); 79 if (next >= 0xfff7) next = -1; 80 } else { 81 p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)]; 82 p_last = &((__u8 *)bh2->b_data)[(first + 1) & (sb->s_blocksize - 1)]; 83 if (nr & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff; 84 else next = (*p_first+(*p_last << 8)) & 0xfff; 85 if (next >= 0xff7) next = -1; 86 } 87 if (new_value != -1) { 88 if (MSDOS_SB(sb)->fat_bits == 32) { 89 ((__u32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2] 90 = CT_LE_L(new_value); 91 } else if (MSDOS_SB(sb)->fat_bits == 16) { 92 ((__u16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1] 93 = CT_LE_W(new_value); 94 } else { 95 if (nr & 1) { 96 *p_first = (*p_first & 0xf) | (new_value << 4); 97 *p_last = new_value >> 4; 98 } 99 else { 100 *p_first = new_value & 0xff; 101 *p_last = (*p_last & 0xf0) | (new_value >> 8); 102 } 103 fat_mark_buffer_dirty(sb, bh2); 104 } 105 fat_mark_buffer_dirty(sb, bh); 106 for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) { 107 b = MSDOS_SB(sb)->fat_start + (first >> sb->s_blocksize_bits) 108 + MSDOS_SB(sb)->fat_length * copy; 109 if (!(c_bh = fat_bread(sb, b))) 110 break; 111 if (bh != bh2) { 112 if (!(c_bh2 = fat_bread(sb, b+1))) { 113 fat_brelse(sb, c_bh); 114 break; 115 } 116 memcpy(c_bh2->b_data, bh2->b_data, sb->s_blocksize); 117 fat_mark_buffer_dirty(sb, c_bh2); 118 fat_brelse(sb, c_bh2); 119 } 120 memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize); 121 fat_mark_buffer_dirty(sb, c_bh); 122 fat_brelse(sb, c_bh); 123 } 124 } 125 fat_brelse(sb, bh); 126 if (bh != bh2) 127 fat_brelse(sb, bh2); 128 return next; 129} 130 131void fat_cache_init(void) 132{ 133 static int initialized = 0; 134 int count; 135 136 spin_lock(&fat_cache_lock); 137 if (initialized) { 138 spin_unlock(&fat_cache_lock); 139 return; 140 } 141 fat_cache = &cache[0]; 142 for (count = 0; count < FAT_CACHE; count++) { 143 cache[count].device = 0; 144 cache[count].next = count == FAT_CACHE-1 ? NULL : 145 &cache[count+1]; 146 } 147 initialized = 1; 148 spin_unlock(&fat_cache_lock); 149} 150 151 152void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu) 153{ 154 struct fat_cache *walk; 155 int first = MSDOS_I(inode)->i_start; 156 157 if (!first) 158 return; 159 spin_lock(&fat_cache_lock); 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; 166#ifdef DEBUG 167printk("cache hit: %d (%d)\n",walk->file_cluster,*d_clu); 168#endif 169 if ((*f_clu = walk->file_cluster) == cluster) { 170 spin_unlock(&fat_cache_lock); 171 return; 172 } 173 } 174 spin_unlock(&fat_cache_lock); 175#ifdef DEBUG 176printk("cache miss\n"); 177#endif 178} 179 180 181#ifdef DEBUG 182static void list_cache(void) 183{ 184 struct fat_cache *walk; 185 186 for (walk = fat_cache; walk; walk = walk->next) { 187 if (walk->device) 188 printk("<%s,%d>(%d,%d) ", kdevname(walk->device), 189 walk->start_cluster, walk->file_cluster, 190 walk->disk_cluster); 191 else printk("-- "); 192 } 193 printk("\n"); 194} 195#endif 196 197 198void fat_cache_add(struct inode *inode,int f_clu,int d_clu) 199{ 200 struct fat_cache *walk,*last; 201 int first = MSDOS_I(inode)->i_start; 202 203 last = NULL; 204 spin_lock(&fat_cache_lock); 205 for (walk = fat_cache; walk->next; walk = (last = walk)->next) 206 if (inode->i_dev == walk->device 207 && walk->start_cluster == first 208 && walk->file_cluster == f_clu) { 209 if (walk->disk_cluster != d_clu) { 210 printk("FAT cache corruption inode=%ld\n", 211 inode->i_ino); 212 spin_unlock(&fat_cache_lock); 213 fat_cache_inval_inode(inode); 214 return; 215 } 216 /* update LRU */ 217 if (last == NULL) { 218 spin_unlock(&fat_cache_lock); 219 return; 220 } 221 last->next = walk->next; 222 walk->next = fat_cache; 223 fat_cache = walk; 224#ifdef DEBUG 225list_cache(); 226#endif 227 spin_unlock(&fat_cache_lock); 228 return; 229 } 230 walk->device = inode->i_dev; 231 walk->start_cluster = first; 232 walk->file_cluster = f_clu; 233 walk->disk_cluster = d_clu; 234 last->next = NULL; 235 walk->next = fat_cache; 236 fat_cache = walk; 237 spin_unlock(&fat_cache_lock); 238#ifdef DEBUG 239list_cache(); 240#endif 241} 242 243 244/* Cache invalidation occurs rarely, thus the LRU chain is not updated. It 245 fixes itself after a while. */ 246 247void fat_cache_inval_inode(struct inode *inode) 248{ 249 struct fat_cache *walk; 250 int first = MSDOS_I(inode)->i_start; 251 252 spin_lock(&fat_cache_lock); 253 for (walk = fat_cache; walk; walk = walk->next) 254 if (walk->device == inode->i_dev 255 && walk->start_cluster == first) 256 walk->device = 0; 257 spin_unlock(&fat_cache_lock); 258} 259 260 261void fat_cache_inval_dev(kdev_t device) 262{ 263 struct fat_cache *walk; 264 265 spin_lock(&fat_cache_lock); 266 for (walk = fat_cache; walk; walk = walk->next) 267 if (walk->device == device) 268 walk->device = 0; 269 spin_unlock(&fat_cache_lock); 270} 271 272 273int fat_get_cluster(struct inode *inode,int cluster) 274{ 275 int nr,count; 276 277 if (!(nr = MSDOS_I(inode)->i_start)) return 0; 278 if (!cluster) return nr; 279 count = 0; 280 for (fat_cache_lookup(inode,cluster,&count,&nr); count < cluster; 281 count++) { 282 if ((nr = fat_access(inode->i_sb,nr,-1)) == -1) return 0; 283 if (!nr) return 0; 284 } 285 fat_cache_add(inode,cluster,nr); 286 return nr; 287} 288 289int default_fat_bmap(struct inode *inode,int sector) 290{ 291 struct super_block *sb = inode->i_sb; 292 struct msdos_sb_info *sbi = MSDOS_SB(sb); 293 int cluster, offset, last_block; 294 295 if ((sbi->fat_bits != 32) && 296 (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) && 297 !MSDOS_I(inode)->i_start))) { 298 if (sector >= sbi->dir_entries >> sbi->dir_per_block_bits) 299 return 0; 300 return sector + sbi->dir_start; 301 } 302 last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1)) 303 >> sb->s_blocksize_bits; 304 if (sector >= last_block) 305 return 0; 306 307 cluster = sector / sbi->cluster_size; 308 offset = sector % sbi->cluster_size; 309 if (!(cluster = fat_get_cluster(inode, cluster))) 310 return 0; 311 312 return (cluster - 2) * sbi->cluster_size + sbi->data_start + offset; 313} 314 315 316/* Free all clusters after the skip'th cluster. Doesn't use the cache, 317 because this way we get an additional sanity check. */ 318 319int fat_free(struct inode *inode,int skip) 320{ 321 int nr,last; 322 323 if (!(nr = MSDOS_I(inode)->i_start)) return 0; 324 last = 0; 325 while (skip--) { 326 last = nr; 327 if ((nr = fat_access(inode->i_sb,nr,-1)) == -1) return 0; 328 if (!nr) { 329 printk("fat_free: skipped EOF\n"); 330 return -EIO; 331 } 332 } 333 if (last) { 334 fat_access(inode->i_sb,last,EOF_FAT(inode->i_sb)); 335 fat_cache_inval_inode(inode); 336 } else { 337 fat_cache_inval_inode(inode); 338 MSDOS_I(inode)->i_start = 0; 339 MSDOS_I(inode)->i_logstart = 0; 340 mark_inode_dirty(inode); 341 } 342 lock_fat(inode->i_sb); 343 while (nr != -1) { 344 if (!(nr = fat_access(inode->i_sb,nr,0))) { 345 fat_fs_panic(inode->i_sb,"fat_free: deleting beyond EOF"); 346 break; 347 } 348 if (MSDOS_SB(inode->i_sb)->free_clusters != -1) { 349 MSDOS_SB(inode->i_sb)->free_clusters++; 350 if (MSDOS_SB(inode->i_sb)->fat_bits == 32) { 351 fat_clusters_flush(inode->i_sb); 352 } 353 } 354 inode->i_blocks -= (1 << MSDOS_SB(inode->i_sb)->cluster_bits) / 512; 355 } 356 unlock_fat(inode->i_sb); 357 return 0; 358} 359