Annotation of linux/fs/ext/truncate.c, revision 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.