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