/* preallocated blocks don't need to be run through journal_mark_freed */ static void reiserfs_free_prealloc_block (struct reiserfs_transaction_handle *th, struct inode *inode, b_blocknr_t block) { RFALSE(!th->t_super, "vs-4060: trying to free block on nonexistent device"); RFALSE(is_reusable (th->t_super, block, 1) == 0, "vs-4070: can not free such block"); BUG_ON (!th->t_trans_id); _reiserfs_free_block(th, inode, block, 1) ; }
void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long block) { struct super_block * s = th->t_super; RFALSE(!s, "vs-4061: trying to free block on nonexistent device"); RFALSE(is_reusable (s, block, 1) == 0, "vs-4071: can not free such block"); /* mark it before we clear it, just in case */ journal_mark_freed(th, s, block) ; _reiserfs_free_block(th, block) ; }
void reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *inode, b_blocknr_t block, int for_unformatted) { struct super_block * s = th->t_super; BUG_ON (!th->t_trans_id); RFALSE(!s, "vs-4061: trying to free block on nonexistent device"); RFALSE(is_reusable (s, block, 1) == 0, "vs-4071: can not free such block"); /* mark it before we clear it, just in case */ journal_mark_freed(th, s, block) ; _reiserfs_free_block(th, inode, block, for_unformatted) ; }
/* I wonder if it would be less modest now that we use journaling. -Hans */ void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long block) { struct super_block * s = th->t_super; struct reiserfs_super_block * rs; struct buffer_head * sbh; struct buffer_head ** apbh; int nr, offset; RFALSE(!s, "vs-4060: trying to free block on nonexistent device"); RFALSE(is_reusable (s, block, 1) == 0, "vs-4070: can not free such block"); PROC_INFO_INC( s, free_block ); rs = SB_DISK_SUPER_BLOCK (s); sbh = SB_BUFFER_WITH_SB (s); apbh = SB_AP_BITMAP (s); get_bit_address (s, block, &nr, &offset); /* mark it before we clear it, just in case */ journal_mark_freed(th, s, block) ; reiserfs_prepare_for_journal(s, apbh[nr], 1 ) ; /* clear bit for the given block in bit map */ if (!reiserfs_test_and_clear_le_bit (offset, apbh[nr]->b_data)) { reiserfs_warning ("vs-4080: reiserfs_free_block: " "free_block (%04x:%lu)[dev:blocknr]: bit already cleared\n", s->s_dev, block); } journal_mark_dirty (th, s, apbh[nr]); reiserfs_prepare_for_journal(s, sbh, 1) ; /* update super block */ set_sb_free_blocks( rs, sb_free_blocks(rs) + 1 ); journal_mark_dirty (th, s, sbh); s->s_dirt = 1; }
/* preallocated blocks don't need to be run through journal_mark_freed */ void reiserfs_free_prealloc_block (struct reiserfs_transaction_handle *th, unsigned long block) { RFALSE(!th->t_super, "vs-4060: trying to free block on nonexistent device"); RFALSE(is_reusable (th->t_super, block, 1) == 0, "vs-4070: can not free such block"); _reiserfs_free_block(th, block) ; }
static int do_reiserfs_new_blocknrs (struct reiserfs_transaction_handle *th, unsigned long * free_blocknrs, unsigned long search_start, int amount_needed, int priority, int for_unformatted, int for_prealloc) { struct super_block * s = th->t_super; int i, j; unsigned long * block_list_start = free_blocknrs; int init_amount_needed = amount_needed; unsigned long new_block = 0 ; if (SB_FREE_BLOCKS (s) < SPARE_SPACE && !priority) /* we can answer NO_DISK_SPACE being asked for new block with priority 0 */ return NO_DISK_SPACE; RFALSE( !s, "vs-4090: trying to get new block from nonexistent device"); RFALSE( search_start == MAX_B_NUM, "vs-4100: we are optimizing location based on " "the bogus location of a temp buffer (%lu).", search_start); RFALSE( amount_needed < 1 || amount_needed > 2, "vs-4110: amount_needed parameter incorrect (%d)", amount_needed); /* We continue the while loop if another process snatches our found * free block from us after we find it but before we successfully * mark it as in use */ while (amount_needed--) { /* skip over any blocknrs already gotten last time. */ if (*(free_blocknrs) != 0) { RFALSE( is_reusable (s, *free_blocknrs, 1) == 0, "vs-4120: bad blocknr on free_blocknrs list"); free_blocknrs++; continue; } /* look for zero bits in bitmap */ if (find_zero_bit_in_bitmap(s,search_start, &i, &j,for_unformatted) == 0) { if (find_zero_bit_in_bitmap(s,search_start,&i,&j, for_unformatted) == 0) { /* recode without the goto and without the if. It will require a duplicate for. This is worth the code clarity. Your way was admirable, and just a bit too clever in saving instructions.:-) I'd say create a new function, but that would slow things also, yes? -Hans */ free_and_return: for ( ; block_list_start != free_blocknrs; block_list_start++) { reiserfs_free_block (th, *block_list_start); *block_list_start = 0; } if (for_prealloc) return NO_MORE_UNUSED_CONTIGUOUS_BLOCKS; else return NO_DISK_SPACE; } } /* i and j now contain the results of the search. i = bitmap block number containing free block, j = offset in this block. we compute the blocknr which is our result, store it in free_blocknrs, and increment the pointer so that on the next loop we will insert into the next location in the array. Also in preparation for the next loop, search_start is changed so that the next search will not rescan the same range but will start where this search finished. Note that while it is possible that schedule has occurred and blocks have been freed in that range, it is perhaps more important that the blocks returned be near each other than that they be near their other neighbors, and it also simplifies and speeds the code this way. */ /* journal: we need to make sure the block we are giving out is not ** a log block, horrible things would happen there. */ new_block = (i * (s->s_blocksize << 3)) + j; if (for_prealloc && (new_block - 1) != search_start) { /* preallocated blocks must be contiguous, bail if we didnt find one. ** this is not a bug. We want to do the check here, before the ** bitmap block is prepared, and before we set the bit and log the ** bitmap. ** ** If we do the check after this function returns, we have to ** call reiserfs_free_block for new_block, which would be pure ** overhead. ** ** for_prealloc should only be set if the caller can deal with the ** NO_MORE_UNUSED_CONTIGUOUS_BLOCKS return value. This can be ** returned before the disk is actually full */ goto free_and_return ; } search_start = new_block ; if (search_start >= reiserfs_get_journal_block(s) && search_start < (reiserfs_get_journal_block(s) + JOURNAL_BLOCK_COUNT)) { reiserfs_warning("vs-4130: reiserfs_new_blocknrs: trying to allocate log block %lu\n", search_start) ; search_start++ ; amount_needed++ ; continue ; } reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[i], 1) ; RFALSE( buffer_locked (SB_AP_BITMAP (s)[i]) || is_reusable (s, search_start, 0) == 0, "vs-4140: bitmap block is locked or bad block number found"); /* if this bit was already set, we've scheduled, and someone else ** has allocated it. loop around and try again */ if (reiserfs_test_and_set_le_bit (j, SB_AP_BITMAP (s)[i]->b_data)) { reiserfs_warning("vs-4150: reiserfs_new_blocknrs, block not free"); reiserfs_restore_prepared_buffer(s, SB_AP_BITMAP(s)[i]) ; amount_needed++ ; continue ; } journal_mark_dirty (th, s, SB_AP_BITMAP (s)[i]); *free_blocknrs = search_start ; free_blocknrs ++; } reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ; /* update free block count in super block */ PUT_SB_FREE_BLOCKS( s, SB_FREE_BLOCKS(s) - init_amount_needed ); journal_mark_dirty (th, s, SB_BUFFER_WITH_SB (s)); s->s_dirt = 1; return CARRY_ON; }