Annotation of linux/fs/minix/truncate.c, revision 1.1.1.7

1.1       root        1: /*
                      2:  *  linux/fs/truncate.c
                      3:  *
1.1.1.6   root        4:  *  Copyright (C) 1991, 1992  Linus Torvalds
1.1       root        5:  */
                      6: 
1.1.1.6   root        7: #include <linux/errno.h>
1.1       root        8: #include <linux/sched.h>
                      9: #include <linux/minix_fs.h>
                     10: #include <linux/tty.h>
1.1.1.4   root       11: #include <linux/stat.h>
1.1.1.5   root       12: #include <linux/fcntl.h>
1.1       root       13: 
1.1.1.3   root       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)
1.1       root       28: {
1.1.1.7 ! root       29:        unsigned short * p;
        !            30:        struct buffer_head * bh;
        !            31:        int i, tmp;
        !            32:        int retry = 0;
1.1.1.3   root       33: #define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
1.1       root       34: 
1.1.1.3   root       35: repeat:
                     36:        for (i = DIRECT_BLOCK ; i < 7 ; i++) {
1.1.1.7 ! root       37:                p = i + inode->u.minix_i.i_data;
        !            38:                if (!(tmp = *p))
        !            39:                        continue;
        !            40:                bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
        !            41:                if (i < DIRECT_BLOCK) {
        !            42:                        brelse(bh);
1.1.1.3   root       43:                        goto repeat;
1.1.1.7 ! root       44:                }
        !            45:                if ((bh && bh->b_count != 1) || tmp != *p) {
        !            46:                        retry = 1;
        !            47:                        brelse(bh);
1.1.1.3   root       48:                        continue;
1.1.1.7 ! root       49:                }
        !            50:                *p = 0;
        !            51:                inode->i_dirt = 1;
        !            52:                brelse(bh);
        !            53:                minix_free_block(inode->i_dev,tmp);
1.1       root       54:        }
1.1.1.7 ! root       55:        return retry;
1.1       root       56: }
                     57: 
1.1.1.3   root       58: static int trunc_indirect(struct inode * inode, int offset, unsigned short * p)
1.1       root       59: {
1.1.1.7 ! root       60:        struct buffer_head * bh;
        !            61:        int i, tmp;
        !            62:        struct buffer_head * ind_bh;
1.1.1.3   root       63:        unsigned short * ind;
1.1.1.7 ! root       64:        int retry = 0;
1.1.1.3   root       65: #define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
                     66: 
1.1.1.7 ! root       67:        tmp = *p;
        !            68:        if (!tmp)
        !            69:                return 0;
        !            70:        ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
        !            71:        if (tmp != *p) {
        !            72:                brelse(ind_bh);
        !            73:                return 1;
        !            74:        }
        !            75:        if (!ind_bh) {
        !            76:                *p = 0;
1.1.1.3   root       77:                return 0;
1.1.1.7 ! root       78:        }
1.1.1.3   root       79: repeat:
                     80:        for (i = INDIRECT_BLOCK ; i < 512 ; i++) {
                     81:                if (i < 0)
                     82:                        i = 0;
                     83:                if (i < INDIRECT_BLOCK)
                     84:                        goto repeat;
1.1.1.7 ! root       85:                ind = i+(unsigned short *) ind_bh->b_data;
        !            86:                tmp = *ind;
        !            87:                if (!tmp)
1.1.1.3   root       88:                        continue;
1.1.1.7 ! root       89:                bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
        !            90:                if (i < INDIRECT_BLOCK) {
        !            91:                        brelse(bh);
        !            92:                        goto repeat;
        !            93:                }
        !            94:                if ((bh && bh->b_count != 1) || tmp != *ind) {
        !            95:                        retry = 1;
        !            96:                        brelse(bh);
        !            97:                        continue;
        !            98:                }
        !            99:                *ind = 0;
        !           100:                ind_bh->b_dirt = 1;
        !           101:                brelse(bh);
        !           102:                minix_free_block(inode->i_dev,tmp);
1.1       root      103:        }
1.1.1.7 ! root      104:        ind = (unsigned short *) ind_bh->b_data;
1.1.1.3   root      105:        for (i = 0; i < 512; i++)
                    106:                if (*(ind++))
                    107:                        break;
1.1.1.7 ! root      108:        if (i >= 512)
        !           109:                if (ind_bh->b_count != 1)
        !           110:                        retry = 1;
        !           111:                else {
        !           112:                        tmp = *p;
1.1.1.3   root      113:                        *p = 0;
1.1.1.7 ! root      114:                        minix_free_block(inode->i_dev,tmp);
        !           115:                }
        !           116:        brelse(ind_bh);
        !           117:        return retry;
1.1.1.3   root      118: }
                    119:                
                    120: static int trunc_dindirect(struct inode * inode)
                    121: {
1.1.1.7 ! root      122:        int i, tmp;
        !           123:        struct buffer_head * dind_bh;
        !           124:        unsigned short * dind, * p;
        !           125:        int retry = 0;
1.1.1.3   root      126: #define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
                    127: 
1.1.1.7 ! root      128:        p = 8 + inode->u.minix_i.i_data;
        !           129:        if (!(tmp = *p))
1.1       root      130:                return 0;
1.1.1.7 ! root      131:        dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
        !           132:        if (tmp != *p) {
        !           133:                brelse(dind_bh);
        !           134:                return 1;
        !           135:        }
        !           136:        if (!dind_bh) {
        !           137:                *p = 0;
        !           138:                return 0;
        !           139:        }
1.1.1.3   root      140: repeat:
                    141:        for (i = DINDIRECT_BLOCK ; i < 512 ; i ++) {
                    142:                if (i < 0)
                    143:                        i = 0;
                    144:                if (i < DINDIRECT_BLOCK)
                    145:                        goto repeat;
1.1.1.7 ! root      146:                dind = i+(unsigned short *) dind_bh->b_data;
        !           147:                retry |= trunc_indirect(inode,7+512+(i<<9),dind);
        !           148:                dind_bh->b_dirt = 1;
1.1.1.3   root      149:        }
1.1.1.7 ! root      150:        dind = (unsigned short *) dind_bh->b_data;
1.1.1.3   root      151:        for (i = 0; i < 512; i++)
                    152:                if (*(dind++))
                    153:                        break;
1.1.1.7 ! root      154:        if (i >= 512)
        !           155:                if (dind_bh->b_count != 1)
        !           156:                        retry = 1;
        !           157:                else {
        !           158:                        tmp = *p;
        !           159:                        *p = 0;
        !           160:                        inode->i_dirt = 1;
        !           161:                        minix_free_block(inode->i_dev,tmp);
        !           162:                }
        !           163:        brelse(dind_bh);
        !           164:        return retry;
1.1       root      165: }
1.1.1.3   root      166:                
1.1       root      167: void minix_truncate(struct inode * inode)
                    168: {
1.1.1.7 ! root      169:        int retry;
1.1       root      170: 
                    171:        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
                    172:             S_ISLNK(inode->i_mode)))
                    173:                return;
1.1.1.3   root      174:        while (1) {
1.1.1.7 ! root      175:                retry = trunc_direct(inode);
        !           176:                retry |= trunc_indirect(inode,7,inode->u.minix_i.i_data+7);
        !           177:                retry |= trunc_dindirect(inode);
        !           178:                if (!retry)
1.1.1.3   root      179:                        break;
1.1       root      180:                current->counter = 0;
                    181:                schedule();
                    182:        }
                    183:        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1.1.1.3   root      184:        inode->i_dirt = 1;
1.1       root      185: }
                    186: 
                    187: /*
                    188:  * Called when a inode is released. Note that this is different
                    189:  * from minix_open: open gets called at every open, but release
                    190:  * gets called only when /all/ the files are closed.
                    191:  */
                    192: void minix_release(struct inode * inode, struct file * filp)
                    193: {
                    194:        printk("minix_release not implemented\n");
                    195: }

unix.superglobalmegacorp.com

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