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

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: {
                     29:        int i;
1.1.1.3   root       30:        int result = 0;
                     31: #define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
1.1       root       32: 
1.1.1.3   root       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;
1.1       root       42:        }
1.1.1.3   root       43:        return result;
1.1       root       44: }
                     45: 
1.1.1.3   root       46: static int trunc_indirect(struct inode * inode, int offset, unsigned short * p)
1.1       root       47: {
                     48:        int i;
1.1.1.3   root       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)
1.1.1.6 ! root       55:                bh = bread(inode->i_dev, *p, BLOCK_SIZE);
1.1.1.3   root       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;
1.1       root       70:        }
1.1.1.3   root       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)
                     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])
1.1.1.6 ! root       93:                bh = bread(inode->i_dev, inode->i_data[8], BLOCK_SIZE);
1.1.1.3   root       94:        if (!bh)
1.1       root       95:                return 0;
1.1.1.3   root       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;
1.1       root      118: }
1.1.1.3   root      119:                
1.1       root      120: void minix_truncate(struct inode * inode)
                    121: {
1.1.1.3   root      122:        int flag;
1.1       root      123: 
                    124:        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
                    125:             S_ISLNK(inode->i_mode)))
                    126:                return;
1.1.1.3   root      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;
1.1       root      135:                current->counter = 0;
                    136:                schedule();
                    137:        }
                    138:        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1.1.1.3   root      139:        inode->i_dirt = 1;
1.1       root      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)
                    148: {
                    149:        printk("minix_release not implemented\n");
                    150: }

unix.superglobalmegacorp.com

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