/* * 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; }
static int tux3_set_page_dirty_buffers(struct page *page) { #if 0 struct address_space *mapping = page->mapping; int newly_dirty; spin_lock(&mapping->private_lock); if (page_has_buffers(page)) { struct buffer_head *head = page_buffers(page); struct buffer_head *bh = head; do { set_buffer_dirty(bh); bh = bh->b_this_page; } while (bh != head); } newly_dirty = !TestSetPageDirty(page); spin_unlock(&mapping->private_lock); if (newly_dirty) __set_page_dirty(page, mapping, 1); return newly_dirty; #else struct address_space *mapping = page->mapping; unsigned delta = tux3_get_current_delta(); struct buffer_head *head, *buffer; int newly_dirty; /* This should be tux3 page and locked */ assert(mapping); assert(PageLocked(page)); /* This page should have buffers (caller should allocate) */ assert(page_has_buffers(page)); /* * FIXME: we dirty all buffers on this page, so we optimize this * by avoiding to check page-dirty/inode-dirty multiple times. */ newly_dirty = 0; if (!TestSetPageDirty(page)) { __tux3_set_page_dirty(page, mapping, 1); newly_dirty = 1; } buffer = head = page_buffers(page); do { __tux3_mark_buffer_dirty(buffer, delta); buffer = buffer->b_this_page; } while (buffer != head); #endif return newly_dirty; }