/** * nilfs_alloc_private_page - allocate a private page with buffer heads * * Return Value: On success, a pointer to the allocated page is returned. * On error, NULL is returned. */ struct page *nilfs_alloc_private_page(struct block_device *bdev, int size, unsigned long state) { struct buffer_head *bh, *head, *tail; struct page *page; page = alloc_page(GFP_NOFS); /* page_count of the returned page is 1 */ if (unlikely(!page)) return NULL; lock_page(page); head = alloc_page_buffers(page, size, 0); if (unlikely(!head)) { unlock_page(page); __free_page(page); return NULL; } bh = head; do { bh->b_state = (1UL << BH_NILFS_Allocated) | state; tail = bh; bh->b_bdev = bdev; bh = bh->b_this_page; } while (bh); tail->b_this_page = head; attach_page_buffers(page, head); return page; }
/* read a page from a file. * We both read the page, and attach buffers to the page to record the * address of each block (using bmap). These addresses will be used * to write the block later, completely bypassing the filesystem. * This usage is similar to how swap files are handled, and allows us * to write to a file with no concerns of memory allocation failing. */ static struct page *read_page(struct file *file, unsigned long index, struct bitmap *bitmap, unsigned long count) { struct page *page = NULL; struct inode *inode = file->f_path.dentry->d_inode; struct buffer_head *bh; sector_t block; PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_SIZE, (unsigned long long)index << PAGE_SHIFT); page = alloc_page(GFP_KERNEL); if (!page) page = ERR_PTR(-ENOMEM); if (IS_ERR(page)) goto out; bh = alloc_page_buffers(page, 1<<inode->i_blkbits, 0); if (!bh) { put_page(page); page = ERR_PTR(-ENOMEM); goto out; } attach_page_buffers(page, bh); block = index << (PAGE_SHIFT - inode->i_blkbits); while (bh) { if (count == 0) bh->b_blocknr = 0; else { bh->b_blocknr = bmap(inode, block); if (bh->b_blocknr == 0) { /* Cannot use this file! */ free_buffers(page); page = ERR_PTR(-EINVAL); goto out; } bh->b_bdev = inode->i_sb->s_bdev; if (count < (1<<inode->i_blkbits)) count = 0; else count -= (1<<inode->i_blkbits); bh->b_end_io = end_bitmap_write; bh->b_private = bitmap; atomic_inc(&bitmap->pending_writes); set_buffer_locked(bh); set_buffer_mapped(bh); submit_bh(READ, bh); } block++; bh = bh->b_this_page; } page->index = index; wait_event(bitmap->write_wait, atomic_read(&bitmap->pending_writes)==0); if (bitmap->flags & BITMAP_WRITE_ERROR) { free_buffers(page); page = ERR_PTR(-EIO); } out: if (IS_ERR(page)) printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n", (int)PAGE_SIZE, (unsigned long long)index << PAGE_SHIFT, PTR_ERR(page)); return page; }