Annotation of linux/fs/ext/truncate.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.