/* * Caller must hold lock_page() or backend (otherwise, you may race * with buffer fork or clear dirty) */ int tux3_set_buffer_dirty_list(struct address_space *mapping, struct buffer_head *buffer, int delta, struct list_head *head) { /* FIXME: we better to set this by caller? */ if (!buffer_uptodate(buffer)) set_buffer_uptodate(buffer); /* * Basically, open code of mark_buffer_dirty() without mark * inode dirty. Caller decides whether dirty inode or not. */ if (!test_set_buffer_dirty(buffer)) { struct page *page = buffer->b_page; /* Mark dirty for delta, then add buffer to our dirty list */ __tux3_set_buffer_dirty_list(mapping, buffer, delta, head); if (!TestSetPageDirty(page)) { struct address_space *mapping = page->mapping; if (mapping) __tux3_set_page_dirty(page, mapping, 0); return 1; } } return 0; }
/** * nilfs_btnode_commit_change_key * commit the change_key operation prepared by prepare_change_key(). */ void nilfs_btnode_commit_change_key(struct address_space *btnc, struct nilfs_btnode_chkey_ctxt *ctxt) { struct buffer_head *obh = ctxt->bh, *nbh = ctxt->newbh; __u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey; struct page *opage; if (oldkey == newkey) return; if (nbh == NULL) { /* blocksize == pagesize */ opage = obh->b_page; if (unlikely(oldkey != opage->index)) NILFS_PAGE_BUG(opage, "invalid oldkey %lld (newkey=%lld)", (unsigned long long)oldkey, (unsigned long long)newkey); if (!test_set_buffer_dirty(obh) && TestSetPageDirty(opage)) BUG(); WRITE_LOCK_IRQ(&btnc->tree_lock); radix_tree_delete(&btnc->page_tree, oldkey); radix_tree_tag_set(&btnc->page_tree, newkey, PAGECACHE_TAG_DIRTY); WRITE_UNLOCK_IRQ(&btnc->tree_lock); opage->index = obh->b_blocknr = newkey; unlock_page(opage); } else { nilfs_copy_buffer(nbh, obh); nilfs_btnode_mark_dirty(nbh); nbh->b_blocknr = newkey; ctxt->bh = nbh; nilfs_btnode_delete(obh); /* will decrement bh->b_count */ } }
/* * Since the page cache of B-tree node pages or data page cache of pseudo * inodes does not have a valid mapping->host pointer, calling * mark_buffer_dirty() for their buffers causes a NULL pointer dereference; * it calls __mark_inode_dirty(NULL) through __set_page_dirty(). * To avoid this problem, the old style mark_buffer_dirty() is used instead. */ void nilfs_mark_buffer_dirty(struct buffer_head *bh) { if (!buffer_dirty(bh) && !test_set_buffer_dirty(bh)) __set_page_dirty_nobuffers(bh->b_page); }