void nilfs_page_bug(struct page *page) { struct address_space *m; unsigned long ino = 0; if (unlikely(!page)) { printk(KERN_CRIT "NILFS_PAGE_BUG(NULL)\n"); return; } m = page->mapping; if (m) { struct inode *inode = NILFS_AS_I(m); if (inode != NULL) ino = inode->i_ino; } printk(KERN_CRIT "NILFS_PAGE_BUG(%p): cnt=%d index#=%llu flags=0x%lx " "mapping=%p ino=%lu\n", page, atomic_read(&page->_count), (unsigned long long)page->index, page->flags, m, ino); if (page_has_buffers(page)) { struct buffer_head *bh, *head; int i = 0; bh = head = page_buffers(page); do { printk(KERN_CRIT " BH[%d] %p: cnt=%d block#=%llu state=0x%lx\n", i++, bh, atomic_read(&bh->b_count), (unsigned long long)bh->b_blocknr, bh->b_state); bh = bh->b_this_page; } while (bh != head); } }
/* * For inode and page debug */ int nilfs_releasepage(struct page *page, gfp_t gfp_mask) { struct address_space *mapping = page->mapping; struct inode *inode; int verbose = (nilfs_debug_info.verbose[NILFS_VERBOSE_PAGE] > 1); int ret; if (!verbose && mapping) { inode = NILFS_AS_I(mapping); if (inode->i_sb && !(inode->i_sb->s_flags & MS_ACTIVE)) verbose = 1; } if (unlikely(!PagePrivate(page))) NILFS_PAGE_BUG(page, "no buffers"); if (buffer_nilfs_allocated(page_buffers(page))) NILFS_PAGE_BUG(page, "nilfs allocated page"); /* * Note that non-busy buffer heads may be discarded though the * try_to_free_buffers() call. This may happen when the page is not * dirty, not in writeback, not locked, and belongs to a mapping. * Before changing the state of buffer heads to busy, the page lock * must be held to protect them. */ ret = try_to_free_buffers(page); if (verbose && ret && mapping && mapping->host) { if (page_count(page) > 2 + !PageLRU(page)) /* * This may happen when the other task just happen to * find and get the page during this invalidation. */ PAGE_DEBUG(page, "too many page count"); } return ret; }
void nilfs_page_debug(const char *fname, int line, struct page *page, const char *m, ...) { struct address_space *mapping; struct inode *inode; va_list args; int len; char b[MSIZ]; /* The page should be locked */ len = snprintf(b, MSIZ, "PAGE %p ", page); va_start(args, m); len += vsnprintf(b + len, MSIZ - len, m, args); va_end(args); if (page == NULL) { printk(KERN_DEBUG "%s: page=NULL %s at %d\n", b, fname, line); return; } mapping = page->mapping; len += snprintf(b + len, MSIZ - len, ": cnt=%d index#=%llu mapping=%d lru=%d", atomic_read(&page->_count), (unsigned long long)page->index, !!mapping, !list_empty(&page->lru)); len += snprintf(b + len, MSIZ - len, " %s(%d) flags=", fname, line); len += snprint_page_flags(b + len, MSIZ - len, page); if (mapping) { if (buffer_nilfs_node(page_buffers(page))) inode = NILFS_BTNC_I(mapping); else inode = NILFS_AS_I(mapping); if (inode != NULL) len += snprintf(b + len, MSIZ - len, " ino=%lu", inode->i_ino); } printk(KERN_DEBUG "%s\n", b); if (page_has_buffers(page)) { struct buffer_head *bh, *head; int i = 0; bh = head = page_buffers(page); if (!bh) { printk(KERN_DEBUG "PAGE %p: invalid page buffers\n", page); return; } do { len = snprintf(b, MSIZ, " BH[%d] %p: cnt=%d blk#=%llu state=", i, bh, atomic_read(&bh->b_count), (unsigned long long)bh->b_blocknr); len += snprint_bh_state(b + len, MSIZ - len, bh); printk(KERN_DEBUG "%s\n", b); bh = bh->b_this_page; i++; if (unlikely(!bh)) { printk(KERN_DEBUG "PAGE %p: unexpected buffers end\n", page); break; } } while (bh != head); } }