struct buffer_head *blockdirty(struct buffer_head *buffer, unsigned newdelta) { map_t *map = buffer->map; assert(buffer->state < BUFFER_STATES); buftrace("---- before: fork buffer %p ----", buffer); if (buffer_dirty(buffer)) { if (buffer_already_dirty(buffer, newdelta)) return buffer; /* Buffer can't modify already, we have to fork buffer */ buftrace("---- fork buffer %p ----", buffer); struct buffer_head *clone = new_buffer(map); if (IS_ERR(clone)) return clone; /* Create the cloned buffer */ memcpy(bufdata(clone), bufdata(buffer), bufsize(buffer)); clone->index = buffer->index; /* Replace the buffer by cloned buffer. */ remove_buffer_hash(buffer); insert_buffer_hash(clone); /* * The refcount of buffer is used for backend. So, the * backend has to free this buffer (blockput(buffer)) */ buffer = clone; } __tux3_mark_buffer_dirty(buffer, newdelta); return buffer; }
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; }