root/fs/minix/truncate.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. trunc_direct
  2. trunc_indirect
  3. trunc_dindirect
  4. minix_truncate
  5. minix_release

   1 /*
   2  *  linux/fs/truncate.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <linux/errno.h>
   8 #include <linux/sched.h>
   9 #include <linux/minix_fs.h>
  10 #include <linux/tty.h>
  11 #include <linux/stat.h>
  12 #include <linux/fcntl.h>
  13 
  14 /*
  15  * Truncate has the most races in the whole filesystem: coding it is
  16  * a pain in the a**. Especially as I don't do any locking...
  17  *
  18  * The code may look a bit weird, but that's just because I've tried to
  19  * handle things like file-size changes in a somewhat graceful manner.
  20  * Anyway, truncating a file at the same time somebody else writes to it
  21  * is likely to result in pretty weird behaviour...
  22  *
  23  * The new code handles normal truncates (size = 0) as well as the more
  24  * general case (size = XXX). I hope.
  25  */
  26 
  27 static int trunc_direct(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  28 {
  29         int i;
  30         int result = 0;
  31 #define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
  32 
  33 repeat:
  34         for (i = DIRECT_BLOCK ; i < 7 ; i++) {
  35                 if (i < DIRECT_BLOCK)
  36                         goto repeat;
  37                 if (!inode->i_data[i])
  38                         continue;
  39                 result = 1;
  40                 if (minix_free_block(inode->i_dev,inode->i_data[i]))
  41                         inode->i_data[i] = 0;
  42         }
  43         return result;
  44 }
  45 
  46 static int trunc_indirect(struct inode * inode, int offset, unsigned short * p)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         int i;
  49         struct buffer_head * bh = NULL;
  50         unsigned short * ind;
  51         int result = 0;
  52 #define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
  53 
  54         if (*p)
  55                 bh = bread(inode->i_dev, *p, BLOCK_SIZE);
  56         if (!bh)
  57                 return 0;
  58 repeat:
  59         for (i = INDIRECT_BLOCK ; i < 512 ; i++) {
  60                 if (i < 0)
  61                         i = 0;
  62                 if (i < INDIRECT_BLOCK)
  63                         goto repeat;
  64                 ind = i+(unsigned short *) bh->b_data;
  65                 if (!*ind)
  66                         continue;
  67                 result = 1;
  68                 if (minix_free_block(inode->i_dev,*ind))
  69                         *ind = 0;
  70         }
  71         ind = (unsigned short *) bh->b_data;
  72         for (i = 0; i < 512; i++)
  73                 if (*(ind++))
  74                         break;
  75         brelse(bh);
  76         if (i >= 512) {
  77                 result = 1;
  78                 if (minix_free_block(inode->i_dev,*p))
  79                         *p = 0;
  80         }
  81         return result;
  82 }
  83                 
  84 static int trunc_dindirect(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         int i;
  87         struct buffer_head * bh = NULL;
  88         unsigned short * dind;
  89         int result = 0;
  90 #define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
  91 
  92         if (inode->i_data[8])
  93                 bh = bread(inode->i_dev, inode->i_data[8], BLOCK_SIZE);
  94         if (!bh)
  95                 return 0;
  96 repeat:
  97         for (i = DINDIRECT_BLOCK ; i < 512 ; i ++) {
  98                 if (i < 0)
  99                         i = 0;
 100                 if (i < DINDIRECT_BLOCK)
 101                         goto repeat;
 102                 dind = i+(unsigned short *) bh->b_data;
 103                 if (!*dind)
 104                         continue;
 105                 result |= trunc_indirect(inode,7+512+(i<<9),dind);
 106         }
 107         dind = (unsigned short *) bh->b_data;
 108         for (i = 0; i < 512; i++)
 109                 if (*(dind++))
 110                         break;
 111         brelse(bh);
 112         if (i >= 512) {
 113                 result = 1;
 114                 if (minix_free_block(inode->i_dev,inode->i_data[8]))
 115                         inode->i_data[8] = 0;
 116         }
 117         return result;
 118 }
 119                 
 120 void minix_truncate(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122         int flag;
 123 
 124         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 125              S_ISLNK(inode->i_mode)))
 126                 return;
 127         if (inode->i_data[7] & 0xffff0000)
 128                 printk("BAD! minix inode has 16 high bits set\n");
 129         while (1) {
 130                 flag = trunc_direct(inode);
 131                 flag |= trunc_indirect(inode,7,(unsigned short *)&inode->i_data[7]);
 132                 flag |= trunc_dindirect(inode);
 133                 if (!flag)
 134                         break;
 135                 current->counter = 0;
 136                 schedule();
 137         }
 138         inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 139         inode->i_dirt = 1;
 140 }
 141 
 142 /*
 143  * Called when a inode is released. Note that this is different
 144  * from minix_open: open gets called at every open, but release
 145  * gets called only when /all/ the files are closed.
 146  */
 147 void minix_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 148 {
 149         printk("minix_release not implemented\n");
 150 }

/* [previous][next][first][last][top][bottom][index][help] */