Annotation of linux/fs/msdos/fat.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  linux/fs/msdos/fat.c
                      3:  *
                      4:  *  Written 1992 by Werner Almesberger
                      5:  */
                      6: 
                      7: #include <linux/msdos_fs.h>
                      8: #include <linux/kernel.h>
                      9: #include <linux/errno.h>
                     10: #include <linux/stat.h>
                     11: 
                     12: static struct fat_cache *fat_cache,cache[FAT_CACHE];
                     13: 
                     14: /* Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
                     15:    new_value is != -1, that FAT entry is replaced by it. */
                     16: 
                     17: int fat_access(struct super_block *sb,int this,int new_value)
                     18: {
                     19:        struct buffer_head *bh,*bh2,*c_bh,*c_bh2;
                     20:        unsigned char *p_first,*p_last;
                     21:        void *data,*data2,*c_data,*c_data2;
                     22:        int first,last,next,copy;
                     23: 
                     24:        if (MSDOS_SB(sb)->fat_bits == 16) first = last = this*2;
                     25:        else {
                     26:                first = this*3/2;
                     27:                last = first+1;
                     28:        }
                     29:        if (!(bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(first >>
                     30:            SECTOR_BITS),&data))) {
                     31:                printk("bread in fat_access failed\r\n");
                     32:                return 0;
                     33:        }
                     34:        if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS)) {
                     35:                bh2 = bh;
                     36:                data2 = data;
                     37:        }
                     38:        else {
                     39:                if (!(bh2 = msdos_sread(sb->s_dev,MSDOS_SB(sb)->fat_start+(last
                     40:                    >> SECTOR_BITS),&data2))) {
                     41:                        brelse(bh);
                     42:                        printk("bread in fat_access failed\r\n");
                     43:                        return 0;
                     44:                }
                     45:        }
                     46:        if (MSDOS_SB(sb)->fat_bits == 16) {
                     47:                next = ((unsigned short *) data)[(first & (SECTOR_SIZE-1))
                     48:                    >> 1];
                     49:                if (next >= 0xfff8) next = -1;
                     50:        }
                     51:        else {
                     52:                p_first = &((unsigned char *) data)[first & (SECTOR_SIZE-1)];
                     53:                p_last = &((unsigned char *) data2)[(first+1) &
                     54:                    (SECTOR_SIZE-1)];
                     55:                if (this & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
                     56:                else next = (*p_first+(*p_last << 8)) & 0xfff;
                     57:                if (next >= 0xff8) next = -1;
                     58:        }
                     59:        if (new_value != -1) {
                     60:                if (MSDOS_SB(sb)->fat_bits == 16)
                     61:                        ((unsigned short *) data)[(first & (SECTOR_SIZE-1)) >>
                     62:                            1] = new_value;
                     63:                else {
                     64:                        if (this & 1) {
                     65:                                *p_first = (*p_first & 0xf) | (new_value << 4);
                     66:                                *p_last = new_value >> 4;
                     67:                        }
                     68:                        else {
                     69:                                *p_first = new_value & 0xff;
                     70:                                *p_last = (*p_last & 0xf0) | (new_value >> 8);
                     71:                        }
                     72:                        bh2->b_dirt = 1;
                     73:                }
                     74:                bh->b_dirt = 1;
                     75:                for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
                     76:                        if (!(c_bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->
                     77:                            fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)->
                     78:                            fat_length*copy,&c_data))) break;
                     79:                        memcpy(c_data,data,SECTOR_SIZE);
                     80:                        c_bh->b_dirt = 1;
                     81:                        if (data != data2 || bh != bh2) {
                     82:                                if (!(c_bh2 = msdos_sread(sb->s_dev,
                     83:                                    MSDOS_SB(sb)->fat_start+(first >>
                     84:                                    SECTOR_BITS)+MSDOS_SB(sb)->fat_length*copy
                     85:                                    +1,&c_data2))) {
                     86:                                        brelse(c_bh);
                     87:                                        break;
                     88:                                }
                     89:                                memcpy(c_data2,data2,SECTOR_SIZE);
                     90:                                brelse(c_bh2);
                     91:                        }
                     92:                        brelse(c_bh);
                     93:                }
                     94:        }
                     95:        brelse(bh);
                     96:        if (data != data2) brelse(bh2);
                     97:        return next;
                     98: }
                     99: 
                    100: 
                    101: void cache_init(void)
                    102: {
                    103:        static int initialized = 0;
                    104:        int count;
                    105: 
                    106:        if (initialized) return;
                    107:        fat_cache = &cache[0];
                    108:        for (count = 0; count < FAT_CACHE; count++) {
                    109:                cache[count].device = 0;
                    110:                cache[count].next = count == FAT_CACHE-1 ? NULL :
                    111:                    &cache[count+1];
                    112:        }
                    113:        initialized = 1;
                    114: }
                    115: 
                    116: 
                    117: void cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu)
                    118: {
                    119:        struct fat_cache *walk;
                    120: 
                    121: #ifdef DEBUG
                    122: printk("cache lookup: %d\r\n",*f_clu);
                    123: #endif
                    124:        for (walk = fat_cache; walk; walk = walk->next)
                    125:                if (inode->i_dev == walk->device && walk->ino == inode->i_ino &&
                    126:                    walk->file_cluster <= cluster && walk->file_cluster >
                    127:                    *f_clu) {
                    128:                        *d_clu = walk->disk_cluster;
                    129: #ifdef DEBUG
                    130: printk("cache hit: %d (%d)\r\n",walk->file_cluster,*d_clu);
                    131: #endif
                    132:                        if ((*f_clu = walk->file_cluster) == cluster) return;
                    133:                }
                    134: }
                    135: 
                    136: 
                    137: #ifdef DEBUG
                    138: static void list_cache(void)
                    139: {
                    140:        struct fat_cache *walk;
                    141: 
                    142:        for (walk = fat_cache; walk; walk = walk->next) {
                    143:                if (walk->device) printk("(%d,%d) ",walk->file_cluster,
                    144:                        walk->disk_cluster);
                    145:                else printk("-- ");
                    146:        }
                    147:        printk("\r\n");
                    148: }
                    149: #endif
                    150: 
                    151: 
                    152: void cache_add(struct inode *inode,int f_clu,int d_clu)
                    153: {
                    154:        struct fat_cache *walk,*last;
                    155: 
                    156: #ifdef DEBUG
                    157: printk("cache add: %d (%d)\r\n",f_clu,d_clu);
                    158: #endif
                    159:        last = NULL;
                    160:        for (walk = fat_cache; walk->next; walk = (last = walk)->next)
                    161:                if (inode->i_dev == walk->device && walk->ino == inode->i_ino &&
                    162:                    walk->file_cluster == f_clu) {
                    163:                        if (walk->disk_cluster != d_clu)
                    164:                                panic("FAT cache corruption");
                    165:                        /* update LRU */
                    166:                        if (last == NULL) return;
                    167:                        last->next = walk->next;
                    168:                        walk->next = fat_cache;
                    169:                        fat_cache = walk;
                    170: #ifdef DEBUG
                    171: list_cache();
                    172: #endif
                    173:                        return;
                    174:                }
                    175:        walk->device = inode->i_dev;
                    176:        walk->ino = inode->i_ino;
                    177:        walk->file_cluster = f_clu;
                    178:        walk->disk_cluster = d_clu;
                    179:        last->next = NULL;
                    180:        walk->next = fat_cache;
                    181:        fat_cache = walk;
                    182: #ifdef DEBUG
                    183: list_cache();
                    184: #endif
                    185: }
                    186: 
                    187: 
                    188: /* Cache invalidation occurs rarely, thus the LRU chain is not updated. It
                    189:    fixes itself after a while. */
                    190: 
                    191: void cache_inval_inode(struct inode *inode)
                    192: {
                    193:        struct fat_cache *walk;
                    194: 
                    195:        for (walk = fat_cache; walk; walk = walk->next)
                    196:                if (walk->device == inode->i_dev && walk->ino == inode->i_ino)
                    197:                        walk->device = 0;
                    198: }
                    199: 
                    200: 
                    201: void cache_inval_dev(int device)
                    202: {
                    203:        struct fat_cache *walk;
                    204: 
                    205:        for (walk = fat_cache; walk; walk = walk->next)
                    206:                if (walk->device == device) walk->device = 0;
                    207: }
                    208: 
                    209: 
                    210: int get_cluster(struct inode *inode,int cluster)
                    211: {
                    212:        int this,count;
                    213: 
                    214:        if (!(this = inode->i_data[D_START])) return 0;
                    215:        if (!cluster) return this;
                    216:        count = 0;
                    217:        for (cache_lookup(inode,cluster,&count,&this); count < cluster;
                    218:            count++) {
                    219:                if ((this = fat_access(inode->i_sb,this,-1)) == -1) return 0;
                    220:                if (!this) return 0;
                    221:        }
                    222:        cache_add(inode,cluster,this);
                    223:        return this;
                    224: }
                    225: 
                    226: 
                    227: int msdos_smap(struct inode *inode,int sector)
                    228: {
                    229:        struct msdos_sb_info *sb;
                    230:        int cluster,offset;
                    231: 
                    232:        sb = MSDOS_SB(inode->i_sb);
                    233:        if (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
                    234:            !inode->i_data[D_START])) {
                    235:                if (sector >= sb->dir_entries >> MSDOS_DPS_BITS) return 0;
                    236:                return sector+sb->dir_start;
                    237:        }
                    238:        cluster = sector/sb->cluster_size;
                    239:        offset = sector % sb->cluster_size;
                    240:        if (!(cluster = get_cluster(inode,cluster))) return 0;
                    241:        return (cluster-2)*sb->cluster_size+sb->data_start+offset;
                    242: }
                    243: 
                    244: 
                    245: /* Free all clusters after the skip'th cluster. Doesn't use the cache,
                    246:    because this way we get an additional sanity check. */
                    247: 
                    248: int fat_free(struct inode *inode,int skip)
                    249: {
                    250:        int this,last;
                    251: 
                    252:        if (!(this = inode->i_data[D_START])) return 0;
                    253:        last = 0;
                    254:        while (skip--) {
                    255:                last = this;
                    256:                if ((this = fat_access(inode->i_sb,this,-1)) == -1)
                    257:                        return 0;
                    258:                if (!this) {
                    259:                        printk("fat_free: skipped EOF\r\n");
                    260:                        return -EIO;
                    261:                }
                    262:        }
                    263:        if (last)
                    264:                fat_access(inode->i_sb,last,MSDOS_SB(inode->i_sb)->fat_bits ==
                    265:                    12 ? 0xff8 : 0xfff8);
                    266:        else {
                    267:                inode->i_data[D_START] = 0;
                    268:                inode->i_dirt = 1;
                    269:        }
                    270:        while (this != -1)
                    271:                if (!(this = fat_access(inode->i_sb,this,0)))
                    272:                        panic("fat_free: deleting beyond EOF");
                    273:        cache_inval_inode(inode);
                    274:        return 0;
                    275: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.