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

📄 file.c

📁 ocfs1.2.7 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
				       size >> PAGE_CACHE_SHIFT);		if (!page) {			res = -ENOMEM;			mlog_errno(res);			return res;		}		offset = (unsigned int)(size & (PAGE_CACHE_SIZE - 1)) + 1;		res = mapping->a_ops->prepare_write(NULL, page, offset,						    offset);		if (res < 0) {			mlog_errno(res);			goto bail_unlock;		}		res = mapping->a_ops->commit_write(NULL, page, offset, offset);		if (res < 0)			mlog_errno(res);bail_unlock:		unlock_page(page);		page_cache_release(page);		mark_inode_dirty(inode);	}	return res;}/* * extend allocation only here. * we'll update all the disk stuff, and oip->alloc_size * * expect stuff to be locked, a transaction started and enough data / * metadata reservations in the contexts. I'll return -EAGAIN, if we * run out of transaction credits, so the caller can restart us. */int ocfs2_extend_allocation(struct ocfs2_super *osb,			    struct inode *inode,			    u32 clusters_to_add,			    struct buffer_head *fe_bh,			    struct ocfs2_journal_handle *handle,			    struct ocfs2_alloc_context *data_ac,			    struct ocfs2_alloc_context *meta_ac,			    enum ocfs2_alloc_restarted *reason){	int status = 0;	int free_extents;	struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;	u32 bit_off, num_bits;	u64 block;	BUG_ON(!clusters_to_add);	free_extents = ocfs2_num_free_extents(osb, inode, fe);	if (free_extents < 0) {		status = free_extents;		mlog_errno(status);		goto leave;	}	/* there are two cases which could cause us to EAGAIN in the	 * we-need-more-metadata case:	 * 1) we haven't reserved *any*	 * 2) we are so fragmented, we've needed to add metadata too	 *    many times. */	if (!free_extents && !meta_ac) {		mlog(0, "we haven't reserved any metadata!\n");		status = -EAGAIN;		if (reason)			*reason = RESTART_META;		goto leave;	} else if ((!free_extents)		   && (ocfs2_alloc_context_bits_left(meta_ac)		       < ocfs2_extend_meta_needed(fe))) {		mlog(0, "filesystem is really fragmented...\n");		status = -EAGAIN;		if (reason)			*reason = RESTART_META;		goto leave;	}	status = ocfs2_claim_clusters(osb, handle, data_ac, 1,				      &bit_off, &num_bits);	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto leave;	}	BUG_ON(num_bits > clusters_to_add);	/* reserve our write early -- insert_extent may update the inode */	status = ocfs2_journal_access(handle, inode, fe_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto leave;	}	block = ocfs2_clusters_to_blocks(osb->sb, bit_off);	mlog(0, "Allocating %u clusters at block %u for inode %"MLFu64"\n",	     num_bits, bit_off, OCFS2_I(inode)->ip_blkno);	status = ocfs2_insert_extent(osb, handle, inode, fe_bh, block,				     num_bits, meta_ac);	if (status < 0) {		mlog_errno(status);		goto leave;	}	le32_add_cpu(&fe->i_clusters, num_bits);	spin_lock(&OCFS2_I(inode)->ip_lock);	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);	spin_unlock(&OCFS2_I(inode)->ip_lock);	status = ocfs2_journal_dirty(handle, fe_bh);	if (status < 0) {		mlog_errno(status);		goto leave;	}	clusters_to_add -= num_bits;	if (clusters_to_add) {		mlog(0, "need to alloc once more, clusters = %u, wanted = "		     "%u\n", fe->i_clusters, clusters_to_add);		status = -EAGAIN;		if (reason)			*reason = RESTART_TRANS;	}leave:	mlog_exit(status);	return status;}/* * Ok, this function is heavy on the goto's - we need to clean it up a * bit. * * *bytes_extended is a measure of how much was added to * dinode->i_size, NOT how much allocated was actually added to the * file. It will always be correct, even when we return an error. */int ocfs2_extend_file(struct ocfs2_super *osb,		      struct inode *inode,		      u64 new_i_size,		      u64 *bytes_extended){	int status = 0;	int restart_func = 0;	int drop_alloc_sem = 0;	int credits, num_free_extents;	u32 clusters_to_add;	u64 new_fe_size;	struct buffer_head *bh = NULL;	struct ocfs2_dinode *fe;	struct ocfs2_journal_handle *handle = NULL;	struct ocfs2_alloc_context *data_ac = NULL;	struct ocfs2_alloc_context *meta_ac = NULL;	enum ocfs2_alloc_restarted why;	mlog_entry("(Inode %"MLFu64" new_i_size=%"MLFu64")\n",		   OCFS2_I(inode)->ip_blkno, new_i_size);	*bytes_extended = 0;	/* setattr sometimes calls us like this. */	if (new_i_size == 0)		goto leave;restart_all:	handle = ocfs2_alloc_handle(osb);	if (handle == NULL) {		status = -ENOMEM;		mlog_errno(status);		goto leave;	}	status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,				  OCFS2_BH_CACHED, inode);	if (status < 0) {		mlog_errno(status);		goto leave;	}	fe = (struct ocfs2_dinode *) bh->b_data;	if (!OCFS2_IS_VALID_DINODE(fe)) {		OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);		status = -EIO;		goto leave;	}	mlog_bug_on_msg(i_size_read(inode) !=			(le64_to_cpu(fe->i_size) - *bytes_extended),			"Inode %"MLFu64" i_size = %lld, dinode i_size "			"= %"MLFu64", bytes_extended = %"MLFu64", new_i_size "			"= %"MLFu64"\n", OCFS2_I(inode)->ip_blkno,			i_size_read(inode), le64_to_cpu(fe->i_size),			*bytes_extended, new_i_size);	mlog_bug_on_msg(new_i_size < i_size_read(inode),			"Inode %"MLFu64", i_size = %lld, new sz = %"MLFu64"\n",			OCFS2_I(inode)->ip_blkno, i_size_read(inode),			new_i_size);	if (i_size_read(inode) == new_i_size)  		goto leave;	clusters_to_add = ocfs2_clusters_for_bytes(osb->sb, new_i_size) -			  le32_to_cpu(fe->i_clusters);	mlog(0, "extend inode %"MLFu64", new_i_size = %"MLFu64", "		"i_size = %lld, fe->i_clusters = %u, clusters_to_add = %u\n",	     OCFS2_I(inode)->ip_blkno, new_i_size, i_size_read(inode),	     fe->i_clusters, clusters_to_add);	if (!clusters_to_add)		goto do_start_trans;	num_free_extents = ocfs2_num_free_extents(osb,						  inode,						  fe);	if (num_free_extents < 0) {		status = num_free_extents;		mlog_errno(status);		goto leave;	}	if (!num_free_extents) {		status = ocfs2_reserve_new_metadata(osb,						    handle,						    fe,						    &meta_ac);		if (status < 0) {			if (status != -ENOSPC)				mlog_errno(status);			goto leave;		}	}	status = ocfs2_reserve_clusters(osb,					handle,					clusters_to_add,					&data_ac);	if (status < 0) {		if (status != -ENOSPC)			mlog_errno(status);		goto leave;	}	/* blocks peope in read/write from reading our allocation	 * until we're done changing it. We depend on i_mutex to block	 * other extend/truncate calls while we're here. Ordering wrt	 * start_trans is important here -- always do it before! */	down_write(&OCFS2_I(inode)->ip_alloc_sem);	drop_alloc_sem = 1;do_start_trans:	credits = ocfs2_calc_extend_credits(osb->sb, fe, clusters_to_add);	handle = ocfs2_start_trans(osb, handle, credits);	if (IS_ERR(handle)) {		status = PTR_ERR(handle);		handle = NULL;		mlog_errno(status);		goto leave;	}restarted_transaction:	/* reserve a write to the file entry early on - that we if we	 * run out of credits in the allocation path, we can still	 * update i_size. */	status = ocfs2_journal_access(handle, inode, bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto leave;	}	if (!clusters_to_add)		goto no_alloc;	status = ocfs2_extend_allocation(osb,					 inode,					 clusters_to_add,					 bh,					 handle,					 data_ac,					 meta_ac,					 &why);	if ((status < 0) && (status != -EAGAIN)) {		if (status != -ENOSPC)			mlog_errno(status);		goto leave;	}	if (status == -EAGAIN && (new_i_size >	    ocfs2_clusters_to_bytes(osb->sb, le32_to_cpu(fe->i_clusters)))) {		if (why == RESTART_META) {			mlog(0, "Inode %"MLFu64" restarting function.\n",			     OCFS2_I(inode)->ip_blkno);			restart_func = 1;		} else {			BUG_ON(why != RESTART_TRANS);			new_fe_size = ocfs2_clusters_to_bytes(osb->sb,						le32_to_cpu(fe->i_clusters));			*bytes_extended += new_fe_size -					   le64_to_cpu(fe->i_size);			/* update i_size in case we crash after the			 * extend_trans */			fe->i_size = cpu_to_le64(new_fe_size);			fe->i_mtime = cpu_to_le64(CURRENT_TIME.tv_sec);			fe->i_mtime_nsec = cpu_to_le32(CURRENT_TIME.tv_nsec);			status = ocfs2_journal_dirty(handle, bh);			if (status < 0) {				mlog_errno(status);				goto leave;			}			clusters_to_add =				ocfs2_clusters_for_bytes(osb->sb,							 new_i_size)				- le32_to_cpu(fe->i_clusters);			mlog(0, "Inode %"MLFu64" restarting transaction.\n",			     OCFS2_I(inode)->ip_blkno);			/* TODO: This can be more intelligent. */			credits = ocfs2_calc_extend_credits(osb->sb,							    fe,							    clusters_to_add);			status = ocfs2_extend_trans(handle, credits);			if (status < 0) {				/* handle still has to be committed at				 * this point. */				status = -ENOMEM;				mlog_errno(status);				goto leave;			}			goto restarted_transaction;		}	}	status = 0;no_alloc:	/* this may not be the end of our allocation so only update	 * i_size to what's appropriate. */	new_fe_size = ocfs2_clusters_to_bytes(osb->sb,					      le32_to_cpu(fe->i_clusters));	if (new_i_size < new_fe_size)		new_fe_size = new_i_size;	*bytes_extended += new_fe_size - le64_to_cpu(fe->i_size);	fe->i_size = cpu_to_le64(new_fe_size);	mlog(0, "fe: i_clusters = %u, i_size=%"MLFu64"\n",	     le32_to_cpu(fe->i_clusters), le64_to_cpu(fe->i_size));	mlog(0, "inode: ip_clusters=%u, i_size=%lld\n",	     OCFS2_I(inode)->ip_clusters, i_size_read(inode));	fe->i_ctime = fe->i_mtime = cpu_to_le64(CURRENT_TIME.tv_sec);	fe->i_ctime_nsec = fe->i_mtime_nsec = cpu_to_le32(CURRENT_TIME.tv_nsec);	status = ocfs2_journal_dirty(handle, bh);	if (status < 0) {		mlog_errno(status);		goto leave;	}leave:	if (drop_alloc_sem) {		up_write(&OCFS2_I(inode)->ip_alloc_sem);		drop_alloc_sem = 0;	}	if (handle) {		ocfs2_commit_trans(handle);		handle = NULL;	}	if (data_ac) {		ocfs2_free_alloc_context(data_ac);		data_ac = NULL;	}	if (meta_ac) {		ocfs2_free_alloc_context(meta_ac);		meta_ac = NULL;	}	if (bh) {		brelse(bh);		bh = NULL;	}	if ((!status) && restart_func) {		restart_func = 0;		goto restart_all;	}	mlog_exit(status);	return status;}static int ocfs2_setattr_newsize(struct ocfs2_super *osb, struct inode *inode,				 u64 newsize){	u64 bytes_added = 0;	u64 actual_size;	int tmp_status;	int status;	if (i_size_read(inode) > newsize) {		status = ocfs2_truncate_file(osb, newsize, inode);		/* should this be translating errnos to enospc?  it		 * used to.. */		if (status < 0 && status != -ENOSPC)			mlog_errno(status);		/* _truncate_file calls _set_file_size which updates		 * mmu_private and i_size, we're done.. */		goto out;	}	/* 	 * protect the pages that ocfs2_zero_extend is going to	 * be pulling into the page cache.. we do this before the	 * metadata extend so that we don't get into the situation	 * where we've extended the metadata but can't get the data	 * lock to zero.	 */	status = ocfs2_data_lock(inode, 1);	if (status < 0) {		mlog_errno(status);		goto out;	}	status = ocfs2_extend_file(osb, inode, newsize, &bytes_added);	if (status < 0 && (!bytes_added)) {		if (status != -ENOSPC)			mlog_errno(status);		status = -ENOSPC;		goto out_unlock;	}	/* partial extend, we continue with what we've got. */	if (status < 0	    && status != -ENOSPC	    && status != -EINTR	    && status != -ERESTARTSYS)		mlog(ML_ERROR,		     "status return of %d extending inode "		     "%"MLFu64"\n", status,		     OCFS2_I(inode)->ip_blkno);		actual_size = bytes_added + i_size_read(inode);	if ((newsize > actual_size) && (status == 0))		status = -ENOSPC;	if (bytes_added)		ocfs2_update_inode_size(inode, actual_size);#ifdef OCFS2_ORACORE_WORKAROUNDS	spin_lock(&OCFS2_I(inode)->ip_lock);	if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_OPEN_DIRECT) {		/* This is a total broken hack for O_DIRECT crack */		OCFS2_I(inode)->ip_mmu_private = i_size_read(inode);	}	spin_unlock(&OCFS2_I(inode)->ip_lock);#endif	tmp_status = status;	status = ocfs2_zero_extend(inode);	if (status < 0)		mlog_errno(status);	if (tmp_status < 0) 		status = tmp_status;out_unlock:	ocfs2_data_unlock(inode, 1);out:	return status;}int ocfs2_setattr(struct dentry *dentry, struct iattr *attr){	int status = 0;	u64 newsize;	struct inode *inode = dentry->d_inode;	struct super_block *sb = inode->i_sb;	struct ocfs2_super *osb = OCFS2_SB(sb);	struct buffer_head *bh = NULL;	struct ocfs2_journal_handle *handle = NULL;	mlog_entry("(0x%p, '%.*s', inode %"MLFu64")\n", dentry,	           dentry->d_name.len, dentry->d_name.name,		   OCFS2_I(inode)->ip_blkno);	if (attr->ia_valid & ATTR_MODE)		mlog(0, "mode change: %d\n", attr->ia_mode);	if (attr->ia_valid & ATTR_UID)		mlog(0, "uid change: %d\n", attr->ia_uid);	if (attr->ia_valid & ATTR_GID)		mlog(0, "gid change: %d\n", attr->ia_gid);	if (attr->ia_valid & ATTR_SIZE)		mlog(0, "size change...\n");	if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME))		mlog(0, "time change...\n");#define OCFS2_VALID_ATTRS (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME | ATTR_SIZE \			   | ATTR_GID | ATTR_UID | ATTR_MODE)	if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) {		mlog(0, "can't handle attrs: 0x%x\n", attr->ia_valid);		return 0;	}	status = inode_change_ok(inode, attr);	if (status)		return status;	newsize = attr->ia_size;	status = ocfs2_meta_lock(inode, NULL, &bh, 1);	if (status < 0) {		if (status != -ENOENT)			mlog_errno(status);		goto bail;	}	if (S_ISREG(inode->i_mode) &&	    attr->ia_valid & ATTR_SIZE &&	    newsize != i_size_read(inode)) {		status = ocfs2_setattr_newsize(osb, inode, newsize);		if (status < 0)			goto bail_unlock;	}	handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);	if (IS_ERR(handle)) {		status = PTR_ERR(handle);		mlog_errno(status);		goto bail_unlock;	}	status = inode_setattr(inode, attr);	if (status < 0) {		mlog_errno(status);		goto bail_commit;	}	status = ocfs2_mark_inode_dirty(handle, inode, bh);	if (status < 0)		mlog_errno(status);bail_commit:	ocfs2_commit_trans(handle);bail_unlock:	ocfs2_meta_unlock(inode, 1);bail:	if (bh)		brelse(bh);	mlog_exit(status);	return status;}int ocfs2_getattr(struct vfsmount *mnt,		  struct dentry *dentry,		  struct kstat *stat){	struct inode *inode = dentry->d_inode;	struct super_block *sb = dentry->d_inode->i_sb;	struct ocfs2_super *osb = sb->s_fs_info;	int err;	mlog_entry_void();	err = ocfs2_inode_revalidate(dentry);	if (err) {		if (err != -ENOENT)			mlog_errno(err);		goto bail;	}	generic_fillattr(inode, stat);	/* We set the blksize from the cluster size for performance */	stat->blksize = osb->s_clustersize;bail:	mlog_exit(err);	return err;}struct inode_operations ocfs2_file_iops = {	.setattr	= ocfs2_setattr,	.getattr	= ocfs2_getattr,};struct inode_operations ocfs2_special_file_iops = {	.setattr	= ocfs2_setattr,	.getattr	= ocfs2_getattr,};

⌨️ 快捷键说明

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