--- linux/fs/ext/inode.c 2018/04/24 18:12:24 1.1.1.2 +++ linux/fs/ext/inode.c 2018/04/24 18:14:23 1.1.1.3 @@ -22,6 +22,14 @@ int sync_dev(int dev); +static inline void wait_on_buffer(struct buffer_head * bh) +{ + cli(); + while (bh->b_lock) + sleep_on(&bh->b_wait); + sti(); +} + void ext_put_inode(struct inode *inode) { inode->i_size = 0; @@ -31,24 +39,13 @@ void ext_put_inode(struct inode *inode) void ext_put_super(struct super_block *sb) { -#ifdef EXTFS_BITMAP - int i; -#endif lock_super(sb); sb->s_dev = 0; -#ifdef EXTFS_BITMAP - for(i = 0 ; i < EXT_I_MAP_SLOTS ; i++) - brelse(sb->u.ext_sb.s_imap[i]); - for(i = 0 ; i < EXT_Z_MAP_SLOTS ; i++) - brelse(sb->u.ext_sb.s_zmap[i]); -#endif -#ifdef EXTFS_FREELIST - if (sb->u.ext_sb.s_imap[1]) - brelse (sb->u.ext_sb.s_imap[1]); - if (sb->u.ext_sb.s_zmap[1]) - brelse (sb->u.ext_sb.s_zmap[1]); -#endif + if (sb->u.ext_sb.s_firstfreeinodeblock) + brelse (sb->u.ext_sb.s_firstfreeinodeblock); + if (sb->u.ext_sb.s_firstfreeblock) + brelse (sb->u.ext_sb.s_firstfreeblock); free_super(sb); return; } @@ -67,9 +64,6 @@ struct super_block *ext_read_super(struc struct buffer_head *bh; struct ext_super_block *es; int dev = s->s_dev,block; -#ifdef EXTFS_BITMAP - int i; -#endif lock_super(s); if (!(bh = bread(dev, 1, BLOCK_SIZE))) { @@ -78,26 +72,18 @@ struct super_block *ext_read_super(struc printk("bread failed\n"); return NULL; } -/* *((struct ext_super_block *) s) = - *((struct ext_super_block *) bh->b_data); */ es = (struct ext_super_block *) bh->b_data; s->s_blocksize = 1024; s->u.ext_sb.s_ninodes = es->s_ninodes; s->u.ext_sb.s_nzones = es->s_nzones; -#ifdef EXTFS_BITMAP - s->u.ext_sb.s_imap_blocks = es->s_imap_blocks; - s->u.ext_sb.s_zmap_blocks = es->s_zmap_blocks; -#endif s->u.ext_sb.s_firstdatazone = es->s_firstdatazone; s->u.ext_sb.s_log_zone_size = es->s_log_zone_size; s->u.ext_sb.s_max_size = es->s_max_size; s->s_magic = es->s_magic; -#ifdef EXTFS_FREELIST - s->u.ext_sb.s_zmap[0] = (struct buffer_head *) es->s_firstfreeblock; - s->u.ext_sb.s_zmap[2] = (struct buffer_head *) es->s_freeblockscount; - s->u.ext_sb.s_imap[0] = (struct buffer_head *) es->s_firstfreeinode; - s->u.ext_sb.s_imap[2] = (struct buffer_head *) es->s_freeinodescount; -#endif + s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock; + s->u.ext_sb.s_freeblockscount = es->s_freeblockscount; + s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode; + s->u.ext_sb.s_freeinodescount = es->s_freeinodescount; brelse(bh); if (s->s_magic != EXT_SUPER_MAGIC) { s->s_dev = 0; @@ -105,59 +91,28 @@ struct super_block *ext_read_super(struc printk("magic match failed\n"); return NULL; } -#ifdef EXTFS_BITMAP - for (i=0;i < EXT_I_MAP_SLOTS;i++) - s->u.ext_sb.s_imap[i] = NULL; - for (i=0;i < EXT_Z_MAP_SLOTS;i++) - s->u.ext_sb.s_zmap[i] = NULL; - block=2; - for (i=0 ; i < s->u.ext_sb.s_imap_blocks ; i++) - if (s->u.ext_sb.s_imap[i]=bread(dev, block, BLOCK_SIZE)) - block++; - else - break; - for (i=0 ; i < s->u.ext_sb.s_zmap_blocks ; i++) - if (s->u.ext_sb.s_zmap[i]=bread(dev, block, BLOCK_SIZE)) - block++; - else - break; - if (block != 2+s->u.ext_sb.s_imap_blocks+s->u.ext_sb.s_zmap_blocks) { - for(i=0;iu.ext_sb.s_imap[i]); - for(i=0;iu.ext_sb.s_zmap[i]); - s->s_dev=0; - free_super(s); - printk("block failed\n"); - return NULL; - } - s->u.ext_sb.s_imap[0]->b_data[0] |= 1; - s->u.ext_sb.s_zmap[0]->b_data[0] |= 1; -#endif -#ifdef EXTFS_FREELIST - if (!s->u.ext_sb.s_zmap[0]) - s->u.ext_sb.s_zmap[1] = NULL; + if (!s->u.ext_sb.s_firstfreeblocknumber) + s->u.ext_sb.s_firstfreeblock = NULL; else - if (!(s->u.ext_sb.s_zmap[1] = bread(dev, (unsigned long) s->u.ext_sb.s_zmap[0], BLOCK_SIZE))) { + if (!(s->u.ext_sb.s_firstfreeblock = bread(dev, + s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) { printk ("ext_read_super: unable to read first free block\n"); s->s_dev = 0; free_super(s); return NULL; } - if (!s->u.ext_sb.s_imap[0]) - s->u.ext_sb.s_imap[1] = NULL; + if (!s->u.ext_sb.s_firstfreeinodenumber) + s->u.ext_sb.s_firstfreeinodeblock = NULL; else { - block = 2 + (((unsigned long) s->u.ext_sb.s_imap[0]) - 1) / EXT_INODES_PER_BLOCK; - if (!(s->u.ext_sb.s_imap[1] = bread(dev, block, BLOCK_SIZE))) { + block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK; + if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) { printk ("ext_read_super: unable to read first free inode block\n"); - brelse(s->u.ext_sb.s_zmap[1]); + brelse(s->u.ext_sb.s_firstfreeblock); s->s_dev = 0; free_super (s); return NULL; } } -#endif - free_super(s); /* set up enough so that it can read an inode */ s->s_dev = dev; @@ -172,26 +127,21 @@ struct super_block *ext_read_super(struc void ext_write_super (struct super_block *sb) { -#ifdef EXTFS_FREELIST struct buffer_head * bh; struct ext_super_block * es; -#ifdef EXTFS_DEBUG - printk ("ext_write_super called\n"); -#endif if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) { printk ("ext_write_super: bread failed\n"); return; } es = (struct ext_super_block *) bh->b_data; - es->s_firstfreeblock = (unsigned long) sb->u.ext_sb.s_zmap[0]; - es->s_freeblockscount = (unsigned long) sb->u.ext_sb.s_zmap[2]; - es->s_firstfreeinode = (unsigned long) sb->u.ext_sb.s_imap[0]; - es->s_freeinodescount = (unsigned long) sb->u.ext_sb.s_imap[2]; + es->s_firstfreeblock = sb->u.ext_sb.s_firstfreeblocknumber; + es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount; + es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber; + es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount; bh->b_dirt = 1; brelse (bh); sb->s_dirt = 0; -#endif } void ext_statfs (struct super_block *sb, struct statfs *buf) @@ -200,7 +150,8 @@ void ext_statfs (struct super_block *sb, put_fs_long(EXT_SUPER_MAGIC, &buf->f_type); put_fs_long(1024, &buf->f_bsize); - put_fs_long(sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size, &buf->f_blocks); + put_fs_long(sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size, + &buf->f_blocks); tmp = ext_count_free_blocks(sb); put_fs_long(tmp, &buf->f_bfree); put_fs_long(tmp, &buf->f_bavail); @@ -209,130 +160,190 @@ void ext_statfs (struct super_block *sb, /* Don't know what value to put in buf->f_fsid */ } -static int _ext_bmap(struct inode * inode,int block,int create) +#define inode_bmap(inode,nr) ((inode)->u.ext_i.i_data[(nr)]) + +static int block_bmap(struct buffer_head * bh, int nr) +{ + int tmp; + + if (!bh) + return 0; + tmp = ((unsigned long *) bh->b_data)[nr]; + brelse(bh); + return tmp; +} + +int ext_bmap(struct inode * inode,int block) { - struct buffer_head * bh; int i; if (block<0) { - printk("_ext_bmap: block<0"); + printk("ext_bmap: block<0"); return 0; } if (block >= 9+256+256*256+256*256*256) { - printk("_ext_bmap: block>big"); + printk("ext_bmap: block>big"); return 0; } - if (block<9) { - if (create && !inode->i_data[block]) - if (inode->i_data[block]=ext_new_block(inode->i_dev)) { - inode->i_ctime=CURRENT_TIME; - inode->i_dirt=1; - } - return inode->i_data[block]; - } + if (block<9) + return inode_bmap(inode,block); block -= 9; if (block<256) { - if (create && !inode->i_data[9]) - if (inode->i_data[9]=ext_new_block(inode->i_dev)) { - inode->i_dirt=1; - inode->i_ctime=CURRENT_TIME; - } - if (!inode->i_data[9]) - return 0; - if (!(bh = bread(inode->i_dev, inode->i_data[9], BLOCK_SIZE))) + i = inode_bmap(inode,9); + if (!i) return 0; - i = ((unsigned long *) (bh->b_data))[block]; - if (create && !i) - if (i=ext_new_block(inode->i_dev)) { - ((unsigned long *) (bh->b_data))[block]=i; - bh->b_dirt=1; - } - brelse(bh); - return i; + return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block); } block -= 256; if (block<256*256) { - if (create && !inode->i_data[10]) - if (inode->i_data[10]=ext_new_block(inode->i_dev)) { - inode->i_dirt=1; - inode->i_ctime=CURRENT_TIME; - } - if (!inode->i_data[10]) - return 0; - if (!(bh=bread(inode->i_dev, inode->i_data[10], BLOCK_SIZE))) - return 0; - i = ((unsigned long *)bh->b_data)[block>>8]; - if (create && !i) - if (i=ext_new_block(inode->i_dev)) { - ((unsigned long *) (bh->b_data))[block>>8]=i; - bh->b_dirt=1; - } - brelse(bh); + i = inode_bmap(inode,10); if (!i) return 0; - if (!(bh=bread(inode->i_dev, i, BLOCK_SIZE))) + i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>8); + if (!i) return 0; - i = ((unsigned long *)bh->b_data)[block&255]; - if (create && !i) - if (i=ext_new_block(inode->i_dev)) { - ((unsigned long *) (bh->b_data))[block&255]=i; - bh->b_dirt=1; - } - brelse(bh); - return i; + return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255); } - if (create && !inode->i_data[11]) - if (inode->i_data[11] = ext_new_block(inode->i_dev)) { - inode->i_dirt = 1; - inode->i_ctime = CURRENT_TIME; - } - if (!inode->i_data[11]) - return 0; - if (!(bh = bread(inode->i_dev, inode->i_data[11], BLOCK_SIZE))) - return 0; - i = ((unsigned long *) bh->b_data)[block >> 16]; - if (create && !i) - if (i = ext_new_block(inode->i_dev)) { - ((unsigned long *) bh->b_data)[block >> 16] = i; - bh->b_dirt = 1; - } - brelse (bh); + block -= 256*256; + i = inode_bmap(inode,11); if (!i) return 0; - if (!(bh = bread(inode->i_dev, i, BLOCK_SIZE))) - return 0; - i = ((unsigned long *) bh->b_data)[(block >> 8) & 255]; - if (create && !i) - if (i = ext_new_block(inode->i_dev)) { - ((unsigned long *) bh->b_data)[(block >> 8) & 255] = i; - bh->b_dirt = 1; - } - brelse (bh); + i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>16); if (!i) return 0; - if (!(bh = bread(inode->i_dev, i, BLOCK_SIZE))) + i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block>>8) & 255); + if (!i) return 0; - i = ((unsigned long *) bh->b_data)[block & 255]; - if (create && !i) - if (i = ext_new_block(inode->i_dev)) { - ((unsigned long *) bh->b_data)[block & 255] = i; - bh->b_dirt = 1; + return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255); +} + +static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create) +{ + int tmp; + unsigned long * p; + struct buffer_head * result; + + p = inode->u.ext_i.i_data + nr; +repeat: + tmp = *p; + if (tmp) { + result = getblk(inode->i_dev, tmp, BLOCK_SIZE); + if (tmp == *p) + return result; + brelse(result); + goto repeat; + } + if (!create) + return NULL; + tmp = ext_new_block(inode->i_dev); + if (!tmp) + return NULL; + result = getblk(inode->i_dev, tmp, BLOCK_SIZE); + if (*p) { + ext_free_block(inode->i_dev,tmp); + brelse(result); + goto repeat; + } + *p = tmp; + inode->i_ctime = CURRENT_TIME; + inode->i_dirt = 1; + return result; +} + +static struct buffer_head * block_getblk(struct buffer_head * bh, int nr, int create) +{ + int tmp; + unsigned long * p; + struct buffer_head * result; + + if (!bh) + return NULL; + if (!bh->b_uptodate) { + ll_rw_block(READ,bh); + wait_on_buffer(bh); + if (!bh->b_uptodate) { + brelse(bh); + return NULL; } - brelse (bh); - return i; - - printk("ext_bmap: triple indirection not yet implemented\n"); - return 0; + } + p = nr + (unsigned long *) bh->b_data; +repeat: + tmp = *p; + if (tmp) { + result = getblk(bh->b_dev, tmp, BLOCK_SIZE); + if (tmp == *p) { + brelse(bh); + return result; + } + brelse(result); + goto repeat; + } + if (!create) { + brelse(bh); + return NULL; + } + tmp = ext_new_block(bh->b_dev); + if (!tmp) { + brelse(bh); + return NULL; + } + result = getblk(bh->b_dev, tmp, BLOCK_SIZE); + if (*p) { + ext_free_block(bh->b_dev,tmp); + brelse(result); + goto repeat; + } + *p = tmp; + bh->b_dirt = 1; + brelse(bh); + return result; } -int ext_bmap(struct inode * inode,int block) +struct buffer_head * ext_getblk(struct inode * inode, int block, int create) { - return _ext_bmap(inode,block,0); + struct buffer_head * bh; + + if (block<0) { + printk("ext_getblk: block<0\n"); + return NULL; + } + if (block >= 9+256+256*256+256*256*256) { + printk("ext_getblk: block>big\n"); + return NULL; + } + if (block<9) + return inode_getblk(inode,block,create); + block -= 9; + if (block<256) { + bh = inode_getblk(inode,9,create); + return block_getblk(bh,block,create); + } + block -= 256; + if (block<256*256) { + bh = inode_getblk(inode,10,create); + bh = block_getblk(bh,block>>8,create); + return block_getblk(bh,block & 255,create); + } + block -= 256*256; + bh = inode_getblk(inode,11,create); + bh = block_getblk(bh,block>>16,create); + bh = block_getblk(bh,(block>>8) & 255,create); + return block_getblk(bh,block & 255,create); } -int ext_create_block(struct inode * inode, int block) +struct buffer_head * ext_bread(struct inode * inode, int block, int create) { - return _ext_bmap(inode,block,1); + struct buffer_head * bh; + + bh = ext_getblk(inode,block,create); + if (!bh || bh->b_uptodate) + return bh; + ll_rw_block(READ,bh); + wait_on_buffer(bh); + if (bh->b_uptodate) + return bh; + brelse(bh); + return NULL; } void ext_read_inode(struct inode * inode) @@ -341,13 +352,7 @@ void ext_read_inode(struct inode * inode struct ext_inode * raw_inode; int block; -#ifdef EXTFS_BITMAP - block = 2 + inode->i_sb->u.ext_sb.s_imap_blocks + inode->i_sb->u.ext_sb.s_zmap_blocks + - (inode->i_ino-1)/EXT_INODES_PER_BLOCK; -#endif -#ifdef EXTFS_FREELIST block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK; -#endif if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) panic("unable to read i-node block"); raw_inode = ((struct ext_inode *) bh->b_data) + @@ -358,10 +363,11 @@ void ext_read_inode(struct inode * inode inode->i_nlink = raw_inode->i_nlinks; inode->i_size = raw_inode->i_size; inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time; + inode->i_blocks = inode->i_blksize = 0; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) inode->i_rdev = raw_inode->i_zone[0]; else for (block = 0; block < 12; block++) - inode->i_data[block] = raw_inode->i_zone[block]; + inode->u.ext_i.i_data[block] = raw_inode->i_zone[block]; brelse(bh); inode->i_op = NULL; if (S_ISREG(inode->i_mode)) @@ -376,9 +382,10 @@ void ext_read_inode(struct inode * inode inode->i_op = &ext_blkdev_inode_operations; else if (S_ISFIFO(inode->i_mode)) { inode->i_op = &ext_fifo_inode_operations; - inode->i_size = 0; inode->i_pipe = 1; + PIPE_BASE(*inode) = NULL; PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; + PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; } } @@ -389,13 +396,7 @@ void ext_write_inode(struct inode * inod struct ext_inode * raw_inode; int block; -#ifdef EXTFS_BITMAP - block = 2 + inode->i_sb->u.ext_sb.s_imap_blocks + inode->i_sb->u.ext_sb.s_zmap_blocks + - (inode->i_ino-1)/EXT_INODES_PER_BLOCK; -#endif -#ifdef EXTFS_FREELIST block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK; -#endif if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) panic("unable to read i-node block"); raw_inode = ((struct ext_inode *)bh->b_data) + @@ -409,7 +410,7 @@ void ext_write_inode(struct inode * inod if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_zone[0] = inode->i_rdev; else for (block = 0; block < 12; block++) - raw_inode->i_zone[block] = inode->i_data[block]; + raw_inode->i_zone[block] = inode->u.ext_i.i_data[block]; bh->b_dirt=1; inode->i_dirt=0; brelse(bh);