diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index c57612d443d058e840df3112fd721af8954b745a..72282043a8f465edf1b38b52b1d620496c7e1b8b 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -152,7 +152,7 @@ u64 ufs_frag_map(struct inode *inode, sector_t frag) return ret; } -static void ufs_clear_block(struct inode *inode, struct buffer_head *bh) +static void ufs_clear_frag(struct inode *inode, struct buffer_head *bh) { lock_buffer(bh); memset(bh->b_data, 0, inode->i_sb->s_blocksize); @@ -163,27 +163,52 @@ static void ufs_clear_block(struct inode *inode, struct buffer_head *bh) sync_dirty_buffer(bh); } -static struct buffer_head *ufs_inode_getfrag(struct inode *inode, - unsigned int fragment, unsigned int new_fragment, - unsigned int required, int *err, int metadata, - long *phys, int *new, struct page *locked_page) +static struct buffer_head * +ufs_clear_frags(struct inode *inode, sector_t beg, + unsigned int n) +{ + struct buffer_head *res, *bh; + sector_t end = beg + n; + + res = sb_getblk(inode->i_sb, beg); + ufs_clear_frag(inode, res); + for (++beg; beg < end; ++beg) { + bh = sb_getblk(inode->i_sb, beg); + ufs_clear_frag(inode, bh); + } + return res; +} + +/** + * ufs_inode_getfrag() - allocate new fragment(s) + * @inode - pointer to inode + * @fragment - number of `fragment' which hold pointer + * to new allocated fragment(s) + * @new_fragment - number of new allocated fragment(s) + * @required - how many fragment(s) we require + * @err - we set it if something wrong + * @phys - pointer to where we save physical number of new allocated fragments, + * NULL if we allocate not data(indirect blocks for example). + * @new - we set it if we allocate new block + * @locked_page - for ufs_new_fragments() + */ +static struct buffer_head * +ufs_inode_getfrag(struct inode *inode, unsigned int fragment, + sector_t new_fragment, unsigned int required, int *err, + long *phys, int *new, struct page *locked_page) { struct ufs_inode_info *ufsi = UFS_I(inode); - struct super_block * sb; - struct ufs_sb_private_info * uspi; + struct super_block *sb = inode->i_sb; + struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct buffer_head * result; unsigned block, blockoff, lastfrag, lastblock, lastblockoff; unsigned tmp, goal; __fs32 * p, * p2; - unsigned flags = 0; - UFSD("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n", - inode->i_ino, fragment, new_fragment, required); + UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, " + "metadata %d\n", inode->i_ino, fragment, + (unsigned long long)new_fragment, required, !phys); - sb = inode->i_sb; - uspi = UFS_SB(sb)->s_uspi; - - flags = UFS_SB(sb)->s_flags; /* TODO : to be done for write support if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) goto ufs2; @@ -198,7 +223,7 @@ static struct buffer_head *ufs_inode_getfrag(struct inode *inode, tmp = fs32_to_cpu(sb, *p); lastfrag = ufsi->i_lastfrag; if (tmp && fragment < lastfrag) { - if (metadata) { + if (!phys) { result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); if (tmp == fs32_to_cpu(sb, *p)) { UFSD("EXIT, result %u\n", tmp + blockoff); @@ -265,9 +290,8 @@ static struct buffer_head *ufs_inode_getfrag(struct inode *inode, return NULL; } - if (metadata) { - result = sb_getblk(inode->i_sb, tmp + blockoff); - ufs_clear_block(inode, result); + if (!phys) { + result = ufs_clear_frags(inode, tmp + blockoff, required); } else { *phys = tmp + blockoff; result = NULL; @@ -298,23 +322,35 @@ static struct buffer_head *ufs_inode_getfrag(struct inode *inode, */ } -static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_head *bh, - unsigned int fragment, unsigned int new_fragment, - unsigned int blocksize, int * err, int metadata, - long *phys, int *new, struct page *locked_page) +/** + * ufs_inode_getblock() - allocate new block + * @inode - pointer to inode + * @bh - pointer to block which hold "pointer" to new allocated block + * @fragment - number of `fragment' which hold pointer + * to new allocated block + * @new_fragment - number of new allocated fragment + * (block will hold this fragment and also uspi->s_fpb-1) + * @err - see ufs_inode_getfrag() + * @phys - see ufs_inode_getfrag() + * @new - see ufs_inode_getfrag() + * @locked_page - see ufs_inode_getfrag() + */ +static struct buffer_head * +ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, + unsigned int fragment, sector_t new_fragment, int *err, + long *phys, int *new, struct page *locked_page) { - struct super_block * sb; - struct ufs_sb_private_info * uspi; + struct super_block *sb = inode->i_sb; + struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct buffer_head * result; unsigned tmp, goal, block, blockoff; __fs32 * p; - sb = inode->i_sb; - uspi = UFS_SB(sb)->s_uspi; block = ufs_fragstoblks (fragment); blockoff = ufs_fragnum (fragment); - UFSD("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment); + UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n", + inode->i_ino, fragment, (unsigned long long)new_fragment, !phys); result = NULL; if (!bh) @@ -330,7 +366,7 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_ repeat: tmp = fs32_to_cpu(sb, *p); if (tmp) { - if (metadata) { + if (!phys) { result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); if (tmp == fs32_to_cpu(sb, *p)) goto out; @@ -355,9 +391,8 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_ } - if (metadata) { - result = sb_getblk(sb, tmp + blockoff); - ufs_clear_block(inode, result); + if (!phys) { + result = ufs_clear_frags(inode, tmp + blockoff, uspi->s_fpb); } else { *phys = tmp + blockoff; *new = 1; @@ -375,11 +410,12 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_ return result; } -/* - * This function gets the block which contains the fragment. +/** + * ufs_getfrag_bloc() - `get_block_t' function, interface between UFS and + * readpage, writepage and so on */ -int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) +int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) { struct super_block * sb = inode->i_sb; struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; @@ -421,15 +457,15 @@ int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_hea * it much more readable: */ #define GET_INODE_DATABLOCK(x) \ - ufs_inode_getfrag(inode, x, fragment, 1, &err, 0, &phys, &new, bh_result->b_page) + ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new, bh_result->b_page) #define GET_INODE_PTR(x) \ - ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, 1, NULL, NULL, bh_result->b_page) + ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL, bh_result->b_page) #define GET_INDIRECT_DATABLOCK(x) \ - ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ - &err, 0, &phys, &new, bh_result->b_page); + ufs_inode_getblock(inode, bh, x, fragment, \ + &err, &phys, &new, bh_result->b_page); #define GET_INDIRECT_PTR(x) \ - ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ - &err, 1, NULL, NULL, bh_result->b_page); + ufs_inode_getblock(inode, bh, x, fragment, \ + &err, NULL, NULL, bh_result->b_page); if (ptr < UFS_NDIR_FRAGMENT) { bh = GET_INODE_DATABLOCK(ptr);