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

📄 aops.c

📁 ocfs1.4.1 oracle分布式文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
}static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc){	ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages);	brelse(wc->w_di_bh);	kfree(wc);}static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,				  struct ocfs2_super *osb, loff_t pos,				  unsigned len, struct buffer_head *di_bh){	u32 cend;	struct ocfs2_write_ctxt *wc;	wc = kzalloc(sizeof(struct ocfs2_write_ctxt), GFP_NOFS);	if (!wc)		return -ENOMEM;	wc->w_cpos = pos >> osb->s_clustersize_bits;	cend = (pos + len - 1) >> osb->s_clustersize_bits;	wc->w_clen = cend - wc->w_cpos + 1;	get_bh(di_bh);	wc->w_di_bh = di_bh;	if (unlikely(PAGE_CACHE_SHIFT > osb->s_clustersize_bits))		wc->w_large_pages = 1;	else		wc->w_large_pages = 0;	ocfs2_init_dealloc_ctxt(&wc->w_dealloc);	*wcp = wc;	return 0;}/* * If a page has any new buffers, zero them out here, and mark them uptodate * and dirty so they'll be written out (in order to prevent uninitialised * block data from leaking). And clear the new bit. */static void ocfs2_zero_new_buffers(struct page *page, unsigned from, unsigned to){	unsigned int block_start, block_end;	struct buffer_head *head, *bh;	BUG_ON(!PageLocked(page));	if (!page_has_buffers(page))		return;	bh = head = page_buffers(page);	block_start = 0;	do {		block_end = block_start + bh->b_size;		if (buffer_new(bh)) {			if (block_end > from && block_start < to) {				if (!PageUptodate(page)) {					unsigned start, end;					start = max(from, block_start);					end = min(to, block_end);					zero_user_page(page, start, end - start, KM_USER0);					set_buffer_uptodate(bh);				}				clear_buffer_new(bh);				mark_buffer_dirty(bh);			}		}		block_start = block_end;		bh = bh->b_this_page;	} while (bh != head);}/* * Only called when we have a failure during allocating write to write * zero's to the newly allocated region. */static void ocfs2_write_failure(struct inode *inode,				struct ocfs2_write_ctxt *wc,				loff_t user_pos, unsigned user_len){	int i;	unsigned from = user_pos & (PAGE_CACHE_SIZE - 1),		to = user_pos + user_len;	struct page *tmppage;	ocfs2_zero_new_buffers(wc->w_target_page, from, to);	for(i = 0; i < wc->w_num_pages; i++) {		tmppage = wc->w_pages[i];		if (page_has_buffers(tmppage)) {			if (ocfs2_should_order_data(inode))				walk_page_buffers(wc->w_handle,						  page_buffers(tmppage),						  from, to, NULL,						  ocfs2_journal_dirty_data);			block_commit_write(tmppage, from, to);		}	}}static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,					struct ocfs2_write_ctxt *wc,					struct page *page, u32 cpos,					loff_t user_pos, unsigned user_len,					int new){	int ret;	unsigned int map_from = 0, map_to = 0;	unsigned int cluster_start, cluster_end;	unsigned int user_data_from = 0, user_data_to = 0;	ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,					&cluster_start, &cluster_end);	if (page == wc->w_target_page) {		map_from = user_pos & (PAGE_CACHE_SIZE - 1);		map_to = map_from + user_len;		if (new)			ret = ocfs2_map_page_blocks(page, p_blkno, inode,						    cluster_start, cluster_end,						    new);		else			ret = ocfs2_map_page_blocks(page, p_blkno, inode,						    map_from, map_to, new);		if (ret) {			mlog_errno(ret);			goto out;		}		user_data_from = map_from;		user_data_to = map_to;		if (new) {			map_from = cluster_start;			map_to = cluster_end;		}	} else {		/*		 * If we haven't allocated the new page yet, we		 * shouldn't be writing it out without copying user		 * data. This is likely a math error from the caller.		 */		BUG_ON(!new);		map_from = cluster_start;		map_to = cluster_end;		ret = ocfs2_map_page_blocks(page, p_blkno, inode,					    cluster_start, cluster_end, new);		if (ret) {			mlog_errno(ret);			goto out;		}	}	/*	 * Parts of newly allocated pages need to be zero'd.	 *	 * Above, we have also rewritten 'to' and 'from' - as far as	 * the rest of the function is concerned, the entire cluster	 * range inside of a page needs to be written.	 *	 * We can skip this if the page is up to date - it's already	 * been zero'd from being read in as a hole.	 */	if (new && !PageUptodate(page))		ocfs2_clear_page_regions(page, OCFS2_SB(inode->i_sb),					 cpos, user_data_from, user_data_to);	flush_dcache_page(page);out:	return ret;}/* * This function will only grab one clusters worth of pages. */static int ocfs2_grab_pages_for_write(struct address_space *mapping,				      struct ocfs2_write_ctxt *wc,				      u32 cpos, loff_t user_pos, int new,				      struct page *mmap_page){	int ret = 0, i;	unsigned long start, target_index, index;	struct inode *inode = mapping->host;	target_index = user_pos >> PAGE_CACHE_SHIFT;	/*	 * Figure out how many pages we'll be manipulating here. For	 * non allocating write, we just change the one	 * page. Otherwise, we'll need a whole clusters worth.	 */	if (new) {		wc->w_num_pages = ocfs2_pages_per_cluster(inode->i_sb);		start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos);	} else {		wc->w_num_pages = 1;		start = target_index;	}	for(i = 0; i < wc->w_num_pages; i++) {		index = start + i;		if (index == target_index && mmap_page) {			/*			 * ocfs2_pagemkwrite() is a little different			 * and wants us to directly use the page			 * passed in.			 */			lock_page(mmap_page);			if (mmap_page->mapping != mapping) {				unlock_page(mmap_page);				/*				 * Sanity check - the locking in				 * ocfs2_pagemkwrite() should ensure				 * that this code doesn't trigger.				 */				ret = -EINVAL;				mlog_errno(ret);				goto out;			}			page_cache_get(mmap_page);			wc->w_pages[i] = mmap_page;		} else {			wc->w_pages[i] = find_or_create_page(mapping, index,							     GFP_NOFS);			if (!wc->w_pages[i]) {				ret = -ENOMEM;				mlog_errno(ret);				goto out;			}		}		if (index == target_index)			wc->w_target_page = wc->w_pages[i];	}out:	return ret;}/* * Prepare a single cluster for write one cluster into the file. */static int ocfs2_write_cluster(struct address_space *mapping,			       u32 phys, unsigned int unwritten,			       struct ocfs2_alloc_context *data_ac,			       struct ocfs2_alloc_context *meta_ac,			       struct ocfs2_write_ctxt *wc, u32 cpos,			       loff_t user_pos, unsigned user_len){	int ret, i, new, should_zero = 0;	u64 v_blkno, p_blkno;	struct inode *inode = mapping->host;	new = phys == 0 ? 1 : 0;	if (new || unwritten)		should_zero = 1;	if (new) {		u32 tmp_pos;		/*		 * This is safe to call with the page locks - it won't take		 * any additional semaphores or cluster locks.		 */		tmp_pos = cpos;		ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode,						 &tmp_pos, 1, 0, wc->w_di_bh,						 wc->w_handle, data_ac,						 meta_ac, NULL);		/*		 * This shouldn't happen because we must have already		 * calculated the correct meta data allocation required. The		 * internal tree allocation code should know how to increase		 * transaction credits itself.		 *		 * If need be, we could handle -EAGAIN for a		 * RESTART_TRANS here.		 */		mlog_bug_on_msg(ret == -EAGAIN,				"Inode %llu: EAGAIN return during allocation.\n",				(unsigned long long)OCFS2_I(inode)->ip_blkno);		if (ret < 0) {			mlog_errno(ret);			goto out;		}	} else if (unwritten) {		ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,						wc->w_handle, cpos, 1, phys,						meta_ac, &wc->w_dealloc);		if (ret < 0) {			mlog_errno(ret);			goto out;		}	}	if (should_zero)		v_blkno = ocfs2_clusters_to_blocks(inode->i_sb, cpos);	else		v_blkno = user_pos >> inode->i_sb->s_blocksize_bits;	/*	 * The only reason this should fail is due to an inability to	 * find the extent added.	 */	ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL,					  NULL);	if (ret < 0) {		ocfs2_error(inode->i_sb, "Corrupting extend for inode %llu, "			    "at logical block %llu",			    (unsigned long long)OCFS2_I(inode)->ip_blkno,			    (unsigned long long)v_blkno);		goto out;	}	BUG_ON(p_blkno == 0);	for(i = 0; i < wc->w_num_pages; i++) {		int tmpret;		tmpret = ocfs2_prepare_page_for_write(inode, &p_blkno, wc,						      wc->w_pages[i], cpos,						      user_pos, user_len,						      should_zero);		if (tmpret) {			mlog_errno(tmpret);			if (ret == 0)				tmpret = ret;		}	}	/*	 * We only have cleanup to do in case of allocating write.	 */	if (ret && new)		ocfs2_write_failure(inode, wc, user_pos, user_len);out:	return ret;}static int ocfs2_write_cluster_by_desc(struct address_space *mapping,				       struct ocfs2_alloc_context *data_ac,				       struct ocfs2_alloc_context *meta_ac,				       struct ocfs2_write_ctxt *wc,				       loff_t pos, unsigned len){	int ret, i;	loff_t cluster_off;	unsigned int local_len = len;	struct ocfs2_write_cluster_desc *desc;	struct ocfs2_super *osb = OCFS2_SB(mapping->host->i_sb);	for (i = 0; i < wc->w_clen; i++) {		desc = &wc->w_desc[i];		/*		 * We have to make sure that the total write passed in		 * doesn't extend past a single cluster.		 */		local_len = len;		cluster_off = pos & (osb->s_clustersize - 1);		if ((cluster_off + local_len) > osb->s_clustersize)			local_len = osb->s_clustersize - cluster_off;		ret = ocfs2_write_cluster(mapping, desc->c_phys,					  desc->c_unwritten, data_ac, meta_ac,					  wc, desc->c_cpos, pos, local_len);		if (ret) {			mlog_errno(ret);			goto out;		}		len -= local_len;		pos += local_len;	}	ret = 0;out:	return ret;}/* * ocfs2_write_end() wants to know which parts of the target page it * should complete the write on. It's easiest to compute them ahead of * time when a more complete view of the write is available. */static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,					struct ocfs2_write_ctxt *wc,					loff_t pos, unsigned len, int alloc){	struct ocfs2_write_cluster_desc *desc;	wc->w_target_from = pos & (PAGE_CACHE_SIZE - 1);	wc->w_target_to = wc->w_target_from + len;	if (alloc == 0)		return;	/*	 * Allocating write - we may have different boundaries based	 * on page size and cluster size.	 *	 * NOTE: We can no longer compute one value from the other as	 * the actual write length and user provided length may be	 * different.	 */	if (wc->w_large_pages) {		/*		 * We only care about the 1st and last cluster within		 * our range and whether they should be zero'd or not. Either		 * value may be extended out to the start/end of a		 * newly allocated cluster.		 */		desc = &wc->w_desc[0];		if (ocfs2_should_zero_cluster(desc))			ocfs2_figure_cluster_boundaries(osb,							desc->c_cpos,							&wc->w_target_from,							NULL);		desc = &wc->w_desc[wc->w_clen - 1];		if (ocfs2_should_zero_cluster(desc))			ocfs2_figure_cluster_boundaries(osb,							desc->c_cpos,							NULL,							&wc->w_target_to);	} else {		wc->w_target_from = 0;		wc->w_target_to = PAGE_CACHE_SIZE;	}}/* * Populate each single-cluster write descriptor in the write context * with information about the i/o to be done. * * Returns the number of clusters that will have to be allocated, as * well as a worst case estimate of the number of extent records that * would have to be created during a write to an unwritten region. */static int ocfs2_populate_write_desc(struct inode *inode,				     struct ocfs2_write_ctxt *wc,				     unsigned int *clusters_to_alloc,				     unsigned int *extents_to_split){	int ret;	struct ocfs2_write_cluster_desc *desc;	unsigned int num_clusters = 0;	unsigned int ext_flags = 0;	u32 phys = 0;	int i;	*clusters_to_alloc = 0;	*extents_to_split = 0;	for (i = 0; i < wc->w_clen; i++) {		desc = &wc->w_desc[i];		desc->c_cpos = wc->w_cpos + i;		if (num_clusters == 0) {			/*			 * Need to look up the next extent record.			 */			ret = ocfs2_get_clusters(inode, desc->c_cpos, &phys,						 &num_clusters, &ext_flags);			if (ret) {				mlog_errno(ret);				goto out;			}			/*			 * Assume worst case - that we're writing in			 * the middle of the extent.			 *			 * We can assume that the write proceeds from			 * left to right, in which case the extent			 * insert code is smart enough to coalesce the			 * next splits into the previous records created.			 */

⌨️ 快捷键说明

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