This source file includes following definitions.
- affs_bmap
- affs_getblock
- affs_file_read_ofs
- affs_file_write
- affs_file_write_ofs
- affs_truncate
- affs_truncate_ofs
- affs_release_file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <asm/segment.h>
16 #include <asm/system.h>
17 #include <linux/sched.h>
18 #include <linux/affs_fs.h>
19 #include <linux/fcntl.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/stat.h>
23 #include <linux/locks.h>
24 #include <linux/dirent.h>
25 #include <linux/fs.h>
26 #include <linux/amigaffs.h>
27 #include <linux/mm.h>
28 #include <linux/pagemap.h>
29
30 #define MIN(a,b) (((a)<(b))?(a):(b))
31 #define MAX(a,b) (((a)>(b))?(a):(b))
32
33 static int affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, int count);
34 static int affs_file_write(struct inode *inode, struct file *filp, const char *buf, int count);
35 static int affs_file_write_ofs(struct inode *inode, struct file *filp, const char *buf, int count);
36 static void affs_release_file(struct inode *inode, struct file *filp);
37
38 static struct file_operations affs_file_operations = {
39 NULL,
40 generic_file_read,
41 affs_file_write,
42 NULL,
43 NULL,
44 NULL,
45 generic_file_mmap,
46 NULL,
47 affs_release_file,
48 file_fsync
49 };
50
51 struct inode_operations affs_file_inode_operations = {
52 &affs_file_operations,
53 NULL,
54 NULL,
55 NULL,
56 NULL,
57 NULL,
58 NULL,
59 NULL,
60 NULL,
61 NULL,
62 NULL,
63 NULL,
64 generic_readpage,
65 NULL,
66 affs_bmap,
67 affs_truncate,
68 NULL,
69 NULL
70 };
71
72 static struct file_operations affs_file_operations_ofs = {
73 NULL,
74 affs_file_read_ofs,
75 affs_file_write_ofs,
76 NULL,
77 NULL,
78 NULL,
79 NULL,
80 NULL,
81 NULL,
82 file_fsync
83 };
84
85 struct inode_operations affs_file_inode_operations_ofs = {
86 &affs_file_operations_ofs,
87 NULL,
88 NULL,
89 NULL,
90 NULL,
91 NULL,
92 NULL,
93 NULL,
94 NULL,
95 NULL,
96 NULL,
97 NULL,
98 NULL,
99 NULL,
100 NULL,
101 affs_truncate_ofs,
102 NULL,
103 NULL
104 };
105
106 int
107 affs_bmap(struct inode *inode, LONG block)
108 {
109 struct buffer_head *bh;
110 LONG ext, key;
111 LONG ptype, stype;
112
113 pr_debug("AFFS: bmap(%lu,%d)\n",inode->i_ino,block);
114
115 if (block < 0) {
116 printk("affs_bmap: block < 0\n");
117 return 0;
118 }
119
120
121
122 key = inode->u.affs_i.i_original ? inode->u.affs_i.i_original : inode->i_ino;
123
124 ext = block / AFFS_I2HSIZE(inode);
125 if (ext) {
126 if (ext > inode->u.affs_i.i_max_ext)
127 ext = inode->u.affs_i.i_max_ext;
128 if (ext)
129 key = inode->u.affs_i.i_ext[ext - 1];
130 block -= ext * AFFS_I2HSIZE(inode);
131 }
132
133 for (;;) {
134 bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
135 if (!bh)
136 return 0;
137 if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) ||
138 (ptype != T_SHORT && ptype != T_LIST) || stype != ST_FILE) {
139 affs_brelse(bh);
140 return 0;
141 }
142 if (block < AFFS_I2HSIZE(inode))
143 break;
144 block -= AFFS_I2HSIZE(inode);
145 key = htonl(FILE_END(bh->b_data,inode)->extension);
146 affs_brelse(bh);
147 if (ext < EXT_CACHE_SIZE - 1) {
148 inode->u.affs_i.i_ext[ext] = key;
149 inode->u.affs_i.i_max_ext = ++ext;
150 }
151 }
152 key = AFFS_GET_HASHENTRY(bh->b_data,(AFFS_I2HSIZE(inode) - 1) - block);
153 affs_brelse(bh);
154 return key;
155 }
156
157 struct buffer_head *
158 affs_getblock(struct inode *inode, LONG block)
159 {
160 struct buffer_head *bh;
161 struct buffer_head *ebh;
162 LONG key;
163 LONG ext;
164 LONG cnt, j, pt;
165
166 pr_debug("AFFS: getblock(%lu,%d)\n",inode->i_ino,block);
167
168 if (block < 0)
169 return NULL;
170 key = inode->i_ino;
171 pt = T_SHORT;
172
173 ext = block / AFFS_I2HSIZE(inode);
174 if (ext) {
175 if (ext > inode->u.affs_i.i_max_ext)
176 ext = inode->u.affs_i.i_max_ext;
177 if (ext) {
178 key = inode->u.affs_i.i_ext[ext - 1];
179 block -= ext * AFFS_I2HSIZE(inode);
180 pt = T_LIST;
181 }
182 }
183
184 for (;;) {
185 bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
186 if (!bh)
187 return NULL;
188 if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cnt,&j) ||
189 cnt != pt || j != ST_FILE) {
190 printk("AFFS: getblock(): inode %d is not a valid %s\n",key,
191 pt == T_SHORT ? "file header" : "extension block");
192 affs_brelse(bh);
193 return NULL;
194 }
195 j = htonl(((struct file_front *)bh->b_data)->block_count);
196 while (j < AFFS_I2HSIZE(inode) && j <= block) {
197 key = affs_new_data(inode);
198 if (!key)
199 break;
200 lock_super(inode->i_sb);
201 if (AFFS_BLOCK(bh->b_data,inode,j)) {
202 unlock_super(inode->i_sb);
203 printk("AFFS: getblock(): block already allocated\n");
204 affs_free_block(inode->i_sb,key);
205 j++;
206 continue;
207 }
208 unlock_super(inode->i_sb);
209 AFFS_BLOCK(bh->b_data,inode,j) = ntohl(key);
210 j++;
211 }
212 if (pt == T_SHORT)
213 ((struct file_front *)bh->b_data)->first_data =
214 AFFS_BLOCK(bh->b_data,inode,0);
215 ((struct file_front *)bh->b_data)->block_count = ntohl(j);
216 affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
217 mark_buffer_dirty(bh,1);
218
219 if (block < j)
220 break;
221 if (j < AFFS_I2HSIZE(inode)) {
222 affs_brelse(bh);
223 return NULL;
224 }
225
226 block -= AFFS_I2HSIZE(inode);
227 key = htonl(FILE_END(bh->b_data,inode)->extension);
228 if (!key) {
229 key = affs_new_header(inode);
230 if (!key) {
231 affs_brelse(bh);
232 return NULL;
233 }
234 ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
235 if (!ebh) {
236 affs_free_block(inode->i_sb,key);
237 return NULL;
238 }
239 ((struct file_front *)ebh->b_data)->primary_type = ntohl(T_LIST);
240 ((struct file_front *)ebh->b_data)->own_key = ntohl(key);
241 FILE_END(ebh->b_data,inode)->secondary_type = ntohl(ST_FILE);
242 FILE_END(ebh->b_data,inode)->parent = ntohl(inode->i_ino);
243 affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5);
244 FILE_END(bh->b_data,inode)->extension = ntohl(key);
245 affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
246 mark_buffer_dirty(bh,1);
247 affs_brelse(bh);
248 bh = ebh;
249 }
250 affs_brelse(bh);
251 pt = T_LIST;
252 if (ext < EXT_CACHE_SIZE - 1) {
253 inode->u.affs_i.i_ext[ext] = key;
254 inode->u.affs_i.i_max_ext = ++ext;
255 }
256 }
257 key = htonl(AFFS_BLOCK(bh->b_data,inode,block));
258 affs_brelse(bh);
259 if (!key)
260 return NULL;
261
262 return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
263 }
264
265
266
267
268
269 static int
270 affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, int count)
271 {
272 char *start;
273 int left, offset, size, sector;
274 int blocksize;
275 struct buffer_head *bh;
276 void *data;
277
278 pr_debug("AFFS: file_read_ofs(ino=%lu,pos=%lu,%d)\n",inode->i_ino,(long)filp->f_pos,count);
279
280 if (!inode) {
281 printk("affs_file_read: inode = NULL\n");
282 return -EINVAL;
283 }
284 blocksize = AFFS_I2BSIZE(inode) - 24;
285 if (!(S_ISREG(inode->i_mode))) {
286 pr_debug("affs_file_read: mode = %07o\n",inode->i_mode);
287 return -EINVAL;
288 }
289 if (filp->f_pos >= inode->i_size || count <= 0)
290 return 0;
291
292 start = buf;
293 for (;;) {
294 left = MIN (inode->i_size - filp->f_pos,count - (buf - start));
295 if (!left)
296 break;
297 sector = affs_bmap(inode,(ULONG)filp->f_pos / blocksize);
298 if (!sector)
299 break;
300 offset = (ULONG)filp->f_pos % blocksize;
301 bh = affs_bread(inode->i_dev,sector,AFFS_I2BSIZE(inode));
302 if (!bh)
303 break;
304 data = bh->b_data + 24;
305 size = MIN(blocksize - offset,left);
306 filp->f_pos += size;
307 memcpy_tofs(buf,data + offset,size);
308 buf += size;
309 affs_brelse(bh);
310 }
311 if (start == buf)
312 return -EIO;
313 return buf - start;
314 }
315
316 static int
317 affs_file_write(struct inode *inode, struct file *filp, const char *buf, int count)
318 {
319 off_t pos;
320 int written;
321 int c;
322 int blocksize;
323 struct buffer_head *bh;
324 struct inode *ino;
325 char *p;
326
327 pr_debug("AFFS: file_write(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino,
328 (unsigned long)filp->f_pos,count);
329
330 ino = NULL;
331 if (!inode) {
332 printk("AFFS: file_write(): inode=NULL\n");
333 return -EINVAL;
334 }
335 if (inode->u.affs_i.i_original) {
336 ino = iget(inode->i_sb,inode->u.affs_i.i_original);
337 if (!ino) {
338 printk("AFFS: could not follow link from inode %lu to %d\n",
339 inode->i_ino,inode->u.affs_i.i_original);
340 return -EINVAL;
341 }
342 inode = ino;
343 }
344 if (!S_ISREG(inode->i_mode)) {
345 printk("AFFS: file_write(): mode=%07o\n",inode->i_mode);
346 iput(inode);
347 return -EINVAL;
348 }
349 if (filp->f_flags & O_APPEND) {
350 pos = inode->i_size;
351 } else
352 pos = filp->f_pos;
353 written = 0;
354 blocksize = AFFS_I2BSIZE(inode);
355
356 while (written < count) {
357 bh = affs_getblock(inode,pos / blocksize);
358 if (!bh) {
359 if (!written)
360 written = -ENOSPC;
361 break;
362 }
363 c = blocksize - (pos % blocksize);
364 if (c > count - written)
365 c = count - written;
366 if (c != blocksize && !buffer_uptodate(bh)) {
367 ll_rw_block(READ,1,&bh);
368 wait_on_buffer(bh);
369 if (!buffer_uptodate(bh)) {
370 affs_brelse(bh);
371 if (!written)
372 written = -EIO;
373 break;
374 }
375 }
376 p = (pos % blocksize) + bh->b_data;
377 memcpy_fromfs(p,buf,c);
378 update_vm_cache(inode,pos,p,c);
379 mark_buffer_uptodate(bh,1);
380 mark_buffer_dirty(bh,0);
381 affs_brelse(bh);
382 pos += c;
383 written += c;
384 buf += c;
385 }
386 if (pos > inode->i_size)
387 inode->i_size = pos;
388 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
389 filp->f_pos = pos;
390 inode->i_dirt = 1;
391 iput(ino);
392 return written;
393 }
394
395 static int
396 affs_file_write_ofs(struct inode *inode, struct file *filp, const char *buf, int count)
397 {
398 pr_debug("AFFS: file_write_ofs(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino,
399 (unsigned long)filp->f_pos,count);
400
401 return -ENOSPC;
402 }
403
404 void
405 affs_truncate(struct inode *inode)
406 {
407 struct buffer_head *bh;
408 struct inode *ino;
409 LONG first;
410 LONG block;
411 LONG key;
412 LONG *keyp;
413 LONG ekey;
414 LONG ptype, stype;
415 int freethis;
416 int ext;
417
418 pr_debug("AFFS: file_truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
419
420 ino = NULL;
421 if (inode->u.affs_i.i_original) {
422 ino = iget(inode->i_sb,inode->u.affs_i.i_original);
423 if (!ino) {
424 printk("AFFS: truncate(): cannot follow link from %lu to %u\n",
425 inode->i_ino,inode->u.affs_i.i_original);
426 return;
427 }
428 inode = ino;
429 }
430 first = (inode->i_size + AFFS_I2BSIZE(inode) - 1) / AFFS_I2BSIZE(inode);
431 ekey = inode->i_ino;
432 ext = 0;
433
434 while (ekey) {
435 if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) {
436 printk("AFFS: truncate(): Can't read block %d\n",ekey);
437 break;
438 }
439 ptype = htonl(((struct file_front *)bh->b_data)->primary_type);
440 stype = htonl(FILE_END(bh->b_data,inode)->secondary_type);
441 if (ekey == inode->i_ino && ptype == T_SHORT && stype == ST_LINKFILE &&
442 LINK_END(bh->b_data,inode)->original == 0) {
443 pr_debug("AFFS: truncate(): dumping link\n");
444 affs_brelse(bh);
445 break;
446 }
447 if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) {
448 printk("AFFS: truncate(): bad block (ptype=%d, stype=%d)\n",
449 ptype,stype);
450 affs_brelse(bh);
451 break;
452 }
453
454 freethis = first == 0 && ekey != inode->i_ino;
455 for ( block = first; block < AFFS_I2HSIZE(inode); block++) {
456 keyp = &AFFS_BLOCK(bh->b_data,inode,block);
457 key = htonl(*keyp);
458 if (key) {
459 *keyp = 0;
460 affs_free_block(inode->i_sb,key);
461 } else {
462 block = AFFS_I2HSIZE(inode);
463 break;
464 }
465 }
466 keyp = &GET_END_PTR(struct file_end,bh->b_data,AFFS_I2BSIZE(inode))->extension;
467 key = htonl(*keyp);
468 if (first <= AFFS_I2HSIZE(inode)) {
469 ((struct file_front *)bh->b_data)->block_count = htonl(first);
470 first = 0;
471 *keyp = 0;
472 } else {
473 first -= AFFS_I2HSIZE(inode);
474 }
475 if (freethis) {
476 affs_brelse(bh);
477 affs_free_block(inode->i_sb,ekey);
478 } else {
479 affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
480 mark_buffer_dirty(bh,1);
481 affs_brelse(bh);
482 }
483 ekey = key;
484 }
485 inode->u.affs_i.i_max_ext = 0;
486 iput(ino);
487 }
488
489 void
490 affs_truncate_ofs(struct inode *inode)
491 {
492 struct buffer_head *bh;
493 struct inode *ino;
494 LONG first;
495 LONG block;
496 LONG key;
497 LONG *keyp;
498 LONG ekey;
499 LONG ptype, stype;
500 int freethis;
501 int blocksize;
502
503 pr_debug("AFFS: file_truncate_ofs(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
504
505 ino = NULL;
506 if (inode->u.affs_i.i_original) {
507 ino = iget(inode->i_sb,inode->u.affs_i.i_original);
508 if (!ino) {
509 printk("AFFS: truncate(): cannot follow link from %lu to %u\n",
510 inode->i_ino,inode->u.affs_i.i_original);
511 return;
512 }
513 inode = ino;
514 }
515 blocksize = AFFS_I2BSIZE(inode) - 24;
516 first = (inode->i_size + blocksize - 1) / blocksize;
517 ekey = inode->i_ino;
518
519 while (ekey) {
520 if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) {
521 printk("AFFS: truncate(): Can't read block %d\n",ekey);
522 break;
523 }
524 ptype = htonl(((struct file_front *)bh->b_data)->primary_type);
525 stype = htonl(FILE_END(bh->b_data,inode)->secondary_type);
526 if (ekey == inode->i_ino && ptype == T_SHORT && stype == ST_LINKFILE &&
527 LINK_END(bh->b_data,inode)->original == 0) {
528 pr_debug("AFFS: truncate(): dumping link\n");
529 affs_brelse(bh);
530 break;
531 }
532 if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) {
533 printk("AFFS: truncate(): bad block (ptype=%d, stype=%d)\n",
534 ptype,stype);
535 affs_brelse(bh);
536 break;
537 }
538
539 freethis = first == 0 && ekey != inode->i_ino;
540 for ( block = first; block < AFFS_I2HSIZE(inode); block++) {
541 keyp = &((struct file_front *)bh->b_data)->
542 blocks[AFFS_I2HSIZE(inode) - 1 - block];
543 key = htonl(*keyp);
544 if (key) {
545 *keyp = 0;
546 affs_free_block(inode->i_sb,key);
547 } else {
548 block = AFFS_I2HSIZE(inode);
549 break;
550 }
551 }
552 keyp = &GET_END_PTR(struct file_end,bh->b_data,AFFS_I2BSIZE(inode))->extension;
553 key = htonl(*keyp);
554 if (first <= AFFS_I2HSIZE(inode)) {
555 ((struct file_front *)bh->b_data)->block_count = htonl(first);
556 first = 0;
557 *keyp = 0;
558 } else {
559 first -= AFFS_I2HSIZE(inode);
560 }
561 if (freethis) {
562 affs_brelse(bh);
563 affs_free_block(inode->i_sb,ekey);
564 } else {
565 affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
566 mark_buffer_dirty(bh,1);
567 affs_brelse(bh);
568 }
569 ekey = key;
570 }
571 inode->u.affs_i.i_max_ext = 0;
572 iput(ino);
573 }
574
575 static void
576 affs_release_file(struct inode *inode, struct file *filp)
577 {
578 if (filp->f_mode & 2) {
579 while (inode->u.affs_i.i_pa_cnt) {
580 affs_free_block(inode->i_sb,
581 inode->u.affs_i.i_data[inode->u.affs_i.i_pa_next++]);
582 inode->u.affs_i.i_pa_next &= MAX_PREALLOC - 1;
583 inode->u.affs_i.i_pa_cnt--;
584 }
585 }
586 }