Re: [PATCH 3/3] More comments about block allocation/reservation code
"Randy.Dunlap" <[email protected]> Wed, 23 Aug 2006 12:32:46 -0700
| Newsgroups | gmane.comp.file-systems.ext2.devel |
|---|---|
| Organization | YPO4 |
| Message-ID | <[email protected]> |
On Wed, 23 Aug 2006 12:07:34 -0700 Mingming Cao wrote: > On Tue, 2006-08-22 at 21:18 -0700, Randy.Dunlap wrote: > > I would love to see you make all of these function comment blocks > > be in kernel-doc format, where each function's parameters are listed > > and described. However, that's up to you. But please don't mark them > > as being in kernel-doc format until they are. > > Thanks, Randy. > > Andrew, here is the updated patch.:) > > > Add more comments in block allocation/reservation code (in > ext3/balloc.c) Thanks. Mostly good. A few minor comments below. > Signed-Off-By: Mingming Cao <[email protected]> > > --- > > linux-2.6.18-rc4-ming/fs/ext3/balloc.c | 287 ++++++++++++++++++++++++++++----- > 1 files changed, 245 insertions(+), 42 deletions(-) > > diff -puN fs/ext3/balloc.c~ext3-balloc.c-comment-fix fs/ext3/balloc.c > --- linux-2.6.18-rc4/fs/ext3/balloc.c~ext3-balloc.c-comment-fix 2006-08-23 11:56:04.301528668 -0700 > +++ linux-2.6.18-rc4-ming/fs/ext3/balloc.c 2006-08-23 11:56:04.309527692 -0700 > @@ -38,6 +38,14 @@ > > #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) > > +/** > + * ext3_get_group_desc() -- load group descriptor from disk > + * Drop the "blank" line above. This mucks up the kernel-doc output. No blank lines between the function name and its parameter list. (Yes, I know that we need to fix that ugly perl script. It's on my long list.) > + * @sb: super block > + * @block_group: given block group > + * @bh: pointer to the buffer head to store the block > + * group descriptor > + */ > struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb, > unsigned int block_group, > struct buffer_head ** bh) > @@ -73,7 +81,11 @@ struct ext3_group_desc * ext3_get_group_ > return desc + offset; > } > > -/* > +/** > + * read_block_bitmap() > + * @sb: super block > + * @block_grpup given block grup @block_grpup (is that correct?) needs a colon ':' after it. and "grup" should be "group" ? > + * > * Read the bitmap for a given block_group, reading into the specified > * slot in the superblock's bitmap cache. > * > @@ -103,13 +115,20 @@ error_out: > * Operations include: > * dump, find, add, remove, is_empty, find_next_reservable_window, etc. > * > - * We use sorted double linked list for the per-filesystem reservation > - * window list. (like in vm_region). > + * We use a red-black tree to represent per-filesystem reservation > + * windows. > * > - * Initially, we keep those small operations in the abstract functions, > - * so later if we need a better searching tree than double linked-list, > - * we could easily switch to that without changing too much > - * code. > + */ > + > +/** > + * __rsv_window_dump() -- Dump the filesystem block allocation reservation map > + * @rb_root: root of per-filesystem reservation rb tree > + * @verbose: verbose mode > + * @fn: function which wishes to dump the reservation map > + * > + * If verbose is turned on, it will print the whole block reservation > + * windows(start, end). Otherwise, it will only print out the "bad" windows, > + * those windows overlaps with their immediate neighbors. s/overlaps/that overlap/ > */ > #if 1 > static void __rsv_window_dump(struct rb_root *root, int verbose, > @@ -161,6 +180,22 @@ restart: > #define rsv_window_dump(root, verbose) do {} while (0) > #endif > > +/** > + * goal_in_my_reservation() > + * @rsv: inode's reservation window > + * @grp_goal: given goal block relative to the allocation block group > + * @group: the current allocation block group > + * @sb: filesystem super block > + * > + * Test if the given goal block (group relative) is within the file's > + * own block reservation window range. > + * > + * If the reservation window is outside the goal allocation group, return 0; > + * grp_goal (given goal block) could be -1, which means no specific > + * goal block. In this case, always return 1. > + * If the goal block is within the reservation window, return 1; > + * otherwise, return 0; > + */ > static int > goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal, > unsigned int group, struct super_block * sb) > @@ -179,7 +214,11 @@ goal_in_my_reservation(struct ext3_reser > return 1; > } > > -/* > +/** > + * search_reserve_window() > + * @rb_root: root of reservation tree > + * @goal: target allocation block > + * > * Find the reserved window which includes the goal, or the previous one > * if the goal is not in any window. > * Returns NULL if there are no windows or if all windows start after the goal. > @@ -216,6 +255,13 @@ search_reserve_window(struct rb_root *ro > return rsv; > } > > +/** > + * ext3_rsv_window_add() -- Insert a window to the block reservation rb tree. > + * @sb: super block > + * @rsv: reservation window to add > + * > + * Must be called with rsv_lock hold. > + */ > void ext3_rsv_window_add(struct super_block *sb, > struct ext3_reserve_window_node *rsv) > { > @@ -246,6 +292,15 @@ void ext3_rsv_window_add(struct super_bl > rb_insert_color(node, root); > } > > +/** > + * ext3_rsv_window_remove() -- unlink a window from the reservation rb tree > + * @sb: super block > + * @rsv: reservation window to remove > + * > + * Mark the block reservation window as not allocated, and unlink it > + * from the filesystem reservation window rb tree. Must be called with > + * rsv_lock hold. > + */ > static void rsv_window_remove(struct super_block *sb, > struct ext3_reserve_window_node *rsv) > { > @@ -255,11 +310,39 @@ static void rsv_window_remove(struct sup > rb_erase(&rsv->rsv_node, &EXT3_SB(sb)->s_rsv_window_root); > } > > +/* > + * rsv_is_empty() -- Check if the reservation window is allocated. > + * @rsv: given reservation window to check > + * > + * returns 1 if the end block is EXT3_RESERVE_WINDOW_NOT_ALLOCATED. > + */ > static inline int rsv_is_empty(struct ext3_reserve_window *rsv) > { > /* a valid reservation end block could not be 0 */ > return (rsv->_rsv_end == EXT3_RESERVE_WINDOW_NOT_ALLOCATED); > } > + > +/** > + * ext3_init_block_alloc_info() > + * @inode: file inode structure > + * > + * Allocate and initialize the reservation window structure, and > + * link the window to the ext3 inode structure at last > + * > + * The reservation window structure is only dynamically allocated > + * and linked to ext3 inode the first time the open file > + * needs a new block. So, before every ext3_new_block(s) call, for > + * regular files, we should check whether the reservation window > + * structure exists or not. In the latter case, this function is called. > + * Fail to do so will result in block reservation being turned off for that > + * open file. > + * > + * This function is called from ext3_get_blocks_handle(), also called > + * when setting the reservation window size through ioctl before the file > + * is open for write (needs block allocation). > + * > + * Needs truncate_mutex protection prior to call this function. > + */ > void ext3_init_block_alloc_info(struct inode *inode) > { > struct ext3_inode_info *ei = EXT3_I(inode); > @@ -289,6 +372,19 @@ void ext3_init_block_alloc_info(struct i > ei->i_block_alloc_info = block_i; > } > > +/** > + * ext3_discard_reservation() > + * @inode: inode > + * > + * Discard(free) block reservation window on last file close, or truncate > + * or at last iput(). > + * > + * It is being called in three cases: > + * ext3_release_file(): last writer close the file > + * ext3_clear_inode(): last iput(), when nobody link to this file. > + * ext3_truncate(): when the block indirect map is about to change. > + * > + */ > void ext3_discard_reservation(struct inode *inode) > { > struct ext3_inode_info *ei = EXT3_I(inode); > @@ -308,7 +404,14 @@ void ext3_discard_reservation(struct ino > } > } > > -/* Free given blocks, update quota and i_blocks field */ > +/** > + * ext3_free_blocks_sb() -- Free given blocks and update quota > + * @handle handle to this transaction > + * @sb: super block > + * @block: start physcial block to free > + * @count number of blocks to free > + * @pdquot_freed_blocks pointer to quota Parameter names need a colon ':' after them (handle & pdquot_freed_blocks & count). > + */ > void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb, > ext3_fsblk_t block, unsigned long count, > unsigned long *pdquot_freed_blocks) > @@ -492,7 +595,13 @@ error_return: > return; > } > > -/* Free given blocks, update quota and i_blocks field */ > +/** > + * ext3_free_blocks() -- Free given blocks and update quota > + * @handle: handle for this transaction > + * @inode: inode > + * @block: start physical block to free > + * @count: number of blocks to count > + */ > void ext3_free_blocks(handle_t *handle, struct inode *inode, > ext3_fsblk_t block, unsigned long count) > { > @@ -510,7 +619,11 @@ void ext3_free_blocks(handle_t *handle, > return; > } > > -/* > +/** > + * ext3_test_allocatable() > + * @nr: given allocation block group > + * @bh: bufferhead contains the bitmap of the given block group > + * > * For ext3 allocations, we must not reuse any blocks which are > * allocated in the bitmap buffer's "last committed data" copy. This > * prevents deletes from freeing up the page for reuse until we have > @@ -543,6 +656,16 @@ static int ext3_test_allocatable(ext3_gr > return ret; > } > > +/** > + * bitmap_search_next_usable_block() > + * @start: the starting block (group relative) of the search > + * @bh: bufferhead contains the block group bitmap > + * @maxblocks: the ending block (group relative) of the reservation > + * > + * The bitmap search --- search forward alternately through the actual > + * bitmap on disk and the last-committed copy in journal, until we find a > + * bit free in both bitmaps. > + */ > static ext3_grpblk_t > bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh, > ext3_grpblk_t maxblocks) > @@ -550,11 +673,6 @@ bitmap_search_next_usable_block(ext3_grp > ext3_grpblk_t next; > struct journal_head *jh = bh2jh(bh); > > - /* > - * The bitmap search --- search forward alternately through the actual > - * bitmap and the last-committed copy until we find a bit free in > - * both > - */ > while (start < maxblocks) { > next = ext3_find_next_zero_bit(bh->b_data, maxblocks, start); > if (next >= maxblocks) > @@ -570,8 +688,14 @@ bitmap_search_next_usable_block(ext3_grp > return -1; > } > > -/* > - * Find an allocatable block in a bitmap. We honour both the bitmap and > +/** > + * find_next_usable_block() > + * @start: the starting block (group relative) to find next > + * allocatable block in bitmap. > + * @bh: bufferhead contains the block group bitmap > + * @maxblocks: the ending block (group relative) for the search > + * > + * Find an allocatable block in a bitmap. We honor both the bitmap and > * its last-committed copy (if that exists), and perform the "most > * appropriate allocation" algorithm of looking for a free block near > * the initial goal; then for a free byte somewhere in the bitmap; then > @@ -622,7 +746,11 @@ find_next_usable_block(ext3_grpblk_t sta > return here; > } > > -/* > +/** > + * claim_block() > + * @block: the free block (group relative) to allocate > + * @bh: the bufferhead containts the block group bitmap > + * > * We think we can allocate this block in this bitmap. Try to set the bit. > * If that succeeds then check that nobody has allocated and then freed the > * block since we saw that is was not marked in b_committed_data. If it _was_ > @@ -648,7 +776,26 @@ claim_block(spinlock_t *lock, ext3_grpbl > return ret; > } > > -/* > +/** > + * ext3_try_to_allocate() > + * @sb: superblock > + * @handle: handle to this transaction > + * @group: given allocation block group > + * @bitmap_bh: bufferhead holds the block bitmap > + * @grp_goal: given target block within the group > + * @count: target number of blocks to allocate > + * @my_rsv: reservation window > + * > + * Attempt to allocate blocks within a give range. Set the range of allocation > + * first, then find the first free bit(s) from the bitmap (within the range), > + * and at last, allocate the blocks by claiming the found free bit as allocated. > + * > + * To set the range of this allocation: > + * if there is a reservation window, only try to allocate block(s) from the > + * file's own reservation window; > + * Otherwise, the allocation range starts from the give goal block, ends at > + * the block group's last block. > + * > * If we failed to allocate the desired block then we may end up crossing to a > * new bitmap. In that case we must release write access to the old one via > * ext3_journal_release_buffer(), else we'll run out of credits. > @@ -705,7 +852,8 @@ repeat: > } > start = grp_goal; > > - if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) { > + if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), > + grp_goal, bitmap_bh)) { > /* > * The block was allocated by another thread, or it was > * allocated and then freed by another thread > @@ -720,7 +868,8 @@ repeat: > grp_goal++; > while (num < *count && grp_goal < end > && ext3_test_allocatable(grp_goal, bitmap_bh) > - && claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) { > + && claim_block(sb_bgl_lock(EXT3_SB(sb), group), > + grp_goal, bitmap_bh)) { > num++; > grp_goal++; > } > @@ -931,7 +1080,8 @@ static int alloc_new_reservation(struct > if ((my_rsv->rsv_alloc_hit > > (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) { > /* > - * if we previously allocation hit ration is greater than half > + * if we previously allocation hit ration is eh? > + * greater than half > * we double the size of reservation window next time > * otherwise keep the same > */ > @@ -1012,6 +1162,23 @@ retry: > goto retry; > } > > +/** > + * try_to_extend_reservation() > + * @my_rsv: given reservation window > + * @sb: super block > + * @size: the delta to extend > + * > + * Attempt to expand the reservation window large enough to have > + * required number of free blocks > + * > + * Since ext3_try_to_allocate() will always allocate blocks within > + * the reservation window range, if the window size is too small, > + * multiple blocks allocation has to stop at the end of the reservation > + * window. To make this more efficient, given the total number of > + * blocks needed and the current size of the window, we try to > + * expand the reservation window size if necessary on a best-effort > + * basis before ext3_new_blocks() tries to allocate blocks, > + */ > static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv, > struct super_block *sb, int size) > { > @@ -1037,7 +1204,17 @@ static void try_to_extend_reservation(st > spin_unlock(rsv_lock); > } > > -/* > +/** > + * ext3_try_to_allocate_with_rsv() > + * @sb: superblock > + * @handle: handle to this transaction > + * @group: given allocation block group > + * @bitmap_bh: bufferhead holds the block bitmap > + * @grp_goal: given target block within the group > + * @count: target number of blocks to allocate > + * @my_rsv: reservation window > + * @errp: pointer to store the error code > + * > * This is the main function used to allocate a new block and its reservation > * window. > * > @@ -1053,9 +1230,7 @@ static void try_to_extend_reservation(st > * reservation), and there are lots of free blocks, but they are all > * being reserved. > * > - * We use a sorted double linked list for the per-filesystem reservation list. > - * The insert, remove and find a free space(non-reserved) operations for the > - * sorted double linked list should be fast. > + * We use a red-black tree for the per-filesystem reservation list. > * > */ > static ext3_grpblk_t > @@ -1120,7 +1295,8 @@ ext3_try_to_allocate_with_rsv(struct sup > */ > while (1) { > if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) || > - !goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) { > + !goal_in_my_reservation(&my_rsv->rsv_window, > + grp_goal, group, sb)) { > if (my_rsv->rsv_goal_size < *count) > my_rsv->rsv_goal_size = *count; > ret = alloc_new_reservation(my_rsv, grp_goal, sb, > @@ -1128,19 +1304,22 @@ ext3_try_to_allocate_with_rsv(struct sup > if (ret < 0) > break; /* failed */ > > - if (!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) > + if (!goal_in_my_reservation(&my_rsv->rsv_window, > + grp_goal, group, sb)) > grp_goal = -1; > - } else if (grp_goal > 0 && (my_rsv->rsv_end-grp_goal+1) < *count) > + } else if (grp_goal > 0 && > + (my_rsv->rsv_end-grp_goal+1) < *count) > try_to_extend_reservation(my_rsv, sb, > *count-my_rsv->rsv_end + grp_goal - 1); > > - if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) > + if ((my_rsv->rsv_start >= group_first_block + > + EXT3_BLOCKS_PER_GROUP(sb)) > || (my_rsv->rsv_end < group_first_block)) { > rsv_window_dump(&EXT3_SB(sb)->s_rsv_window_root, 1); > BUG(); > } > - ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, grp_goal, > - &num, &my_rsv->rsv_window); > + ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, > + grp_goal, &num, &my_rsv->rsv_window); > if (ret >= 0) { > my_rsv->rsv_alloc_hit += num; > *count = num; > @@ -1165,6 +1344,12 @@ out: > return ret; > } > > +/** > + * ext3_has_free_blocks() > + * @sbi: in-core super block structure. > + * > + * Check if filesystem has at least 1 free block available for allocation. > + */ > static int ext3_has_free_blocks(struct ext3_sb_info *sbi) > { > ext3_fsblk_t free_blocks, root_blocks; > @@ -1179,11 +1364,17 @@ static int ext3_has_free_blocks(struct e > return 1; > } > > -/* > +/** > + * ext3_should_retry_alloc() > + * @sb: super block > + * @retries number of attemps has been made > + * > * ext3_should_retry_alloc() is called when ENOSPC is returned, and if > * it is profitable to retry the operation, this function will wait > * for the current or commiting transaction to complete, and then > * return TRUE. > + * > + * if the total number of retries exceed three times, return FALSE. > */ > int ext3_should_retry_alloc(struct super_block *sb, int *retries) > { > @@ -1195,13 +1386,19 @@ int ext3_should_retry_alloc(struct super > return journal_force_commit_nested(EXT3_SB(sb)->s_journal); > } > > -/* > - * ext3_new_block uses a goal block to assist allocation. If the goal is > - * free, or there is a free block within 32 blocks of the goal, that block > - * is allocated. Otherwise a forward search is made for a free block; within > - * each block group the search first looks for an entire free byte in the block > - * bitmap, and then for any free bit if that fails. > - * This function also updates quota and i_blocks field. > +/** > + * ext3_new_blocks() -- core block(s) allocation function > + * @handle: handle to this transaction > + * @inode: file inode > + * @goal: given target block(filesystem wide) > + * @count: target number of blocks to allocate > + * @errp: error code > + * > + * ext3_new_blocks uses a goal block to assist allocation. It tries to > + * allocate block(s) from the block group contains the goal block first. If that > + * fails, it will try to allocate block(s) from other block groups without > + * any specific goal block. > + * > */ > ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode, > ext3_fsblk_t goal, unsigned long *count, int *errp) > @@ -1432,7 +1629,7 @@ allocated: > > spin_lock(sb_bgl_lock(sbi, group_no)); > gdp->bg_free_blocks_count = > - cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - num); > + cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num); > spin_unlock(sb_bgl_lock(sbi, group_no)); > percpu_counter_mod(&sbi->s_freeblocks_counter, -num); > > @@ -1475,6 +1672,12 @@ ext3_fsblk_t ext3_new_block(handle_t *ha > return ext3_new_blocks(handle, inode, goal, &count, errp); > } > > +/** > + * ext3_count_free_blocks() -- count filesystem free blocks > + * @sb: superblock > + * > + * Adds up the number of free blocks from each block group. > + */ > ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb) > { > ext3_fsblk_t desc_count; --- ~Randy ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642