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

📄 inode.c

📁 ocfs1.4.1 oracle分布式文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (can_lock) {		status = ocfs2_open_lock(inode);		if (status) {			make_bad_inode(inode);			mlog_errno(status);			return status;		}		status = ocfs2_inode_lock(inode, NULL, 0);		if (status) {			make_bad_inode(inode);			mlog_errno(status);			return status;		}	}	if (args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) {		status = ocfs2_try_open_lock(inode, 0);		if (status) {			make_bad_inode(inode);				return status;		}	}	status = ocfs2_read_block(osb, args->fi_blkno, &bh, 0,				  can_lock ? inode : NULL);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = -EINVAL;	fe = (struct ocfs2_dinode *) bh->b_data;	if (!OCFS2_IS_VALID_DINODE(fe)) {		mlog(0, "Invalid dinode #%llu: signature = %.*s\n",		     (unsigned long long)args->fi_blkno, 7,		     fe->i_signature);		goto bail;	}	/*	 * This is a code bug. Right now the caller needs to	 * understand whether it is asking for a system file inode or	 * not so the proper lock names can be built.	 */	mlog_bug_on_msg(!!(fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) !=			!!(args->fi_flags & OCFS2_FI_FLAG_SYSFILE),			"Inode %llu: system file state is ambigous\n",			(unsigned long long)args->fi_blkno);	if (S_ISCHR(le16_to_cpu(fe->i_mode)) ||	    S_ISBLK(le16_to_cpu(fe->i_mode)))    		inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));	if (ocfs2_populate_inode(inode, fe, 0) < 0)		goto bail;	BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));	status = 0;bail:	if (can_lock)		ocfs2_inode_unlock(inode, 0);	if (status < 0)		make_bad_inode(inode);	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_truncate_context *tc = NULL;	struct ocfs2_dinode *fe;	handle_t *handle = NULL;	mlog_entry_void();	fe = (struct ocfs2_dinode *) fe_bh->b_data;	/*	 * This check will also skip truncate of inodes with inline	 * data and fast symlinks.	 */	if (fe->i_clusters) {		handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);		if (IS_ERR(handle)) {			status = PTR_ERR(handle);			mlog_errno(status);			goto out;		}		status = ocfs2_journal_access(handle, inode, fe_bh,					      OCFS2_JOURNAL_ACCESS_WRITE);		if (status < 0) {			mlog_errno(status);			goto out;		}		i_size_write(inode, 0);		status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);		if (status < 0) {			mlog_errno(status);			goto out;		}		ocfs2_commit_trans(osb, handle);		handle = NULL;		status = ocfs2_prepare_truncate(osb, inode, fe_bh, &tc);		if (status < 0) {			mlog_errno(status);			goto out;		}		status = ocfs2_commit_truncate(osb, inode, fe_bh, tc);		if (status < 0) {			mlog_errno(status);			goto out;		}	}out:	if (handle)		ocfs2_commit_trans(osb, 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;	handle_t *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_inode_lock(inode_alloc_inode, &inode_alloc_bh, 1);	if (status < 0) {		mutex_unlock(&inode_alloc_inode->i_mutex);		mlog_errno(status);		goto bail;	}	handle = ocfs2_start_trans(osb, 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);	di->i_flags &= cpu_to_le32(~(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(osb, handle);bail_unlock:	ocfs2_inode_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 it 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);	struct ocfs2_dinode *di;	di = (struct ocfs2_dinode *) di_bh->b_data;	orphaned_slot = le16_to_cpu(di->i_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_inode_lock(orphan_dir_inode, &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 try an	 * inode delete underneath 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_inode_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 * trylock 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 downconvert_thread 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->dc_task) {		mlog(0, "Skipping delete of %lu because we're currently "		     "in downconvert\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 %llu\n",		     (unsigned long long)oi->ip_blkno);		goto bail_unlock;	}	/* If we have allowd 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 %llu because flags changed\n",		     (unsigned long long)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 %llu because nlink = %u\n",		     (unsigned long long)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 %llu (on-disk %llu) not orphaned! "		     "Disk flags  0x%x, inode flags 0x%x\n",		     (unsigned long long)oi->ip_blkno,		     (unsigned long long)le64_to_cpu(di->i_blkno),		     le32_to_cpu(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;	}	/*	 * This is how ocfs2 determines whether an inode is still live	 * within the cluster. Every node takes a shared read lock on	 * the inode open lock in ocfs2_read_locked_inode(). When we

⌨️ 快捷键说明

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