~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/affs/file.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/fs/affs/file.c
  3  *
  4  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
  5  *
  6  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  7  *
  8  *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
  9  *
 10  *  (C) 1991  Linus Torvalds - minix filesystem
 11  *
 12  *  affs regular file handling primitives
 13  */
 14 
 15 #define DEBUG 0
 16 #include <asm/div64.h>
 17 #include <asm/uaccess.h>
 18 #include <asm/system.h>
 19 #include <linux/sched.h>
 20 #include <linux/affs_fs.h>
 21 #include <linux/fcntl.h>
 22 #include <linux/kernel.h>
 23 #include <linux/errno.h>
 24 #include <linux/malloc.h>
 25 #include <linux/stat.h>
 26 #include <linux/locks.h>
 27 #include <linux/smp_lock.h>
 28 #include <linux/dirent.h>
 29 #include <linux/fs.h>
 30 #include <linux/amigaffs.h>
 31 #include <linux/mm.h>
 32 #include <linux/pagemap.h>
 33 
 34 #define MIN(a,b) (((a)<(b))?(a):(b))
 35 #define MAX(a,b) (((a)>(b))?(a):(b))
 36 
 37 #if PAGE_SIZE < 4096
 38 #error PAGE_SIZE must be at least 4096
 39 #endif
 40 
 41 static struct buffer_head *affs_getblock(struct inode *inode, s32 block);
 42 static ssize_t affs_file_read_ofs(struct file *filp, char *buf, size_t count, loff_t *ppos);
 43 static ssize_t affs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos);
 44 static ssize_t affs_file_write_ofs(struct file *filp, const char *buf, size_t cnt, loff_t *ppos);
 45 static int alloc_ext_cache(struct inode *inode);
 46 
 47 struct file_operations affs_file_operations = {
 48         read:           generic_file_read,
 49         write:          affs_file_write,
 50         mmap:           generic_file_mmap,
 51         fsync:          file_fsync,
 52 };
 53 
 54 struct inode_operations affs_file_inode_operations = {
 55         truncate:       affs_truncate,
 56         setattr:        affs_notify_change,
 57 };
 58 
 59 struct file_operations affs_file_operations_ofs = {
 60         read:           affs_file_read_ofs,
 61         write:          affs_file_write_ofs,
 62         fsync:          file_fsync,
 63 };
 64 
 65 #define AFFS_ISINDEX(x) ((x < 129) ||                           \
 66                          (x < 512 && (x & 1) == 0) ||           \
 67                          (x < 1024 && (x & 3) == 0) ||          \
 68                          (x < 2048 && (x & 15) == 0) ||         \
 69                          (x < 4096 && (x & 63) == 0) ||         \
 70                          (x < 20480 && (x & 255) == 0) ||       \
 71                          (x < 36864 && (x & 511) == 0))
 72 
 73 /* The keys of the extension blocks are stored in a 512-entry
 74  * deep cache. In order to save memory, not every key of later
 75  * extension blocks is stored - the larger the file gets, the
 76  * bigger the holes in between.
 77  */
 78 
 79 static int
 80 seqnum_to_index(int seqnum)
 81 {
 82         /* All of the first 127 keys are stored */
 83         if (seqnum < 128)
 84                 return seqnum;
 85         seqnum -= 128;
 86 
 87         /* Of the next 384 keys, every 2nd is kept */
 88         if (seqnum < (192 * 2))
 89                 return 128 + (seqnum >> 1);
 90         seqnum -= 192 * 2;
 91         
 92         /* Every 4th of the next 512 */
 93         if (seqnum < (128 * 4))
 94                 return 128 + 192 + (seqnum >> 2);
 95         seqnum -= 128 * 4;
 96 
 97         /* Every 16th of the next 1024 */
 98         if (seqnum < (64 * 16))
 99                 return 128 + 192 + 128 + (seqnum >> 4);
100         seqnum -= 64 * 16;
101 
102         /* Every 64th of the next 2048 */
103         if (seqnum < (32 * 64))
104                 return 128 + 192 + 128 + 64 + (seqnum >> 6);
105         seqnum -= 32 * 64;
106 
107         /* Every 256th of the next 16384 */
108         if (seqnum < (64 * 256))
109                 return 128 + 192 + 128 + 64 + 32 + (seqnum >> 8);
110         seqnum -= 64 * 256;
111 
112         /* Every 512th upto 36479 (1.3 GB with 512 byte blocks).
113          * Seeking to positions behind this will get slower
114          * than dead snails nailed to the ground. But if
115          * someone uses files that large with 512-byte blocks,
116          * he or she deserves no better.
117          */
118         
119         if (seqnum > (31 * 512))
120                 seqnum = 31 * 512;
121         return 128 + 192 + 128 + 64 + 32 + 64 + (seqnum >> 9);
122 }
123 
124 /* Now the other way round: Calculate the sequence
125  * number of an extension block of a key at the
126  * given index in the cache.
127  */
128 
129 static int
130 index_to_seqnum(int index)
131 {
132         if (index < 128)
133                 return index;
134         index -= 128;
135         if (index < 192)
136                 return 128 + (index << 1);
137         index -= 192;
138         if (index < 128)
139                 return 128 + 192 * 2 + (index << 2);
140         index -= 128;
141         if (index < 64)
142                 return 128 + 192 * 2 + 128 * 4 + (index << 4);
143         index -= 64;
144         if (index < 32)
145                 return 128 + 192 * 2 + 128 * 4 + 64 * 16 + (index << 6);
146         index -= 32;
147         if (index < 64)
148                 return 128 + 192 * 2 + 128 * 4 + 64 * 16 + 32 * 64 + (index << 8);
149         index -= 64;
150         return 128 + 192 * 2 + 128 * 4 + 64 * 16 + 32 * 64 + 64 * 256 + (index << 9);
151 }
152 
153 static s32 __inline__
154 calc_key(struct inode *inode, int *ext)
155 {
156         int               index;
157         struct key_cache *kc;
158 
159         for (index = 0; index < 4; index++) {
160                 kc = &inode->u.affs_i.i_ec->kc[index];
161                 if (kc->kc_last == -1)
162                         continue;       /* don't look in cache if invalid. */
163                 if (*ext == kc->kc_this_seq) {
164                         return kc->kc_this_key;
165                 } else if (*ext == kc->kc_this_seq + 1) {
166                         if (kc->kc_next_key)
167                                 return kc->kc_next_key;
168                         else {
169                                 (*ext)--;
170                                 return kc->kc_this_key;
171                         }
172                 }
173         }
174         index = seqnum_to_index(*ext);
175         if (index > inode->u.affs_i.i_ec->max_ext)
176                 index = inode->u.affs_i.i_ec->max_ext;
177         *ext = index_to_seqnum(index);
178         return inode->u.affs_i.i_ec->ec[index];
179 }
180 
181 int
182 affs_bmap(struct inode *inode, int block)
183 {
184         struct buffer_head      *bh;
185         s32                      key, nkey;
186         s32                      ptype, stype;
187         int                      ext;
188         int                      index;
189         int                      keycount;
190         struct key_cache        *kc;
191         struct key_cache        *tkc;
192         struct timeval           tv;
193         s32                     *keyp;
194         int                      i;
195 
196         pr_debug("AFFS: bmap(%lu,%d)\n",inode->i_ino,block);
197 
198         lock_kernel();
199         if (block < 0) {
200                 affs_error(inode->i_sb,"bmap","Block < 0");
201                 goto out_fail;
202         }
203         if (!inode->u.affs_i.i_ec) {
204                 if (alloc_ext_cache(inode)) {
205                         goto out_fail;
206                 }
207         }
208 
209         /* Try to find the requested key in the cache.
210          * In order to speed this up as much as possible,
211          * the cache line lookup is done in a separate
212          * step.
213          */
214 
215         for (i = 0; i < 4; i++) {
216                 tkc = &inode->u.affs_i.i_ec->kc[i];
217                 /* Look in any cache if the key is there */
218                 if (block <= tkc->kc_last && block >= tkc->kc_first) {
219                         unlock_kernel();
220                         return tkc->kc_keys[block - tkc->kc_first];
221                 }
222         }
223         kc = NULL;
224         tv = xtime;
225         for (i = 0; i < 4; i++) {
226                 tkc = &inode->u.affs_i.i_ec->kc[i];
227                 if (tkc->kc_lru_time.tv_sec > tv.tv_sec)
228                         continue;
229                 if (tkc->kc_lru_time.tv_sec < tv.tv_sec ||
230                     tkc->kc_lru_time.tv_usec < tv.tv_usec) {
231                         kc = tkc;
232                         tv = tkc->kc_lru_time;
233                 }
234         }
235         if (!kc)        /* Really shouldn't happen */
236                 kc = tkc;
237         kc->kc_lru_time = xtime;
238         keyp            = kc->kc_keys;
239         kc->kc_first    = block;
240         kc->kc_last     = -1;
241         keycount        = AFFS_KCSIZE;
242 
243         /* Calculate sequence number of the extension block where the
244          * number of the requested block is stored. 0 means it's in
245          * the file header.
246          */
247 
248         ext    = block / AFFS_I2HSIZE(inode);
249         key    = calc_key(inode,&ext);
250         block -= ext * AFFS_I2HSIZE(inode);
251 
252         for (;;) {
253                 bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
254                 if (!bh)
255                         goto out_fail;
256 
257                 index = seqnum_to_index(ext);
258                 if (index > inode->u.affs_i.i_ec->max_ext &&
259                     (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) ||
260                      (ptype != T_SHORT && ptype != T_LIST) || stype != ST_FILE)) {
261                         affs_brelse(bh);
262                         goto out_fail;
263                 }
264                 nkey = be32_to_cpu(FILE_END(bh->b_data,inode)->extension);
265                 if (block < AFFS_I2HSIZE(inode)) {
266                         /* Fill cache as much as possible */
267                         if (keycount) {
268                                 kc->kc_first = ext * AFFS_I2HSIZE(inode) + block;
269                                 keycount     = keycount < AFFS_I2HSIZE(inode) - block ? keycount :
270                                                 AFFS_I2HSIZE(inode) - block;
271                                 for (i = 0; i < keycount; i++)
272                                         kc->kc_keys[i] = be32_to_cpu(AFFS_BLOCK(bh->b_data,inode,block + i));
273                                 kc->kc_last = kc->kc_first + i - 1;
274                         }
275                         break;
276                 }
277                 block -= AFFS_I2HSIZE(inode);
278                 affs_brelse(bh);
279                 ext++;
280                 if (index > inode->u.affs_i.i_ec->max_ext && AFFS_ISINDEX(ext)) {
281                         inode->u.affs_i.i_ec->ec[index] = nkey;
282                         inode->u.affs_i.i_ec->max_ext   = index;
283                 }
284                 key = nkey;
285         }
286         kc->kc_this_key = key;
287         kc->kc_this_seq = ext;
288         kc->kc_next_key = nkey;
289         key = be32_to_cpu(AFFS_BLOCK(bh->b_data,inode,block));
290         affs_brelse(bh);
291 out:
292         unlock_kernel();
293         return key;
294 
295 out_fail:
296         key=0;
297         goto out;
298 }
299 
300 
301 static int affs_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create)
302 {
303         int err, phys=0, new=0;
304 
305         if (!create) {
306                 phys = affs_bmap(inode, block);
307                 if (phys) {
308                         bh_result->b_dev = inode->i_dev;
309                         bh_result->b_blocknr = phys;
310                         bh_result->b_state |= (1UL << BH_Mapped);
311                 }
312                 return 0;
313         }
314 
315         err = -EIO;
316         lock_kernel();
317         if (block < 0)
318                 goto abort_negative;
319 
320         if (affs_getblock(inode, block)==NULL) {
321                 err = -EIO;
322                 goto abort;
323         }
324 
325         bh_result->b_dev = inode->i_dev;
326         bh_result->b_blocknr = phys;
327         bh_result->b_state |= (1UL << BH_Mapped);
328         if (new)
329                 bh_result->b_state |= (1UL << BH_New);
330         
331 abort:
332         unlock_kernel();
333         return err;
334 
335 abort_negative:
336         affs_error(inode->i_sb,"affs_get_block","Block < 0");
337         goto abort;
338 
339 }
340                 
341 static int affs_writepage(struct page *page)
342 {
343         return block_write_full_page(page,affs_get_block);
344 }
345 static int affs_readpage(struct file *file, struct page *page)
346 {
347         return block_read_full_page(page,affs_get_block);
348 }
349 static int affs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
350 {
351         return cont_prepare_write(page,from,to,affs_get_block,
352                 &page->mapping->host->u.affs_i.mmu_private);
353 }
354 static int _affs_bmap(struct address_space *mapping, long block)
355 {
356         return generic_block_bmap(mapping,block,affs_get_block);
357 }
358 struct address_space_operations affs_aops = {
359         readpage: affs_readpage,
360         writepage: affs_writepage,
361         sync_page: block_sync_page,
362         prepare_write: affs_prepare_write,
363         commit_write: generic_commit_write,
364         bmap: _affs_bmap
365 };
366 
367 /* With the affs, getting a random block from a file is not
368  * a simple business. Since this fs does not allow holes,
369  * it may be necessary to allocate all the missing blocks
370  * in between, as well as some new extension blocks. The OFS
371  * is even worse: All data blocks contain pointers to the
372  * next ones, so you have to fix [n-1] after allocating [n].
373  * What a mess.
374  */
375 
376 static struct buffer_head * affs_getblock(struct inode *inode, s32 block)
377 {
378         struct super_block      *sb = inode->i_sb;
379         int                      ofs = sb->u.affs_sb.s_flags & SF_OFS;
380         int                      ext = block / AFFS_I2HSIZE(inode);
381         struct buffer_head      *bh, *ebh, *pbh = NULL;
382         struct key_cache        *kc;
383         s32                      key, nkey;
384         int                      cf, j, pt;
385         int                      index;
386         int                      err;
387 
388         pr_debug("AFFS: getblock(%lu,%d)\n",inode->i_ino,block);
389 
390         key    = calc_key(inode,&ext);
391         block -= ext * AFFS_I2HSIZE(inode);
392         pt     = ext ? T_LIST : T_SHORT;
393 
394         /* Key refers now to the last known extension block,
395          * ext is its sequence number (if 0, key refers to the
396          * header block), and block is the block number relative
397          * to the first block stored in that extension block.
398          */
399         for (;;) {      /* Loop over header block and extension blocks */
400                 struct file_front *fdp;
401 
402                 bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
403                 if (!bh)
404                         goto out_fail;
405                 fdp = (struct file_front *) bh->b_data;
406                 err = affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cf,&j);
407                 if (err || cf != pt || j != ST_FILE) {
408                         affs_error(sb, "getblock",
409                                 "Block %d is not a valid %s", key,
410                                 pt == T_SHORT ? "file header" : "ext block");
411                         goto out_free_bh;
412                 }
413                 j  = be32_to_cpu(((struct file_front *)bh->b_data)->block_count);
414                 for (cf = 0; j < AFFS_I2HSIZE(inode) && j <= block; j++) {
415                         if (ofs && !pbh && inode->u.affs_i.i_lastblock >= 0) {
416                                 if (j > 0) {
417                                         s32 k = AFFS_BLOCK(bh->b_data, inode, j - 1);
418                                         pbh = affs_bread(inode->i_dev,
419                                                         be32_to_cpu(k),
420                                                         AFFS_I2BSIZE(inode));
421                                 } else
422                                         pbh = affs_getblock(inode,inode->u.affs_i.i_lastblock);
423                                 if (!pbh) {
424                                         affs_error(sb,"getblock", "Cannot get last block in file");
425                                         break;
426                                 }
427                         }
428                         nkey = affs_new_data(inode);
429                         if (!nkey)
430                                 break;
431                         inode->u.affs_i.i_lastblock++;
432                         if (AFFS_BLOCK(bh->b_data,inode,j)) {
433                                 affs_warning(sb,"getblock","Block already allocated");
434                                 affs_free_block(sb,nkey);
435                                 continue;
436                         }
437                         AFFS_BLOCK(bh->b_data,inode,j) = cpu_to_be32(nkey);
438                         if (ofs) {
439                                 ebh = affs_bread(inode->i_dev,nkey,AFFS_I2BSIZE(inode));
440                                 if (!ebh) {
441                                         affs_error(sb,"getblock", "Cannot get block %d",nkey);
442                                         affs_free_block(sb,nkey);
443                                         AFFS_BLOCK(bh->b_data,inode,j) = 0;
444                                         break;
445                                 }
446                                 DATA_FRONT(ebh)->primary_type    = cpu_to_be32(T_DATA);
447                                 DATA_FRONT(ebh)->header_key      = cpu_to_be32(inode->i_ino);
448                                 DATA_FRONT(ebh)->sequence_number = cpu_to_be32(inode->u.affs_i.i_lastblock + 1);
449                                 affs_fix_checksum(AFFS_I2BSIZE(inode), ebh->b_data, 5);
450                                 mark_buffer_dirty(ebh);
451                                 if (pbh) {
452                                         DATA_FRONT(pbh)->data_size = cpu_to_be32(AFFS_I2BSIZE(inode) - 24);
453                                         DATA_FRONT(pbh)->next_data = cpu_to_be32(nkey);
454                                         affs_fix_checksum(AFFS_I2BSIZE(inode),pbh->b_data,5);
455                                         mark_buffer_dirty(pbh);
456                                         affs_brelse(pbh);
457                                 }
458                                 pbh = ebh;
459                         }
460                         cf = 1;
461                 }
462                 /* N.B. May need to release pbh after here */
463 
464                 if (cf) {
465                         if (pt == T_SHORT)
466                                 fdp->first_data = AFFS_BLOCK(bh->b_data,inode,0);
467                         fdp->block_count = cpu_to_be32(j);
468                         affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
469                         mark_buffer_dirty(bh);
470                 }
471 
472                 if (block < j) {
473                         if (pbh)
474                                 affs_brelse(pbh);
475                         break;
476                 }
477                 if (j < AFFS_I2HSIZE(inode)) {
478                         /* N.B. What about pbh here? */
479                         goto out_free_bh;
480                 }
481 
482                 block -= AFFS_I2HSIZE(inode);
483                 key    = be32_to_cpu(FILE_END(bh->b_data,inode)->extension);
484                 if (!key) {
485                         key = affs_new_header(inode);
486                         if (!key)
487                                 goto out_free_bh;
488                         ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
489                         if (!ebh) {
490                                 /* N.B. must free bh here */
491                                 goto out_free_block;
492                         }
493                         ((struct file_front *)ebh->b_data)->primary_type = cpu_to_be32(T_LIST);
494                         ((struct file_front *)ebh->b_data)->own_key      = cpu_to_be32(key);
495                         FILE_END(ebh->b_data,inode)->secondary_type      = cpu_to_be32(ST_FILE);
496                         FILE_END(ebh->b_data,inode)->parent              = cpu_to_be32(inode->i_ino);
497                         affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5);
498                         mark_buffer_dirty(ebh);
499                         FILE_END(bh->b_data,inode)->extension = cpu_to_be32(key);
500                         affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
501                         mark_buffer_dirty(bh);
502                         affs_brelse(bh);
503                         bh = ebh;
504                 }
505                 pt = T_LIST;
506                 ext++;
507                 index = seqnum_to_index(ext);
508                 if (index > inode->u.affs_i.i_ec->max_ext &&
509                     AFFS_ISINDEX(ext)) {
510                         inode->u.affs_i.i_ec->ec[index] = key;
511                         inode->u.affs_i.i_ec->max_ext   = index;
512                 }
513                 affs_brelse(bh);
514         }
515 
516         /* Invalidate key cache */
517         for (j = 0; j < 4; j++) {
518                 kc = &inode->u.affs_i.i_ec->kc[j];
519                 kc->kc_last = -1;
520         }
521         key = be32_to_cpu(AFFS_BLOCK(bh->b_data,inode,block));
522         affs_brelse(bh);
523         if (!key)
524                 goto out_fail;
525 
526         bh = affs_bread(inode->i_dev, key, AFFS_I2BSIZE(inode));
527         return bh;
528 
529 out_free_block:
530         affs_free_block(sb, key);
531 out_free_bh:
532         affs_brelse(bh);
533 out_fail:
534         return NULL;
535 }
536 
537 static ssize_t
538 affs_file_read_ofs(struct file *filp, char *buf, size_t count, loff_t *ppos)
539 {
540         struct inode            *inode = filp->f_dentry->d_inode;
541         char                    *start;
542         ssize_t                  left, offset, size, sector;
543         ssize_t                  blocksize;
544         struct buffer_head      *bh;
545         void                    *data;
546         loff_t          tmp;
547 
548         pr_debug("AFFS: file_read_ofs(ino=%lu,pos=%lu,%d)\n",inode->i_ino,
549                  (unsigned long)*ppos,count);
550 
551         if (!inode) {
552                 affs_error(inode->i_sb,"file_read_ofs","Inode = NULL");
553                 return -EINVAL;
554         }
555         blocksize = AFFS_I2BSIZE(inode) - 24;
556         if (!(S_ISREG(inode->i_mode))) {
557                 pr_debug("AFFS: file_read: mode = %07o",inode->i_mode);
558                 return -EINVAL;
559         }
560         if (*ppos >= inode->i_size || count <= 0)
561                 return 0;
562 
563         start = buf;
564         for (;;) {
565                 left = MIN (inode->i_size - *ppos,count - (buf - start));
566                 if (!left)
567                         break;
568                 tmp = *ppos;
569                 do_div(tmp, blocksize);
570                 sector = affs_bmap(inode, tmp);
571                 if (!sector)
572                         break;
573                 tmp = *ppos;
574                 offset = do_div(tmp, blocksize);
575                 bh = affs_bread(inode->i_dev,sector,AFFS_I2BSIZE(inode));
576                 if (!bh)
577                         break;
578                 data = bh->b_data + 24;
579                 size = MIN(blocksize - offset,left);
580                 *ppos += size;
581                 copy_to_user(buf,data + offset,size);
582                 buf += size;
583                 affs_brelse(bh);
584         }
585         if (start == buf)
586                 return -EIO;
587         return buf - start;
588 }
589 
590 static ssize_t
591 affs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
592 {
593         ssize_t retval;
594 
595         retval = generic_file_write (file, buf, count, ppos);
596         if (retval >0) {
597                 struct inode *inode = file->f_dentry->d_inode;
598                 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
599                 mark_inode_dirty(inode);
600         }
601         return retval;
602 }
603 
604 static ssize_t
605 affs_file_write_ofs(struct file *file, const char *buf, size_t count, loff_t *ppos)
606 {
607         ssize_t retval;
608 
609         retval = generic_file_write (file, buf, count, ppos);
610         if (retval >0) {
611                 struct inode *inode = file->f_dentry->d_inode;
612                 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
613                 mark_inode_dirty(inode);
614         }
615         return retval;
616 }
617 
618 /* Free any preallocated blocks. */
619 
620 void
621 affs_free_prealloc(struct inode *inode)
622 {
623         struct super_block      *sb = inode->i_sb;
624         struct affs_zone        *zone;
625         int block;
626 
627         pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino);
628 
629         while (inode->u.affs_i.i_pa_cnt) {      
630                 block = inode->u.affs_i.i_data[inode->u.affs_i.i_pa_next++];
631                 inode->u.affs_i.i_pa_next &= AFFS_MAX_PREALLOC - 1;
632                 inode->u.affs_i.i_pa_cnt--;
633                 affs_free_block(sb, block);
634         }
635         if (inode->u.affs_i.i_zone) {
636                 zone = &sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone];
637                 if (zone->z_ino == inode->i_ino)
638                         zone->z_ino = 0;
639         }
640 }
641 
642 /* Truncate (or enlarge) a file to the requested size. */
643 
644 void
645 affs_truncate(struct inode *inode)
646 {
647         struct buffer_head      *bh = NULL;
648         int      first;                 /* First block to be thrown away        */
649         int      block;
650         s32      key;
651         s32     *keyp;
652         s32      ekey;
653         s32      ptype, stype;
654         int      freethis;
655         int      net_blocksize;
656         int      blocksize = AFFS_I2BSIZE(inode);
657         int      rem;
658         int      ext;
659         loff_t tmp;
660 
661         pr_debug("AFFS: truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
662 
663         net_blocksize = blocksize - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0);
664         first = inode->i_size + net_blocksize -1;
665         do_div (first, net_blocksize);
666         if (inode->u.affs_i.i_lastblock < first - 1) {
667                 /* There has to be at least one new block to be allocated */
668                 if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode)) {
669                         /* XXX Fine! No way to indicate an error. */
670                         return /* -ENOSPC */;
671                 }
672                 bh = affs_getblock(inode,first - 1);
673                 if (!bh) {
674                         affs_warning(inode->i_sb,"truncate","Cannot extend file");
675                         inode->i_size = net_blocksize * (inode->u.affs_i.i_lastblock + 1);
676                 } else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
677                         tmp = inode->i_size;
678                         rem = do_div(tmp, net_blocksize);
679                         DATA_FRONT(bh)->data_size = cpu_to_be32(rem ? rem : net_blocksize);
680                         affs_fix_checksum(blocksize,bh->b_data,5);
681                         mark_buffer_dirty(bh);
682                 }
683                 goto out_truncate;
684         }
685         ekey = inode->i_ino;
686         ext  = 0;
687 
688         /* Free all blocks starting at 'first' and all then-empty
689          * extension blocks. Do not free the header block, though.
690          */
691         while (ekey) {
692                 if (!(bh = affs_bread(inode->i_dev,ekey,blocksize))) {
693                         affs_error(inode->i_sb,"truncate","Cannot read block %d",ekey);
694                         goto out_truncate;
695                 }
696                 if (affs_checksum_block(blocksize,bh->b_data,&ptype,&stype)) {
697                         affs_error(inode->i_sb,"truncate","Checksum error in header/ext block %d",
698                                    ekey);
699                         goto out_truncate;
700                 }
701                 if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) {
702                         affs_error(inode->i_sb,"truncate",
703                                    "Bad block (key=%d, ptype=%d, stype=%d)",ekey,ptype,stype);
704                         goto out_truncate;
705                 }
706                 /* Do we have to free this extension block after
707                  * freeing the data blocks pointed to?
708                  */
709                 freethis = first == 0 && ekey != inode->i_ino;
710 
711                 /* Free the data blocks. 'first' is relative to this
712                  * extension block and may well lie behind this block.
713                  */
714                 for (block = first; block < AFFS_I2HSIZE(inode); block++) {
715                         keyp = &AFFS_BLOCK(bh->b_data,inode,block);
716                         key  = be32_to_cpu(*keyp);
717                         if (key) {
718                                 *keyp = 0;
719                                 affs_free_block(inode->i_sb,key);
720                         } else
721                                 break;
722                 }
723                 keyp = &GET_END_PTR(struct file_end,bh->b_data,blocksize)->extension;
724                 key  = be32_to_cpu(*keyp);
725 
726                 /* If 'first' is in this block or is the first
727                  * in the next one, this will be the last in
728                  * the list, thus we have to adjust the count
729                  * and zero the pointer to the next ext block.
730                  */
731                 if (first <= AFFS_I2HSIZE(inode)) {
732                         ((struct file_front *)bh->b_data)->block_count = cpu_to_be32(first);
733                         first = 0;
734                         *keyp = 0;
735                         affs_fix_checksum(blocksize,bh->b_data,5);
736                         mark_buffer_dirty(bh);
737                 } else
738                         first -= AFFS_I2HSIZE(inode);
739                 affs_brelse(bh);
740                 bh = NULL;
741                 if (freethis)                   /* Don't bother fixing checksum */
742                         affs_free_block(inode->i_sb,ekey);
743                 ekey = key;
744         }
745         block = inode->i_size + net_blocksize - 1;
746         do_div (block, net_blocksize);
747         block--;
748         inode->u.affs_i.i_lastblock = block;
749 
750         /* If the file is not truncated to a block boundary,
751          * the partial block after the EOF must be zeroed
752          * so it cannot become accessible again.
753          */
754 
755         tmp = inode->i_size;
756         rem = do_div(tmp, net_blocksize);
757         if (rem) {
758                 if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) 
759                         rem += 24;
760                 pr_debug("AFFS: Zeroing from offset %d in block %d\n",rem,block);
761                 bh = affs_getblock(inode,block);
762                 if (bh) {
763                         memset(bh->b_data + rem,0,blocksize - rem);
764                         if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) {
765                                 ((struct data_front *)bh->b_data)->data_size = cpu_to_be32(rem);
766                                 ((struct data_front *)bh->b_data)->next_data = 0;
767                                 affs_fix_checksum(blocksize,bh->b_data,5);
768                         }
769                         mark_buffer_dirty(bh);
770                 } else 
771                         affs_error(inode->i_sb,"truncate","Cannot read block %d",block);
772         }
773 
774 out_truncate:
775         affs_brelse(bh);
776         /* Invalidate cache */
777         if (inode->u.affs_i.i_ec) {
778                 inode->u.affs_i.i_ec->max_ext = 0;
779                 for (key = 0; key < 4; key++) {
780                         inode->u.affs_i.i_ec->kc[key].kc_next_key = 0;
781                         inode->u.affs_i.i_ec->kc[key].kc_last     = -1;
782                 }
783         }
784         mark_inode_dirty(inode);
785 }
786 
787 /*
788  * Called only when we need to allocate the extension cache.
789  */
790 
791 static int
792 alloc_ext_cache(struct inode *inode)
793 {
794         s32      key;
795         int      i;
796         unsigned long cache_page;
797         int      error = 0;
798 
799         pr_debug("AFFS: alloc_ext_cache(ino=%lu)\n",inode->i_ino);
800 
801         cache_page = get_free_page(GFP_KERNEL);
802         /*
803          * Check whether somebody else allocated it for us ...
804          */
805         if (inode->u.affs_i.i_ec)
806                 goto out_free;
807         if (!cache_page)
808                 goto out_error;
809 
810         inode->u.affs_i.i_ec = (struct ext_cache *) cache_page;
811         /* We only have to initialize non-zero values.
812          * get_free_page() zeroed the page already.
813          */
814         key = inode->i_ino;
815         inode->u.affs_i.i_ec->ec[0] = key;
816         for (i = 0; i < 4; i++) {
817                 inode->u.affs_i.i_ec->kc[i].kc_this_key = key;
818                 inode->u.affs_i.i_ec->kc[i].kc_last     = -1;
819         }
820 out:
821         return error;
822 
823 out_free:
824         if (cache_page)
825                 free_page(cache_page);
826         goto out;
827 
828 out_error:
829         affs_error(inode->i_sb,"alloc_ext_cache","Cache allocation failed");
830         error = -ENOMEM;
831         goto out;
832 }
833 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.