put_bh(bh); 
static int __block_write_full_page(struct inode *inode, struct page *page,			get_block_t *get_block, struct writeback_control *wbc){	int err;	sector_t block;	sector_t last_block;	struct buffer_head *bh, *head, *last_bh = NULL;	int nr_underway = 0;	BUG_ON(!PageLocked(page));	last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;	if (!page_has_buffers(page)) {		create_empty_buffers(page, 1 << inode->i_blkbits,					(1 << BH_Dirty)|(1 << BH_Uptodate));	}	/*	 * Be very careful.  We have no exclusion from __set_page_dirty_buffers	 * here, and the (potentially unmapped) buffers may become dirty at	 * any time.  If a buffer becomes dirty here after we've inspected it	 * then we just miss that fact, and the page stays dirty.	 *	 * Buffers outside i_size may be dirtied by __set_page_dirty_buffers;	 * handle that here by just cleaning them.	 */	block = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);	head = page_buffers(page);	bh = head;	/*	 * Get all the dirty buffers mapped to disk addresses and	 * handle any aliases from the underlying blockdev's mapping.	 */	do {		if (block > last_block) {			/*			 * mapped buffers outside i_size will occur, because			 * this page can be outside i_size when there is a			 * truncate in progress.			 */			/*			 * The buffer was zeroed by block_write_full_page()			 */			clear_buffer_dirty(bh);			set_buffer_uptodate(bh);		} else if (!buffer_mapped(bh) && buffer_dirty(bh)) {			err = get_block(inode, block, bh, 1);			if (err)				goto recover;			if (buffer_new(bh)) {				/* blockdev mappings never come here */				clear_buffer_new(bh);				unmap_underlying_metadata(bh->b_bdev,							bh->b_blocknr);			}		}		bh = bh->b_this_page;		block++;	} while (bh != head);	do {		if (!buffer_mapped(bh))			continue;		/*		 * If it's a fully non-blocking write attempt and we cannot		 * lock the buffer then redirty the page.  Note that this can		 * potentially cause a busy-wait loop from pdflush and kswapd		 * activity, but those code paths have their own higher-level		 * throttling.		 */		if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {			lock_buffer(bh);		} else if (test_set_buffer_locked(bh)) {			redirty_page_for_writepage(wbc, page);			continue;		}		if (test_clear_buffer_dirty(bh)) {			mark_buffer_async_write(bh);			get_bh(bh);			last_bh = bh;		} else {			unlock_buffer(bh);		}	} while ((bh = bh->b_this_page) != head);	/*	 * The page and its buffers are protected by PageWriteback(), so we can	 * drop the bh refcounts early.	 */	BUG_ON(PageWriteback(page));	set_page_writeback(page);	unlock_page(page);	do {		struct buffer_head *next = bh->b_this_page;		if (buffer_async_write(bh)) {			submit_bh(WRITE, bh);			nr_underway++;			put_bh(bh);			if (bh == last_bh)				break;		}		bh = next;	} while (bh != head);	bh = head;	err = 0;done:	if (nr_underway == 0) {		/*		 * The page was marked dirty, but the buffers were		 * clean.  Someone wrote them back by hand with		 * ll_rw_block/submit_bh.  A rare case.		 */		int uptodate = 1;		do {			if (!buffer_uptodate(bh)) {				uptodate = 0;				break;			}			bh = bh->b_this_page;		} while (bh != head);		if (uptodate)			SetPageUptodate(page);		end_page_writeback(page);		/*		 * The page and buffer_heads can be released at any time from		 * here on.		 */		wbc->pages_skipped++;	/* We didn't write this page */	}	return err;recover:	/*	 * ENOSPC, or some other error.  We may already have added some	 * blocks to the file, so we need to write these out to avoid	 * exposing stale data.	 * The page is currently locked and not marked for writeback	 */	bh = head;	/* Recovery: lock and submit the mapped buffers */	do {		if (buffer_mapped(bh) && buffer_dirty(bh)) {			lock_buffer(bh);			mark_buffer_async_write(bh);			get_bh(bh);			last_bh = bh;		} else {			/*			 * The buffer may have been set dirty during			 * attachment to a dirty page.			 */			clear_buffer_dirty(bh);		}	} while ((bh = bh->b_this_page) != head);	SetPageError(page);	BUG_ON(PageWriteback(page));	set_page_writeback(page);	unlock_page(page);	do {		struct buffer_head *next = bh->b_this_page;		if (buffer_async_write(bh)) {			clear_buffer_dirty(bh);			submit_bh(WRITE, bh);			nr_underway++;			put_bh(bh);			if (bh == last_bh)				break;		}		bh = next;	} while (bh != head);	bh = head;	goto done;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/05937baae9fc27b64bcd4378da7d2b14edf7931c/buffer.c/buggy/fs/buffer.c