/* searches in journal structures for a given block number (bmap, off). If block is found in reiserfs journal it suggests next free block candidate to test. */ static inline int is_block_in_journal (struct super_block * s, int bmap, int off, int *next) { unsigned int tmp; if (reiserfs_in_journal (s, s->s_dev, bmap, off, s->s_blocksize, 1, &tmp)) { if (tmp) { /* hint supplied */ *next = tmp; PROC_INFO_INC( s, scan_bitmap.in_journal_hint ); } else { (*next) = off + 1; /* inc offset to avoid looping. */ PROC_INFO_INC( s, scan_bitmap.in_journal_nohint ); } PROC_INFO_INC( s, scan_bitmap.retry ); return 1; } return 0; }
/* The function is NOT SCHEDULE-SAFE! */ static int find_forward (struct super_block * s, int * bmap_nr, int * offset, int for_unformatted) { int i, j; struct buffer_head * bh; unsigned long block_to_try = 0; unsigned long next_block_to_try = 0 ; PROC_INFO_INC( s, find_forward.call ); for (i = *bmap_nr; i < SB_BMAP_NR (s); i ++, *offset = 0, PROC_INFO_INC( s, find_forward.bmap )) { /* get corresponding bitmap block */ bh = SB_AP_BITMAP (s)[i]; if (buffer_locked (bh)) { PROC_INFO_INC( s, find_forward.wait ); __wait_on_buffer (bh); } retry: j = reiserfs_find_next_zero_le_bit ((unsigned long *)bh->b_data, s->s_blocksize << 3, *offset); /* wow, this really needs to be redone. We can't allocate a block if ** it is in the journal somehow. reiserfs_in_journal makes a suggestion ** for a good block if the one you ask for is in the journal. Note, ** reiserfs_in_journal might reject the block it suggests. The big ** gain from the suggestion is when a big file has been deleted, and ** many blocks show free in the real bitmap, but are all not free ** in the journal list bitmaps. ** ** this whole system sucks. The bitmaps should reflect exactly what ** can and can't be allocated, and the journal should update them as ** it goes. TODO. */ if (j < (s->s_blocksize << 3)) { block_to_try = (i * (s->s_blocksize << 3)) + j; /* the block is not in the journal, we can proceed */ if (!(reiserfs_in_journal(s, s->s_dev, block_to_try, s->s_blocksize, for_unformatted, &next_block_to_try))) { *bmap_nr = i; *offset = j; return 1; } /* the block is in the journal */ else if ((j+1) < (s->s_blocksize << 3)) { /* try again */ /* reiserfs_in_journal suggested a new block to try */ if (next_block_to_try > 0) { int new_i ; get_bit_address (s, next_block_to_try, &new_i, offset); PROC_INFO_INC( s, find_forward.in_journal_hint ); /* block is not in this bitmap. reset i and continue ** we only reset i if new_i is in a later bitmap. */ if (new_i > i) { i = (new_i - 1 ); /* i gets incremented by the for loop */ PROC_INFO_INC( s, find_forward.in_journal_out ); continue ; } } else { /* no suggestion was made, just try the next block */ *offset = j+1 ; } PROC_INFO_INC( s, find_forward.retry ); goto retry ; } } } /* zero bit not found */ return 0; }