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

📄 inode.c

📁 ocfs1.2.7 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (sysfile)	       OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;	status = 0;bail:	if (args && bh)		brelse(bh);	mlog_exit(status);	return status;}void ocfs2_sync_blockdev(struct super_block *sb){	sync_blockdev(sb->s_bdev);}static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,				     struct inode *inode,				     struct buffer_head *fe_bh){	int status = 0;	struct ocfs2_journal_handle *handle = NULL;	struct ocfs2_truncate_context *tc = NULL;	struct ocfs2_dinode *fe;	mlog_entry_void();	fe = (struct ocfs2_dinode *) fe_bh->b_data;	/* zero allocation, zero truncate :) */	if (!fe->i_clusters)		goto bail;	handle = ocfs2_start_trans(osb, handle, OCFS2_INODE_UPDATE_CREDITS);	if (IS_ERR(handle)) {		status = PTR_ERR(handle);		handle = NULL;		mlog_errno(status);		goto bail;	}	status = ocfs2_set_inode_size(handle, inode, fe_bh, 0ULL);	if (status < 0) {		mlog_errno(status);		goto bail;	}	ocfs2_commit_trans(handle);	handle = NULL;	status = ocfs2_prepare_truncate(osb, inode, fe_bh, &tc);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = ocfs2_commit_truncate(osb, inode, fe_bh, tc);	if (status < 0) {		mlog_errno(status);		goto bail;	}bail:	if (handle)		ocfs2_commit_trans(handle);	mlog_exit(status);	return status;}static int ocfs2_remove_inode(struct inode *inode,			      struct buffer_head *di_bh,			      struct inode *orphan_dir_inode,			      struct buffer_head *orphan_dir_bh){	int status;	struct inode *inode_alloc_inode = NULL;	struct buffer_head *inode_alloc_bh = NULL;	struct ocfs2_journal_handle *handle;	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);	struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;	inode_alloc_inode =		ocfs2_get_system_file_inode(osb, INODE_ALLOC_SYSTEM_INODE,					    le16_to_cpu(di->i_suballoc_slot));	if (!inode_alloc_inode) {		status = -EEXIST;		mlog_errno(status);		goto bail;	}	mutex_lock(&inode_alloc_inode->i_mutex);	status = ocfs2_meta_lock(inode_alloc_inode, NULL, &inode_alloc_bh, 1);	if (status < 0) {		mutex_unlock(&inode_alloc_inode->i_mutex);		mlog_errno(status);		goto bail;	}	handle = ocfs2_start_trans(osb, NULL, OCFS2_DELETE_INODE_CREDITS);	if (IS_ERR(handle)) {		status = PTR_ERR(handle);		mlog_errno(status);		goto bail_unlock;	}	status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode,				  orphan_dir_bh);	if (status < 0) {		mlog_errno(status);		goto bail_commit;	}	/* set the inodes dtime */	status = ocfs2_journal_access(handle, inode, di_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto bail_commit;	}	di->i_dtime = cpu_to_le64(CURRENT_TIME.tv_sec);	le32_and_cpu(&di->i_flags, ~(OCFS2_VALID_FL | OCFS2_ORPHANED_FL));	status = ocfs2_journal_dirty(handle, di_bh);	if (status < 0) {		mlog_errno(status);		goto bail_commit;	}	ocfs2_remove_from_cache(inode, di_bh);	status = ocfs2_free_dinode(handle, inode_alloc_inode,				   inode_alloc_bh, di);	if (status < 0)		mlog_errno(status);bail_commit:	ocfs2_commit_trans(handle);bail_unlock:	ocfs2_meta_unlock(inode_alloc_inode, 1);	mutex_unlock(&inode_alloc_inode->i_mutex);	brelse(inode_alloc_bh);bail:	iput(inode_alloc_inode);	return status;}/*  * Serialize with orphan dir recovery. If the process doing * recovery on this orphan dir does an iget() with the dir * i_mutex held, we'll deadlock here. Instead we detect this * and exit early - recovery will wipe this inode for us. */static int ocfs2_check_orphan_recovery_state(struct ocfs2_super *osb,					     int slot){	int ret = 0;	spin_lock(&osb->osb_lock);	if (ocfs2_node_map_test_bit(osb, &osb->osb_recovering_orphan_dirs, slot)) {		mlog(0, "Recovery is happening on orphan dir %d, will skip "		     "this inode\n", slot);		ret = -EDEADLK;		goto out;	}	/* This signals to the orphan recovery process that is should	 * wait for us to handle the wipe. */	osb->osb_orphan_wipes[slot]++;out:	spin_unlock(&osb->osb_lock);	return ret;}static void ocfs2_signal_wipe_completion(struct ocfs2_super *osb,					 int slot){	spin_lock(&osb->osb_lock);	osb->osb_orphan_wipes[slot]--;	spin_unlock(&osb->osb_lock);	wake_up(&osb->osb_wipe_event);}static int ocfs2_wipe_inode(struct inode *inode,			    struct buffer_head *di_bh){	int status, orphaned_slot;	struct inode *orphan_dir_inode = NULL;	struct buffer_head *orphan_dir_bh = NULL;	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);	/* We've already voted on this so it should be readonly - no	 * spinlock needed. */	orphaned_slot = OCFS2_I(inode)->ip_orphaned_slot;	status = ocfs2_check_orphan_recovery_state(osb, orphaned_slot);	if (status)		return status;	orphan_dir_inode = ocfs2_get_system_file_inode(osb,						       ORPHAN_DIR_SYSTEM_INODE,						       orphaned_slot);	if (!orphan_dir_inode) {		status = -EEXIST;		mlog_errno(status);		goto bail;	}	/* Lock the orphan dir. The lock will be held for the entire	 * delete_inode operation. We do this now to avoid races with	 * recovery completion on other nodes. */	mutex_lock(&orphan_dir_inode->i_mutex);	status = ocfs2_meta_lock(orphan_dir_inode, NULL, &orphan_dir_bh, 1);	if (status < 0) {		mutex_unlock(&orphan_dir_inode->i_mutex);		mlog_errno(status);		goto bail;	}	/* we do this while holding the orphan dir lock because we	 * don't want recovery being run from another node to vote for	 * an inode delete on us -- this will result in two nodes	 * truncating the same file! */	status = ocfs2_truncate_for_delete(osb, inode, di_bh);	if (status < 0) {		mlog_errno(status);		goto bail_unlock_dir;	}	status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode,				    orphan_dir_bh);	if (status < 0)		mlog_errno(status);bail_unlock_dir:	ocfs2_meta_unlock(orphan_dir_inode, 1);	mutex_unlock(&orphan_dir_inode->i_mutex);	brelse(orphan_dir_bh);bail:	iput(orphan_dir_inode);	ocfs2_signal_wipe_completion(osb, orphaned_slot);	return status;}/* There is a series of simple checks that should be done before a * vote is even considered. Encapsulate those in this function. */static int ocfs2_inode_is_valid_to_delete(struct inode *inode){	int ret = 0;	struct ocfs2_inode_info *oi = OCFS2_I(inode);	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);	/* We shouldn't be getting here for the root directory	 * inode.. */	if (inode == osb->root_inode) {		mlog(ML_ERROR, "Skipping delete of root inode.\n");		goto bail;	}	/* If we're coming from process_vote we can't go into our own	 * voting [hello, deadlock city!], so unforuntately we just	 * have to skip deleting this guy. That's OK though because	 * the node who's doing the actual deleting should handle it	 * anyway. */	if (current == osb->vote_task) {		mlog(0, "Skipping delete of %lu because we're currently "		     "in process_vote\n", inode->i_ino);		goto bail;	}	spin_lock(&oi->ip_lock);	/* OCFS2 *never* deletes system files. This should technically	 * never get here as system file inodes should always have a	 * positive link count. */	if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) {		mlog(ML_ERROR, "Skipping delete of system file %"MLFu64".\n",		     oi->ip_blkno);		goto bail_unlock;	}	/* If we have voted "yes" on the wipe of this inode for	 * another node, it will be marked here so we can safely skip	 * it. Recovery will cleanup any inodes we might inadvertantly	 * skip here. */	if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE) {		mlog(0, "Skipping delete of %lu because another node "		     "has done this for us.\n", inode->i_ino);		goto bail_unlock;	}	ret = 1;bail_unlock:	spin_unlock(&oi->ip_lock);bail:	return ret;}/* Query the cluster to determine whether we should wipe an inode from * disk or not. * * Requires the inode to have the cluster lock. */static int ocfs2_query_inode_wipe(struct inode *inode,				  struct buffer_head *di_bh,				  int *wipe){	int status = 0;	struct ocfs2_inode_info *oi = OCFS2_I(inode);	struct ocfs2_dinode *di;	*wipe = 0;	/* While we were waiting for the cluster lock in	 * ocfs2_delete_inode, another node might have asked to delete	 * the inode. Recheck our flags to catch this. */	if (!ocfs2_inode_is_valid_to_delete(inode)) {		mlog(0, "Skipping delete of %"MLFu64" because flags changed\n",		     oi->ip_blkno);		goto bail;	}	/* Now that we have an up to date inode, we can double check	 * the link count. */	if (inode->i_nlink) {		mlog(0, "Skipping delete of %"MLFu64" because nlink = %u\n",		     oi->ip_blkno, inode->i_nlink);		goto bail;	}	/* Do some basic inode verification... */	di = (struct ocfs2_dinode *) di_bh->b_data;	if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL))) {		/* for lack of a better error? */		status = -EEXIST;		mlog(ML_ERROR,		     "Inode %"MLFu64" (on-disk %"MLFu64") not orphaned! "		     "Disk flags  0x%x, inode flags 0x%x\n",		     oi->ip_blkno, di->i_blkno, di->i_flags, oi->ip_flags);		goto bail;	}	/* has someone already deleted us?! baaad... */	if (di->i_dtime) {		status = -EEXIST;		mlog_errno(status);		goto bail;	}	status = ocfs2_request_delete_vote(inode);	/* -EBUSY means that other nodes are still using the	 * inode. We're done here though, so avoid doing anything on	 * disk and let them worry about deleting it. */	if (status == -EBUSY) {		status = 0;		mlog(0, "Skipping delete of %"MLFu64" because it is in use on"		     "other nodes\n", oi->ip_blkno);		goto bail;	}	if (status < 0) {		mlog_errno(status);		goto bail;	}	spin_lock(&oi->ip_lock);	if (oi->ip_orphaned_slot == OCFS2_INVALID_SLOT) {		/* Nobody knew which slot this inode was orphaned		 * into. This may happen during node death and		 * recovery knows how to clean it up so we can safely		 * ignore this inode for now on. */		mlog(0, "Nobody knew where inode %"MLFu64" was orphaned!\n",		     oi->ip_blkno);	} else {		*wipe = 1;		mlog(0, "Inode %"MLFu64" is ok to wipe from orphan dir %d\n",		     oi->ip_blkno, oi->ip_orphaned_slot);	}	spin_unlock(&oi->ip_lock);bail:	return status;}/* Support function for ocfs2_delete_inode. Will help us keep the * inode data in a consistent state for clear_inode. Always truncates * pages, optionally sync's them first. */static void ocfs2_cleanup_delete_inode(struct inode *inode,				       int sync_data){	mlog(0, "Cleanup inode %"MLFu64", sync = %d\n",

⌨️ 快捷键说明

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