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

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

unix.superglobalmegacorp.com

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