void nilfs_vinode_debug(const char *fname, int line, struct inode *inode, const char *m, ...) { struct nilfs_inode_info *ii; int n = 0, len; char b[MSIZ]; va_list args; len = snprintf(b, MSIZ, "VINODE %p ", inode); va_start(args, m); len += vsnprintf(b + len, MSIZ - len, m, args); va_end(args); if (inode == NULL) { printk(KERN_DEBUG "%s: inode=NULL %s at %d\n", m, fname, line); return; } ii = NILFS_I(inode); len += snprintf(b + len, MSIZ - len, ": current %p ino=%lu nlink=%u " "count=%u mode=0%o mapping=%p i_bh=%p", current, inode->i_ino, inode->i_nlink, atomic_read(&inode->i_count), inode->i_mode, inode->i_mapping, ii->i_bh); len += snprintf(b + len, MSIZ - len, " %s(%d) i_state=", fname, line); TEST_INODE_STATE(inode, DIRTY_SYNC, b, MSIZ, n, len); TEST_INODE_STATE(inode, DIRTY_DATASYNC, b, MSIZ, n, len); TEST_INODE_STATE(inode, DIRTY_PAGES, b, MSIZ, n, len); TEST_INODE_STATE(inode, LOCK, b, MSIZ, n, len); TEST_INODE_STATE(inode, FREEING, b, MSIZ, n, len); TEST_INODE_STATE(inode, CLEAR, b, MSIZ, n, len); TEST_INODE_STATE(inode, NEW, b, MSIZ, n, len); #ifdef I_WILL_FREE TEST_INODE_STATE(inode, WILL_FREE, b, MSIZ, n, len); #endif if (ii->i_state) { n = 0; len += snprintf(b + len, MSIZ - len, " vi_state="); TEST_NILFS_INODE_STATE(ii, NEW, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, DIRTY, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, QUEUED, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, BUSY, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, COLLECTED, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, UPDATED, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, INODE_DIRTY, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, BMAP, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, GCINODE, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, GCDAT, b, MSIZ, n, len); } printk(KERN_DEBUG "%s\n", b); if (ii->i_bh) BH_DEBUG(ii->i_bh, "ibh"); }
/** * nilfs_btnode_delete - delete B-tree node buffer * @bh: buffer to be deleted * * nilfs_btnode_delete() invalidates the specified buffer and delete the page * including the buffer if the page gets unbusy. */ void nilfs_btnode_delete(struct buffer_head *bh) { struct address_space *mapping; struct page *page = bh->b_page; pgoff_t index = page_index(page); int still_dirty; page_cache_get(page); lock_page(page); wait_on_page_writeback(page); if (unlikely(!buffer_mapped(bh))) BH_DEBUG(bh, "deleting unused btnode buffer"); nilfs_forget_buffer(bh); still_dirty = PageDirty(page); mapping = page->mapping; unlock_page(page); page_cache_release(page); if (!still_dirty && mapping) invalidate_inode_pages2_range(mapping, index, index); }
int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, sector_t pblocknr, struct buffer_head **pbh, int newblk) { struct buffer_head *bh; struct inode *inode = NILFS_BTNC_I(btnc); int err; btnode_debug(3, "called: blocknr=%llu pblocknr=%llu new=%d ino=%lu\n", (unsigned long long)blocknr, (unsigned long long)pblocknr, newblk, inode->i_ino); bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node); if (unlikely(!bh)) return -ENOMEM; err = -EEXIST; /* internal code */ if (newblk) { if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) || buffer_dirty(bh))) { BH_DEBUG(bh, "invalid new bh"); BUG(); } bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev; bh->b_blocknr = blocknr; set_buffer_mapped(bh); set_buffer_uptodate(bh); goto found; } if (buffer_uptodate(bh) || buffer_dirty(bh)) goto found; if (pblocknr == 0) { pblocknr = blocknr; if (inode->i_ino != NILFS_DAT_INO) { struct inode *dat = nilfs_dat_inode(NILFS_I_NILFS(inode)); /* blocknr is a virtual block number */ err = nilfs_dat_translate(dat, blocknr, &pblocknr); if (unlikely(err)) { brelse(bh); btnode_debug(1, "return %d (xlate).\n", err); goto out_locked; } } } lock_buffer(bh); if (buffer_uptodate(bh)) { unlock_buffer(bh); err = -EEXIST; /* internal code */ goto found; } set_buffer_mapped(bh); bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev; bh->b_blocknr = pblocknr; /* set block address for read */ bh->b_end_io = end_buffer_read_sync; get_bh(bh); submit_bh(READ, bh); bh->b_blocknr = blocknr; /* set back to the given block address */ err = 0; found: *pbh = bh; out_locked: unlock_page(bh->b_page); page_cache_release(bh->b_page); btnode_debug(3, "done (err=%d)\n", err); return err; }