home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / minix / truncate.c < prev   
Encoding:
C/C++ Source or Header  |  1995-01-23  |  3.9 KB  |  189 lines

  1. /*
  2.  *  linux/fs/truncate.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. #ifdef MODULE
  8. #include <linux/module.h>
  9. #endif
  10.  
  11. #include <linux/errno.h>
  12. #include <linux/sched.h>
  13. #include <linux/minix_fs.h>
  14. #include <linux/stat.h>
  15. #include <linux/fcntl.h>
  16.  
  17. /*
  18.  * Truncate has the most races in the whole filesystem: coding it is
  19.  * a pain in the a**. Especially as I don't do any locking...
  20.  *
  21.  * The code may look a bit weird, but that's just because I've tried to
  22.  * handle things like file-size changes in a somewhat graceful manner.
  23.  * Anyway, truncating a file at the same time somebody else writes to it
  24.  * is likely to result in pretty weird behaviour...
  25.  *
  26.  * The new code handles normal truncates (size = 0) as well as the more
  27.  * general case (size = XXX). I hope.
  28.  */
  29.  
  30. static int trunc_direct(struct inode * inode)
  31. {
  32.     unsigned short * p;
  33.     struct buffer_head * bh;
  34.     int i, tmp;
  35.     int retry = 0;
  36. #define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
  37.  
  38. repeat:
  39.     for (i = DIRECT_BLOCK ; i < 7 ; i++) {
  40.         p = i + inode->u.minix_i.i_data;
  41.         if (!(tmp = *p))
  42.             continue;
  43.         bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
  44.         if (i < DIRECT_BLOCK) {
  45.             brelse(bh);
  46.             goto repeat;
  47.         }
  48.         if ((bh && bh->b_count != 1) || tmp != *p) {
  49.             retry = 1;
  50.             brelse(bh);
  51.             continue;
  52.         }
  53.         *p = 0;
  54.         inode->i_dirt = 1;
  55.         brelse(bh);
  56.         minix_free_block(inode->i_sb,tmp);
  57.     }
  58.     return retry;
  59. }
  60.  
  61. static int trunc_indirect(struct inode * inode, int offset, unsigned short * p)
  62. {
  63.     struct buffer_head * bh;
  64.     int i, tmp;
  65.     struct buffer_head * ind_bh;
  66.     unsigned short * ind;
  67.     int retry = 0;
  68. #define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
  69.  
  70.     tmp = *p;
  71.     if (!tmp)
  72.         return 0;
  73.     ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
  74.     if (tmp != *p) {
  75.         brelse(ind_bh);
  76.         return 1;
  77.     }
  78.     if (!ind_bh) {
  79.         *p = 0;
  80.         return 0;
  81.     }
  82. repeat:
  83.     for (i = INDIRECT_BLOCK ; i < 512 ; i++) {
  84.         if (i < 0)
  85.             i = 0;
  86.         if (i < INDIRECT_BLOCK)
  87.             goto repeat;
  88.         ind = i+(unsigned short *) ind_bh->b_data;
  89.         tmp = *ind;
  90.         if (!tmp)
  91.             continue;
  92.         bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
  93.         if (i < INDIRECT_BLOCK) {
  94.             brelse(bh);
  95.             goto repeat;
  96.         }
  97.         if ((bh && bh->b_count != 1) || tmp != *ind) {
  98.             retry = 1;
  99.             brelse(bh);
  100.             continue;
  101.         }
  102.         *ind = 0;
  103.         mark_buffer_dirty(ind_bh, 1);
  104.         brelse(bh);
  105.         minix_free_block(inode->i_sb,tmp);
  106.     }
  107.     ind = (unsigned short *) ind_bh->b_data;
  108.     for (i = 0; i < 512; i++)
  109.         if (*(ind++))
  110.             break;
  111.     if (i >= 512)
  112.         if (ind_bh->b_count != 1)
  113.             retry = 1;
  114.         else {
  115.             tmp = *p;
  116.             *p = 0;
  117.             minix_free_block(inode->i_sb,tmp);
  118.         }
  119.     brelse(ind_bh);
  120.     return retry;
  121. }
  122.         
  123. static int trunc_dindirect(struct inode * inode)
  124. {
  125.     int i, tmp;
  126.     struct buffer_head * dind_bh;
  127.     unsigned short * dind, * p;
  128.     int retry = 0;
  129. #define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
  130.  
  131.     p = 8 + inode->u.minix_i.i_data;
  132.     if (!(tmp = *p))
  133.         return 0;
  134.     dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
  135.     if (tmp != *p) {
  136.         brelse(dind_bh);
  137.         return 1;
  138.     }
  139.     if (!dind_bh) {
  140.         *p = 0;
  141.         return 0;
  142.     }
  143. repeat:
  144.     for (i = DINDIRECT_BLOCK ; i < 512 ; i ++) {
  145.         if (i < 0)
  146.             i = 0;
  147.         if (i < DINDIRECT_BLOCK)
  148.             goto repeat;
  149.         dind = i+(unsigned short *) dind_bh->b_data;
  150.         retry |= trunc_indirect(inode,7+512+(i<<9),dind);
  151.         mark_buffer_dirty(dind_bh, 1);
  152.     }
  153.     dind = (unsigned short *) dind_bh->b_data;
  154.     for (i = 0; i < 512; i++)
  155.         if (*(dind++))
  156.             break;
  157.     if (i >= 512)
  158.         if (dind_bh->b_count != 1)
  159.             retry = 1;
  160.         else {
  161.             tmp = *p;
  162.             *p = 0;
  163.             inode->i_dirt = 1;
  164.             minix_free_block(inode->i_sb,tmp);
  165.         }
  166.     brelse(dind_bh);
  167.     return retry;
  168. }
  169.         
  170. void minix_truncate(struct inode * inode)
  171. {
  172.     int retry;
  173.  
  174.     if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
  175.          S_ISLNK(inode->i_mode)))
  176.         return;
  177.     while (1) {
  178.         retry = trunc_direct(inode);
  179.         retry |= trunc_indirect(inode,7,inode->u.minix_i.i_data+7);
  180.         retry |= trunc_dindirect(inode);
  181.         if (!retry)
  182.             break;
  183.         current->counter = 0;
  184.         schedule();
  185.     }
  186.     inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  187.     inode->i_dirt = 1;
  188. }
  189.