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

1.1       root        1: /*
                      2:  *  linux/fs/ext/freelists.c
                      3:  *
                      4:  *  (C) 1992  Remy Card ([email protected])
                      5:  *
                      6:  */
                      7: 
                      8: /* freelists.c contains the code that handles the inode and block free lists */
                      9: 
                     10: 
                     11: /*
                     12: 
                     13:    The free blocks are managed by a linked list. The super block contains the
                     14:    number of the first free block. This block contains 254 numbers of other
                     15:    free blocks and the number of the next block in the list.
                     16: 
                     17:    When an ext fs is mounted, the number of the first free block is stored
                     18:    in s->s_zmap[0] and the block header is stored in s->s_zmap[1]. s_zmap[2]
                     19:    contains the count of free blocks.
                     20: 
                     21:    Currently, it is a hack to allow this kind of management with the super_block
                     22:    structure.
                     23:    Perhaps, in the future, we may have to change the super_block structure to
                     24:    include dedicated fields.
                     25: 
                     26:    The free inodes are also managed by a linked list in a similar way. The
                     27:    super block contains the number of the first free inode. This inode contains
                     28:    14 numbers of other free inodes and the number of the next inode in the list.
                     29:    
                     30:    The number of the first free inode is stored in s->s_imap[0] and the header
                     31:    of the block containing the inode is stored in s->s_imap[1]. s_imap[2] contains
                     32:    the count of free inodes.
                     33: 
                     34: */
                     35: 
                     36: #include <linux/string.h>
                     37: 
                     38: #include <linux/sched.h>
                     39: #include <linux/ext_fs.h>
                     40: #include <linux/kernel.h>
                     41: 
                     42: #ifdef EXTFS_FREELIST
                     43: 
                     44: #define clear_block(addr) \
                     45: __asm__("cld\n\t" \
                     46:         "rep\n\t" \
                     47:         "stosl" \
                     48:         ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
                     49: 
                     50: int ext_free_block(int dev, int block)
                     51: {
                     52:        struct super_block * sb;
                     53:        struct buffer_head * bh;
                     54:        struct ext_free_block * efb;
                     55: 
                     56:        if (!(sb = get_super(dev)))
                     57:                panic("trying to free block on nonexistent device");
                     58:        lock_super (sb);
                     59:        if (block < sb->s_firstdatazone || block >= sb->s_nzones)
                     60:                panic("trying to free block not in datazone");
                     61:        bh = get_hash_table(dev,block);
                     62:        if (bh) {
                     63:                if (bh->b_count > 1) {
                     64:                        brelse(bh);
                     65:                        free_super (sb);
                     66:                        return 0;
                     67:                }
                     68:                bh->b_dirt=0;
                     69:                bh->b_uptodate=0;
                     70:                if (bh->b_count)
                     71:                        brelse(bh);
                     72:        }
                     73:        efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
                     74:        if (efb->count == 254) {
                     75: #ifdef EXTFS_DEBUG
                     76: printk("ext_free_block: block full, skipping to %d\n", block);
                     77: #endif
                     78:                brelse (sb->s_zmap[1]);
                     79:                if (!(sb->s_zmap[1] = bread (dev, block)))
                     80:                        panic ("ext_free_block: unable to read block to free\n");
                     81:                efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
                     82:                efb->next = (unsigned long) sb->s_zmap[0];
                     83:                efb->count = 0;
                     84:                sb->s_zmap[0] = (struct buffer_head *) block;
                     85:        } else {
                     86:                efb->free[efb->count++] = block;
                     87:        }
                     88:        sb->s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->s_zmap[2]) + 1);
                     89:        sb->s_dirt = 1;
                     90:        sb->s_zmap[1]->b_dirt = 1;
                     91:        free_super (sb);
                     92:        return 1;
                     93: }
                     94: 
                     95: int ext_new_block(int dev)
                     96: {
                     97:        struct buffer_head * bh;
                     98:        struct super_block * sb;
                     99:        struct ext_free_block * efb;
                    100:        int /* i, */ j;
                    101: 
                    102:        if (!(sb = get_super(dev)))
                    103:                panic("trying to get new block from nonexistant device");
                    104:        if (!sb->s_zmap[1])
                    105:                return 0;
                    106:        lock_super (sb);
                    107:        efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
                    108:        if (efb->count) {
                    109:                j = efb->free[--efb->count];
                    110:                sb->s_zmap[1]->b_dirt = 1;
                    111:        } else {
                    112: #ifdef EXTFS_DEBUG
                    113: printk("ext_new_block: block empty, skipping to %d\n", efb->next);
                    114: #endif
                    115:                j = (unsigned long) sb->s_zmap[0];
                    116:                sb->s_zmap[0] = (struct buffer_head *) efb->next;
                    117:                brelse (sb->s_zmap[1]);
                    118:                if (!sb->s_zmap[0]) {
                    119:                        sb->s_zmap[1] = NULL;
                    120:                } else {
                    121:                        if (!(sb->s_zmap[1] = bread (dev, (unsigned long) sb->s_zmap[0])))
                    122:                                panic ("ext_new_block: unable to read next free block\n");
                    123:                }
                    124:        }
                    125:        if (j < sb->s_firstdatazone || j > sb->s_nzones) {
                    126:                printk ("ext_new_block: blk = %d\n", j);
                    127:                panic ("allocating block not in data zone\n");
                    128:        }
                    129:        sb->s_zmap[2] = (struct buffer_head *) (((unsigned long) sb->s_zmap[2]) - 1);
                    130:        sb->s_dirt = 1;
                    131: 
                    132:        if (!(bh=getblk(dev,j)))
                    133:                panic("new_block: cannot get block");
                    134:        if (bh->b_count != 1)
                    135:                panic("new block: count is != 1");
                    136:        clear_block(bh->b_data);
                    137:        bh->b_uptodate = 1;
                    138:        bh->b_dirt = 1;
                    139:        brelse(bh);
                    140: #ifdef EXTFS_DEBUG
                    141: printk("ext_new_block: allocating block %d\n", j);
                    142: #endif
                    143:        free_super (sb);
                    144:        return j;
                    145: }
                    146: 
                    147: unsigned long ext_count_free_blocks(struct super_block *sb)
                    148: {
                    149: #ifdef EXTFS_DEBUG
                    150:        struct buffer_head * bh;
                    151:        struct ext_free_block * efb;
                    152:        unsigned long count, block;
                    153: 
                    154:        lock_super (sb);
                    155:        if (!sb->s_zmap[1])
                    156:                count = 0;
                    157:        else {
                    158:                efb = (struct ext_free_block *) sb->s_zmap[1]->b_data;
                    159:                count = efb->count + 1;
                    160:                block = efb->next;
                    161:                while (block) {
                    162:                        if (!(bh = bread (sb->s_dev, block))) {
                    163:                                printk ("ext_count_free: error while reading free blocks list\n");
                    164:                                block = 0;
                    165:                        } else {
                    166:                                efb = (struct ext_free_block *) bh->b_data;
                    167:                                count += efb->count + 1;
                    168:                                block = efb->next;
                    169:                                brelse (bh);
                    170:                        }
                    171:                }
                    172:        }
                    173: printk("ext_count_free_blocks: stored = %d, computed = %d\n",
                    174:        (unsigned long) sb->s_zmap[2], count);
                    175:        free_super (sb);
                    176:        return count;
                    177: #else
                    178:        return (unsigned long) sb->s_zmap[2];
                    179: #endif
                    180: }
                    181: 
                    182: void ext_free_inode(struct inode * inode)
                    183: {
                    184:        struct buffer_head * bh;
                    185:        struct ext_free_inode * efi;
                    186:        unsigned long block;
                    187: 
                    188:        if (!inode)
                    189:                return;
                    190:        if (!inode->i_dev) {
                    191:                memset(inode,0,sizeof(*inode));
                    192:                return;
                    193:        }
                    194:        if (inode->i_count>1) {
                    195:                printk("free_inode: inode has count=%d\n",inode->i_count);
                    196:                return;
                    197:        }
                    198:        if (inode->i_nlink) {
                    199:                printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
                    200:                return;
                    201:        }
                    202:        if (!inode->i_sb) {
                    203:                printk("free_inode: inode on nonexistent device\n");
                    204:                return;
                    205:        }
                    206:        lock_super (inode->i_sb);
                    207:        if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->s_ninodes) {
                    208:                printk("free_inode: inode 0 or nonexistent inode\n");
                    209:                free_super (inode->i_sb);
                    210:                return;
                    211:        }
                    212:        efi = ((struct ext_free_inode *) inode->i_sb->s_imap[1]->b_data) +
                    213:                (((unsigned long) inode->i_sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK;
                    214:        if (efi->count == 14) {
                    215: #ifdef EXTFS_DEBUG
                    216: printk("ext_free_inode: inode full, skipping to %d\n", inode->i_ino);
                    217: #endif
                    218:                brelse (inode->i_sb->s_imap[1]);
                    219:                block = 2 + (inode->i_ino - 1) / EXT_INODES_PER_BLOCK;
                    220:                if (!(bh = bread(inode->i_dev, block)))
                    221:                        panic("ext_free_inode: unable to read inode block\n");
                    222:                efi = ((struct ext_free_inode *) bh->b_data) +
                    223:                        (inode->i_ino - 1) % EXT_INODES_PER_BLOCK;
                    224:                efi->next = (unsigned long) inode->i_sb->s_imap[0];
                    225:                efi->count = 0;
                    226:                inode->i_sb->s_imap[0] = (struct buffer_head *) inode->i_ino;
                    227:                inode->i_sb->s_imap[1] = bh;
                    228:        } else {
                    229:                efi->free[efi->count++] = inode->i_ino;
                    230:        }
                    231:        inode->i_sb->s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->s_imap[2]) + 1);
                    232:        inode->i_sb->s_dirt = 1;
                    233:        inode->i_sb->s_imap[1]->b_dirt = 1;
                    234:        free_super (inode->i_sb);
                    235:        memset(inode,0,sizeof(*inode));
                    236: }
                    237: 
                    238: struct inode * ext_new_inode(int dev)
                    239: {
                    240:        struct inode * inode;
                    241:        struct ext_free_inode * efi;
                    242:        unsigned long block;
                    243:        int /* i, */ j;
                    244: 
                    245:        if (!(inode=get_empty_inode()))
                    246:                return NULL;
                    247:        if (!(inode->i_sb = get_super(dev))) {
                    248:                printk("new_inode: unknown device\n");
                    249:                iput(inode);
                    250:                return NULL;
                    251:        }
                    252:        if (!inode->i_sb->s_imap[1])
                    253:                return 0;
                    254:        lock_super (inode->i_sb);
                    255:        efi = ((struct ext_free_inode *) inode->i_sb->s_imap[1]->b_data) +
                    256:                (((unsigned long) inode->i_sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK;
                    257:        if (efi->count) {
                    258:                j = efi->free[--efi->count];
                    259:                inode->i_sb->s_imap[1]->b_dirt = 1;
                    260:        } else {
                    261: #ifdef EXTFS_DEBUG
                    262: printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
                    263: #endif
                    264:                j = (unsigned long) inode->i_sb->s_imap[0];
                    265:                if (efi->next < 1 || efi->next > inode->i_sb->s_ninodes) {
                    266:                        printk ("efi->next = %d\n", efi->next);
                    267:                        panic ("ext_new_inode: bad inode number in free list\n");
                    268:                }
                    269:                inode->i_sb->s_imap[0] = (struct buffer_head *) efi->next;
                    270:                block = 2 + (((unsigned long) efi->next) - 1) / EXT_INODES_PER_BLOCK;
                    271:                brelse (inode->i_sb->s_imap[1]);
                    272:                if (!inode->i_sb->s_imap[0]) {
                    273:                        inode->i_sb->s_imap[1] = NULL;
                    274:                } else {
                    275:                        if (!(inode->i_sb->s_imap[1] = bread (dev, block)))
                    276:                                panic ("ext_new_inode: unable to read next free inode block\n");
                    277:                }
                    278:        }
                    279:        inode->i_sb->s_imap[2] = (struct buffer_head *) (((unsigned long) inode->i_sb->s_imap[2]) - 1);
                    280:        inode->i_sb->s_dirt = 1;
                    281:        inode->i_count = 1;
                    282:        inode->i_nlink = 1;
                    283:        inode->i_dev = dev;
                    284:        inode->i_uid = current->euid;
                    285:        inode->i_gid = current->egid;
                    286:        inode->i_dirt = 1;
                    287:        inode->i_ino = j;
                    288:        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
                    289:        inode->i_op = NULL;
                    290: #ifdef EXTFS_DEBUG
                    291: printk("ext_new_inode : allocating inode %d\n", inode->i_ino);
                    292: #endif
                    293:        free_super (inode->i_sb);
                    294:        return inode;
                    295: }
                    296: 
                    297: unsigned long ext_count_free_inodes(struct super_block *sb)
                    298: {
                    299: #ifdef EXTFS_DEBUG
                    300:        struct buffer_head * bh;
                    301:        struct ext_free_inode * efi;
                    302:        unsigned long count, block, ino;
                    303: 
                    304:        lock_super (sb);
                    305:        if (!sb->s_imap[1])
                    306:                count = 0;
                    307:        else {
                    308:                efi = ((struct ext_free_inode *) sb->s_imap[1]->b_data) +
                    309:                        ((((unsigned long) sb->s_imap[0])-1)%EXT_INODES_PER_BLOCK);
                    310:                count = efi->count + 1;
                    311:                ino = efi->next;
                    312:                while (ino) {
                    313:                        if (ino < 1 || ino > sb->s_ninodes) {
                    314:                                printk ("s_imap[0] = %d, ino = %d\n", 
                    315:                                        (int) sb->s_imap[0],ino);
                    316:                                panic ("ext_count_fre_inodes: bad inode number in free list\n");
                    317:                        }
                    318:                        block = 2 + ((ino - 1) / EXT_INODES_PER_BLOCK);
                    319:                        if (!(bh = bread (sb->s_dev, block))) {
                    320:                                printk ("ext_count_free_inodes: error while reading free inodes list\n");
                    321:                                block = 0;
                    322:                        } else {
                    323:                                efi = ((struct ext_free_inode *) bh->b_data) +
                    324:                                        ((ino - 1) % EXT_INODES_PER_BLOCK);
                    325:                                count += efi->count + 1;
                    326:                                ino = efi->next;
                    327:                                brelse (bh);
                    328:                        }
                    329:                }
                    330:        }
                    331: printk("ext_count_free_inodes: stored = %d, computed = %d\n",
                    332:        (unsigned long) sb->s_imap[2], count);
                    333:        free_super (sb);
                    334:        return count;
                    335: #else
                    336:        return (unsigned long) sb->s_imap[2];
                    337: #endif
                    338: }
                    339: 
                    340: #endif

unix.superglobalmegacorp.com

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