⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jfs_metapage.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			set_page_writeback(page);			inc_io(page);		}		xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits;		pblock = metapage_get_blocks(inode, lblock, &xlen);		if (!pblock) {			/* Need better error handling */			printk(KERN_ERR "JFS: metapage_get_blocks failed\n");			dec_io(page, last_write_complete);			continue;		}		set_bit(META_io, &mp->flag);		len = min(xlen, (uint) JFS_SBI(inode->i_sb)->nbperpage);		bio = bio_alloc(GFP_NOFS, 1);		bio->bi_bdev = inode->i_sb->s_bdev;		bio->bi_sector = pblock << (inode->i_blkbits - 9);		bio->bi_end_io = metapage_write_end_io;		bio->bi_private = page;		/* Don't call bio_add_page yet, we may add to this vec */		bio_offset = offset;		bio_bytes = len << inode->i_blkbits;		xlen -= len;		next_block = lblock + len;	}	if (bio) {		if (bio_add_page(bio, page, bio_bytes, bio_offset) < bio_bytes)				goto add_failed;		if (!bio->bi_size)			goto dump_bio;		submit_bio(WRITE, bio);	}	if (redirty)		redirty_page_for_writepage(wbc, page);	unlock_page(page);	return 0;add_failed:	/* We should never reach here, since we're only adding one vec */	printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");	goto skip;dump_bio:	print_hex_dump(KERN_ERR, "JFS: dump of bio: ", DUMP_PREFIX_ADDRESS, 16,		       4, bio, sizeof(*bio), 0);skip:	bio_put(bio);	unlock_page(page);	dec_io(page, last_write_complete);	return -EIO;}static int metapage_readpage(struct file *fp, struct page *page){	struct inode *inode = page->mapping->host;	struct bio *bio = NULL;	unsigned int block_offset;	unsigned int blocks_per_page = PAGE_CACHE_SIZE >> inode->i_blkbits;	sector_t page_start;	/* address of page in fs blocks */	sector_t pblock;	unsigned int xlen;	unsigned int len;	unsigned int offset;	BUG_ON(!PageLocked(page));	page_start = (sector_t)page->index <<		     (PAGE_CACHE_SHIFT - inode->i_blkbits);	block_offset = 0;	while (block_offset < blocks_per_page) {		xlen = blocks_per_page - block_offset;		pblock = metapage_get_blocks(inode, page_start + block_offset,					     &xlen);		if (pblock) {			if (!PagePrivate(page))				insert_metapage(page, NULL);			inc_io(page);			if (bio)				submit_bio(READ, bio);			bio = bio_alloc(GFP_NOFS, 1);			bio->bi_bdev = inode->i_sb->s_bdev;			bio->bi_sector = pblock << (inode->i_blkbits - 9);			bio->bi_end_io = metapage_read_end_io;			bio->bi_private = page;			len = xlen << inode->i_blkbits;			offset = block_offset << inode->i_blkbits;			if (bio_add_page(bio, page, len, offset) < len)				goto add_failed;			block_offset += xlen;		} else			block_offset++;	}	if (bio)		submit_bio(READ, bio);	else		unlock_page(page);	return 0;add_failed:	printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");	bio_put(bio);	dec_io(page, last_read_complete);	return -EIO;}static int metapage_releasepage(struct page *page, gfp_t gfp_mask){	struct metapage *mp;	int ret = 1;	unsigned int offset;	for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {		mp = page_to_mp(page, offset);		if (!mp)			continue;		jfs_info("metapage_releasepage: mp = 0x%p", mp);		if (mp->count || mp->nohomeok ||		    test_bit(META_dirty, &mp->flag)) {			jfs_info("count = %ld, nohomeok = %d", mp->count,				 mp->nohomeok);			ret = 0;			continue;		}		if (mp->lsn)			remove_from_logsync(mp);		remove_metapage(page, mp);		INCREMENT(mpStat.pagefree);		free_metapage(mp);	}	return ret;}static void metapage_invalidatepage(struct page *page, unsigned long offset){	BUG_ON(offset);	BUG_ON(PageWriteback(page));	metapage_releasepage(page, 0);}const struct address_space_operations jfs_metapage_aops = {	.readpage	= metapage_readpage,	.writepage	= metapage_writepage,	.sync_page	= block_sync_page,	.releasepage	= metapage_releasepage,	.invalidatepage	= metapage_invalidatepage,	.set_page_dirty	= __set_page_dirty_nobuffers,};struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,				unsigned int size, int absolute,				unsigned long new){	int l2BlocksPerPage;	int l2bsize;	struct address_space *mapping;	struct metapage *mp = NULL;	struct page *page;	unsigned long page_index;	unsigned long page_offset;	jfs_info("__get_metapage: ino = %ld, lblock = 0x%lx, abs=%d",		 inode->i_ino, lblock, absolute);	l2bsize = inode->i_blkbits;	l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize;	page_index = lblock >> l2BlocksPerPage;	page_offset = (lblock - (page_index << l2BlocksPerPage)) << l2bsize;	if ((page_offset + size) > PAGE_CACHE_SIZE) {		jfs_err("MetaData crosses page boundary!!");		jfs_err("lblock = %lx, size  = %d", lblock, size);		dump_stack();		return NULL;	}	if (absolute)		mapping = JFS_SBI(inode->i_sb)->direct_inode->i_mapping;	else {		/*		 * If an nfs client tries to read an inode that is larger		 * than any existing inodes, we may try to read past the		 * end of the inode map		 */		if ((lblock << inode->i_blkbits) >= inode->i_size)			return NULL;		mapping = inode->i_mapping;	}	if (new && (PSIZE == PAGE_CACHE_SIZE)) {		page = grab_cache_page(mapping, page_index);		if (!page) {			jfs_err("grab_cache_page failed!");			return NULL;		}		SetPageUptodate(page);	} else {		page = read_mapping_page(mapping, page_index, NULL);		if (IS_ERR(page) || !PageUptodate(page)) {			jfs_err("read_mapping_page failed!");			return NULL;		}		lock_page(page);	}	mp = page_to_mp(page, page_offset);	if (mp) {		if (mp->logical_size != size) {			jfs_error(inode->i_sb,				  "__get_metapage: mp->logical_size != size");			jfs_err("logical_size = %d, size = %d",				mp->logical_size, size);			dump_stack();			goto unlock;		}		mp->count++;		lock_metapage(mp);		if (test_bit(META_discard, &mp->flag)) {			if (!new) {				jfs_error(inode->i_sb,					  "__get_metapage: using a "					  "discarded metapage");				discard_metapage(mp);				goto unlock;			}			clear_bit(META_discard, &mp->flag);		}	} else {		INCREMENT(mpStat.pagealloc);		mp = alloc_metapage(GFP_NOFS);		mp->page = page;		mp->flag = 0;		mp->xflag = COMMIT_PAGE;		mp->count = 1;		mp->nohomeok = 0;		mp->logical_size = size;		mp->data = page_address(page) + page_offset;		mp->index = lblock;		if (unlikely(insert_metapage(page, mp))) {			free_metapage(mp);			goto unlock;		}		lock_metapage(mp);	}	if (new) {		jfs_info("zeroing mp = 0x%p", mp);		memset(mp->data, 0, PSIZE);	}	unlock_page(page);	jfs_info("__get_metapage: returning = 0x%p data = 0x%p", mp, mp->data);	return mp;unlock:	unlock_page(page);	return NULL;}void grab_metapage(struct metapage * mp){	jfs_info("grab_metapage: mp = 0x%p", mp);	page_cache_get(mp->page);	lock_page(mp->page);	mp->count++;	lock_metapage(mp);	unlock_page(mp->page);}void force_metapage(struct metapage *mp){	struct page *page = mp->page;	jfs_info("force_metapage: mp = 0x%p", mp);	set_bit(META_forcewrite, &mp->flag);	clear_bit(META_sync, &mp->flag);	page_cache_get(page);	lock_page(page);	set_page_dirty(page);	write_one_page(page, 1);	clear_bit(META_forcewrite, &mp->flag);	page_cache_release(page);}void hold_metapage(struct metapage *mp){	lock_page(mp->page);}void put_metapage(struct metapage *mp){	if (mp->count || mp->nohomeok) {		/* Someone else will release this */		unlock_page(mp->page);		return;	}	page_cache_get(mp->page);	mp->count++;	lock_metapage(mp);	unlock_page(mp->page);	release_metapage(mp);}void release_metapage(struct metapage * mp){	struct page *page = mp->page;	jfs_info("release_metapage: mp = 0x%p, flag = 0x%lx", mp, mp->flag);	BUG_ON(!page);	lock_page(page);	unlock_metapage(mp);	assert(mp->count);	if (--mp->count || mp->nohomeok) {		unlock_page(page);		page_cache_release(page);		return;	}	if (test_bit(META_dirty, &mp->flag)) {		set_page_dirty(page);		if (test_bit(META_sync, &mp->flag)) {			clear_bit(META_sync, &mp->flag);			write_one_page(page, 1);			lock_page(page); /* write_one_page unlocks the page */		}	} else if (mp->lsn)	/* discard_metapage doesn't remove it */		remove_from_logsync(mp);	/* Try to keep metapages from using up too much memory */	drop_metapage(page, mp);	unlock_page(page);	page_cache_release(page);}void __invalidate_metapages(struct inode *ip, s64 addr, int len){	sector_t lblock;	int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_blkbits;	int BlocksPerPage = 1 << l2BlocksPerPage;	/* All callers are interested in block device's mapping */	struct address_space *mapping =		JFS_SBI(ip->i_sb)->direct_inode->i_mapping;	struct metapage *mp;	struct page *page;	unsigned int offset;	/*	 * Mark metapages to discard.  They will eventually be	 * released, but should not be written.	 */	for (lblock = addr & ~(BlocksPerPage - 1); lblock < addr + len;	     lblock += BlocksPerPage) {		page = find_lock_page(mapping, lblock >> l2BlocksPerPage);		if (!page)			continue;		for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {			mp = page_to_mp(page, offset);			if (!mp)				continue;			if (mp->index < addr)				continue;			if (mp->index >= addr + len)				break;			clear_bit(META_dirty, &mp->flag);			set_bit(META_discard, &mp->flag);			if (mp->lsn)				remove_from_logsync(mp);		}		unlock_page(page);		page_cache_release(page);	}}#ifdef CONFIG_JFS_STATISTICSint jfs_mpstat_read(char *buffer, char **start, off_t offset, int length,		    int *eof, void *data){	int len = 0;	off_t begin;	len += sprintf(buffer,		       "JFS Metapage statistics\n"		       "=======================\n"		       "page allocations = %d\n"		       "page frees = %d\n"		       "lock waits = %d\n",		       mpStat.pagealloc,		       mpStat.pagefree,		       mpStat.lockwait);	begin = offset;	*start = buffer + begin;	len -= begin;	if (len > length)		len = length;	else		*eof = 1;	if (len < 0)		len = 0;	return len;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -