patch-2.4.7 linux/fs/reiserfs/journal.c
Next file: linux/fs/reiserfs/namei.c
Previous file: linux/fs/reiserfs/inode.c
Back to the patch index
Back to the overall index
- Lines: 417
- Date:
Wed Jul 18 07:46:02 2001
- Orig file:
v2.4.6/linux/fs/reiserfs/journal.c
- Orig date:
Tue Jul 3 17:08:21 2001
diff -u --recursive --new-file v2.4.6/linux/fs/reiserfs/journal.c linux/fs/reiserfs/journal.c
@@ -114,11 +114,7 @@
static int reiserfs_clean_and_file_buffer(struct buffer_head *bh) {
if (bh) {
clear_bit(BH_Dirty, &bh->b_state) ;
-#if 0
- if (bh->b_list != BUF_CLEAN) {
- reiserfs_file_buffer(bh, BUF_CLEAN) ;
- }
-#endif
+ refile_buffer(bh) ;
}
return 0 ;
}
@@ -711,7 +707,7 @@
}
ll_rw_block(WRITE, 1, &tbh) ;
count++ ;
- atomic_dec(&(tbh->b_count)) ; /* once for our get_hash */
+ put_bh(tbh) ; /* once for our get_hash */
}
}
@@ -726,7 +722,7 @@
if (!buffer_uptodate(tbh)) {
reiserfs_panic(s, "journal-601, buffer write failed\n") ;
}
- atomic_dec(&(tbh->b_count)) ; /* once for our get_hash */
+ put_bh(tbh) ; /* once for our get_hash */
bforget(tbh) ; /* once due to original getblk in do_journal_end */
atomic_dec(&(jl->j_commit_left)) ;
}
@@ -873,9 +869,11 @@
}
mark_buffer_uptodate(bh, uptodate) ;
unlock_buffer(bh) ;
+ put_bh(bh) ;
}
static void submit_logged_buffer(struct buffer_head *bh) {
lock_buffer(bh) ;
+ get_bh(bh) ;
bh->b_end_io = reiserfs_end_buffer_io_sync ;
mark_buffer_notjournal_new(bh) ;
clear_bit(BH_Dirty, &bh->b_state) ;
@@ -971,13 +969,13 @@
/* we do this to make sure nobody releases the buffer while
** we are working with it
*/
- atomic_inc(&(saved_bh->b_count)) ;
+ get_bh(saved_bh) ;
if (buffer_journal_dirty(saved_bh)) {
was_jwait = 1 ;
mark_buffer_notjournal_dirty(saved_bh) ;
- /* brelse the inc from journal_mark_dirty */
- atomic_dec(&(saved_bh->b_count)) ;
+ /* undo the inc from journal_mark_dirty */
+ put_bh(saved_bh) ;
}
if (can_dirty(cn)) {
was_dirty = 1 ;
@@ -1020,7 +1018,7 @@
}
if (was_dirty) {
/* we inc again because saved_bh gets decremented at free_cnode */
- atomic_inc(&(saved_bh->b_count)) ;
+ get_bh(saved_bh) ;
set_bit(BLOCK_NEEDS_FLUSH, &cn->state) ;
submit_logged_buffer(saved_bh) ;
count++ ;
@@ -1033,7 +1031,7 @@
cn = cn->next ;
if (saved_bh) {
/* we incremented this to keep others from taking the buffer head away */
- atomic_dec(&(saved_bh->b_count));
+ put_bh(saved_bh) ;
if (atomic_read(&(saved_bh->b_count)) < 0) {
printk("journal-945: saved_bh->b_count < 0") ;
}
@@ -1889,6 +1887,7 @@
memset(journal_writers, 0, sizeof(char *) * 512) ; /* debug code */
INIT_LIST_HEAD(&SB_JOURNAL(p_s_sb)->j_bitmap_nodes) ;
+ INIT_LIST_HEAD(&(SB_JOURNAL(p_s_sb)->j_dummy_inode.i_dirty_buffers)) ;
reiserfs_allocate_list_bitmaps(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_bitmap,
SB_BMAP_NR(p_s_sb)) ;
allocate_bitmap_nodes(p_s_sb) ;
@@ -2179,7 +2178,7 @@
cn->jlist = NULL ;
insert_journal_hash(SB_JOURNAL(p_s_sb)->j_hash_table, cn) ;
if (!count_already_incd) {
- atomic_inc(&(bh->b_count)) ;
+ get_bh(bh) ;
}
}
cn->next = NULL ;
@@ -2251,7 +2250,7 @@
if (!already_cleaned) {
mark_buffer_notjournal_dirty(bh) ;
- atomic_dec(&(bh->b_count)) ;
+ put_bh(bh) ;
if (atomic_read(&(bh->b_count)) < 0) {
printk("journal-1752: remove from trans, b_count < 0\n") ;
}
@@ -2582,11 +2581,8 @@
** in the current trans
*/
mark_buffer_notjournal_dirty(cn->bh) ;
- if (!buffer_locked(cn->bh)) {
- reiserfs_clean_and_file_buffer(cn->bh) ;
- }
cleaned = 1 ;
- atomic_dec(&(cn->bh->b_count)) ;
+ put_bh(cn->bh) ;
if (atomic_read(&(cn->bh->b_count)) < 0) {
printk("journal-2138: cn->bh->b_count < 0\n") ;
}
@@ -2602,7 +2598,8 @@
}
if (bh) {
- atomic_dec(&(bh->b_count)) ; /* get_hash incs this */
+ reiserfs_clean_and_file_buffer(bh) ;
+ put_bh(bh) ; /* get_hash grabs the buffer */
if (atomic_read(&(bh->b_count)) < 0) {
printk("journal-2165: bh->b_count < 0\n") ;
}
@@ -2656,275 +2653,6 @@
}
}
-/*
- * Wait for a page to get unlocked.
- *
- * This must be called with the caller "holding" the page,
- * ie with increased "page->count" so that the page won't
- * go away during the wait..
- */
-static void ___reiserfs_wait_on_page(struct reiserfs_page_list *pl)
-{
- struct task_struct *tsk = current;
- struct page *page = pl->page ;
- DECLARE_WAITQUEUE(wait, tsk);
-
- add_wait_queue(&page->wait, &wait);
- do {
- block_sync_page(page);
- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
- if (!PageLocked(page) || pl->do_not_lock)
- break;
- schedule();
- } while (PageLocked(page));
- tsk->state = TASK_RUNNING;
- remove_wait_queue(&page->wait, &wait);
-}
-
-/*
- * Get an exclusive lock on the page..
- * but, every time you get woken up, check the page to make sure
- * someone hasn't called a journal_begin with it locked.
- *
- * the page should always be locked when this returns
- *
- * returns 0 if you've got the page locked
- * returns 1 if it returns because someone else has called journal_begin
- * with the page locked
- * this is only useful to the code that flushes pages before a
- * commit. Do not export this hack. Ever.
- */
-static int reiserfs_try_lock_page(struct reiserfs_page_list *pl)
-{
- struct page *page = pl->page ;
- while (TryLockPage(page)) {
- if (pl->do_not_lock) {
- /* the page is locked, but we cannot have it */
- return 1 ;
- }
- ___reiserfs_wait_on_page(pl);
- }
- /* we have the page locked */
- return 0 ;
-}
-
-
-/*
-** This can only be called from do_journal_end.
-** it runs through the list things that need flushing before the
-** transaction can commit, and writes each of them to disk
-**
-*/
-
-static void flush_pages_before_commit(struct reiserfs_transaction_handle *th,
- struct super_block *p_s_sb) {
- struct reiserfs_page_list *pl = SB_JOURNAL(p_s_sb)->j_flush_pages ;
- struct reiserfs_page_list *pl_tmp ;
- struct buffer_head *bh, *head ;
- int count = 0 ;
-
- /* first write each dirty unlocked buffer in the list */
-
- while(pl) {
- /* ugly. journal_end can be called from get_block, which has a
- ** page locked. So, we have to check to see if pl->page is the page
- ** currently locked by the calling function, and if so, skip the
- ** lock
- */
- if (reiserfs_try_lock_page(pl)) {
- goto setup_next ;
- }
- if (!PageLocked(pl->page)) {
- BUG() ;
- }
- if (pl->page->buffers) {
- head = pl->page->buffers ;
- bh = head ;
- do {
- if (bh->b_blocknr == pl->blocknr && buffer_dirty(bh) &&
- !buffer_locked(bh) && buffer_uptodate(bh) ) {
- ll_rw_block(WRITE, 1, &bh) ;
- }
- bh = bh->b_this_page ;
- } while (bh != head) ;
- }
- if (!pl->do_not_lock) {
- UnlockPage(pl->page) ;
- }
-setup_next:
- pl = pl->next ;
- }
-
- /* now wait on them */
-
- pl = SB_JOURNAL(p_s_sb)->j_flush_pages ;
- while(pl) {
- if (reiserfs_try_lock_page(pl)) {
- goto remove_page ;
- }
- if (!PageLocked(pl->page)) {
- BUG() ;
- }
- if (pl->page->buffers) {
- head = pl->page->buffers ;
- bh = head ;
- do {
- if (bh->b_blocknr == pl->blocknr) {
- count++ ;
- wait_on_buffer(bh) ;
- if (!buffer_uptodate(bh)) {
- reiserfs_panic(p_s_sb, "journal-2443: flush_pages_before_commit, error writing block %lu\n", bh->b_blocknr) ;
- }
- }
- bh = bh->b_this_page ;
- } while (bh != head) ;
- }
- if (!pl->do_not_lock) {
- UnlockPage(pl->page) ;
- }
-remove_page:
- /* we've waited on the I/O, we can remove the page from the
- ** list, and free our pointer struct to it.
- */
- if (pl->prev) {
- pl->prev->next = pl->next ;
- }
- if (pl->next) {
- pl->next->prev = pl->prev ;
- }
- put_page(pl->page) ;
- pl_tmp = pl ;
- pl = pl->next ;
- reiserfs_kfree(pl_tmp, sizeof(struct reiserfs_page_list), p_s_sb) ;
- }
- SB_JOURNAL(p_s_sb)->j_flush_pages = NULL ;
-}
-
-/*
-** called when a indirect item is converted back into a tail.
-**
-** The reiserfs part of the inode stores enough information to find
-** our page_list struct in the flush list. We remove it from the list
-** and free the struct.
-**
-** Note, it is possible for this to happen:
-**
-** reiserfs_add_page_to_flush_list(inode)
-** transaction ends, list is flushed
-** reiserfs_remove_page_from_flush_list(inode)
-**
-** This would be bad because the page_list pointer in the inode is not
-** updated when the list is flushed, so we can't know if the pointer is
-** valid. So, in the inode, we also store the transaction id when the
-** page was added. If we are trying to remove something from an old
-** transaction, we just clear out the pointer in the inode and return.
-**
-** Normal case is to use the reiserfs_page_list pointer in the inode to
-** find and remove the page from the flush list.
-*/
-int reiserfs_remove_page_from_flush_list(struct reiserfs_transaction_handle *th,
- struct inode *inode) {
- struct reiserfs_page_list *pl ;
-
- /* was this conversion done in a previous transaction? If so, return */
- if (inode->u.reiserfs_i.i_conversion_trans_id < th->t_trans_id) {
- inode->u.reiserfs_i.i_converted_page = NULL ;
- inode->u.reiserfs_i.i_conversion_trans_id = 0 ;
- return 0 ;
- }
-
- /* remove the page_list struct from the list, release our hold on the
- ** page, and free the page_list struct
- */
- pl = inode->u.reiserfs_i.i_converted_page ;
- if (pl) {
- if (pl->next) {
- pl->next->prev = pl->prev ;
- }
- if (pl->prev) {
- pl->prev->next = pl->next ;
- }
- if (SB_JOURNAL(inode->i_sb)->j_flush_pages == pl) {
- SB_JOURNAL(inode->i_sb)->j_flush_pages = pl->next ;
- }
- put_page(pl->page) ;
- reiserfs_kfree(pl, sizeof(struct reiserfs_page_list), inode->i_sb) ;
- inode->u.reiserfs_i.i_converted_page = NULL ;
- inode->u.reiserfs_i.i_conversion_trans_id = 0 ;
- }
- return 0 ;
-}
-
-/*
-** Called after a direct to indirect transaction. The unformatted node
-** must be flushed to disk before the transaction commits, otherwise, we
-** risk losing the data from the direct item. This adds the page
-** containing the unformatted node to a list of pages that need flushing.
-**
-** it calls get_page(page), so the page won't disappear until we've
-** flushed or removed it from our list.
-**
-** pointers to the reiserfs_page_list struct are stored in the inode,
-** so this page can be quickly removed from the list after the tail is
-** converted back into a direct item.
-**
-** If we fail to find the memory for the reiserfs_page_list struct, we
-** just sync the page now. Not good, but safe.
-**
-** since this must be called with the page locked, we always set
-** the do_not_lock field in the page_list struct we allocate
-**
-*/
-int reiserfs_add_page_to_flush_list(struct reiserfs_transaction_handle *th,
- struct inode *inode,
- struct buffer_head *bh) {
- struct reiserfs_page_list *new_pl ;
-
-/* debugging use ONLY. Do not define this on data you care about. */
-#ifdef REISERFS_NO_FLUSH_AFTER_CONVERT
- return 0 ;
-#endif
-
- get_page(bh->b_page) ;
- new_pl = reiserfs_kmalloc(sizeof(struct reiserfs_page_list), GFP_NOFS,
- inode->i_sb) ;
- if (!new_pl) {
- put_page(bh->b_page) ;
- reiserfs_warning("journal-2480: forced to flush page, out of memory\n") ;
- ll_rw_block(WRITE, 1, &bh) ;
- wait_on_buffer(bh) ;
- if (!buffer_uptodate(bh)) {
- reiserfs_panic(inode->i_sb, "journal-2484: error writing buffer %lu to disk\n", bh->b_blocknr) ;
- }
- inode->u.reiserfs_i.i_converted_page = NULL ;
- return 0 ;
- }
-
- new_pl->page = bh->b_page ;
- new_pl->do_not_lock = 1 ;
- new_pl->blocknr = bh->b_blocknr ;
- new_pl->next = SB_JOURNAL(inode->i_sb)->j_flush_pages;
- if (new_pl->next) {
- new_pl->next->prev = new_pl ;
- }
- new_pl->prev = NULL ;
- SB_JOURNAL(inode->i_sb)->j_flush_pages = new_pl ;
-
- /* if we have numbers from an old transaction, zero the converted
- ** page, it has already been flushed and freed
- */
- if (inode->u.reiserfs_i.i_conversion_trans_id &&
- inode->u.reiserfs_i.i_conversion_trans_id < th->t_trans_id) {
- inode->u.reiserfs_i.i_converted_page = NULL ;
- }
- if (inode->u.reiserfs_i.i_converted_page) {
- reiserfs_panic(inode->i_sb, "journal-2501: inode already had a converted page\n") ;
- }
- inode->u.reiserfs_i.i_converted_page = new_pl ;
- inode->u.reiserfs_i.i_conversion_trans_id = th->t_trans_id ;
- return 0 ;
-}
-
/*
** long and ugly. If flush, will not return until all commit
** blocks and all real buffers in the trans are on disk.
@@ -3137,11 +2865,8 @@
jindex = (SB_JOURNAL_LIST_INDEX(p_s_sb) + 1) % JOURNAL_LIST_COUNT ;
SB_JOURNAL_LIST_INDEX(p_s_sb) = jindex ;
- /* make sure to flush any data converted from direct items to
- ** indirect items before allowing the commit blocks to reach the
- ** disk
- */
- flush_pages_before_commit(th, p_s_sb) ;
+ /* write any buffers that must hit disk before this commit is done */
+ fsync_inode_buffers(&(SB_JOURNAL(p_s_sb)->j_dummy_inode)) ;
/* honor the flush and async wishes from the caller */
if (flush) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)