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

📄 inode.c

📁 ocfs1.4.1 oracle分布式文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * get to ->delete_inode(), each node tries to convert it's	 * lock to an exclusive. Trylocks are serialized by the inode	 * meta data lock. If the upconvert suceeds, we know the inode	 * is no longer live and can be deleted.	 *	 * Though we call this with the meta data lock held, the	 * trylock keeps us from ABBA deadlock.	 */	status = ocfs2_try_open_lock(inode, 1);	if (status == -EAGAIN) {		status = 0;		mlog(0, "Skipping delete of %llu because it is in use on "		     "other nodes\n", (unsigned long long)oi->ip_blkno);		goto bail;	}	if (status < 0) {		mlog_errno(status);		goto bail;	}	*wipe = 1;	mlog(0, "Inode %llu is ok to wipe from orphan dir %u\n",	     (unsigned long long)oi->ip_blkno,	     le16_to_cpu(di->i_orphaned_slot));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 %llu, sync = %d\n",	     (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data);	if (sync_data)		write_inode_now(inode, 1);	truncate_inode_pages(&inode->i_data, 0);}void ocfs2_delete_inode(struct inode *inode){	int wipe, status;	sigset_t blocked, oldset;	struct buffer_head *di_bh = NULL;	mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);	if (is_bad_inode(inode)) {		mlog(0, "Skipping delete of bad inode\n");		goto bail;	}	if (!ocfs2_inode_is_valid_to_delete(inode)) {		/* It's probably not necessary to truncate_inode_pages		 * here but we do it for safety anyway (it will most		 * likely be a no-op anyway) */		ocfs2_cleanup_delete_inode(inode, 0);		goto bail;	}	/* We want to block signals in delete_inode as the lock and	 * messaging paths may return us -ERESTARTSYS. Which would	 * cause us to exit early, resulting in inodes being orphaned	 * forever. */	sigfillset(&blocked);	status = sigprocmask(SIG_BLOCK, &blocked, &oldset);	if (status < 0) {		mlog_errno(status);		ocfs2_cleanup_delete_inode(inode, 1);		goto bail;	}	/* Lock down the inode. This gives us an up to date view of	 * it's metadata (for verification), and allows us to	 * serialize delete_inode on multiple nodes.	 *	 * Even though we might be doing a truncate, we don't take the	 * allocation lock here as it won't be needed - nobody will	 * have the file open.	 */	status = ocfs2_inode_lock(inode, &di_bh, 1);	if (status < 0) {		if (status != -ENOENT)			mlog_errno(status);		ocfs2_cleanup_delete_inode(inode, 0);		goto bail_unblock;	}	/* Query the cluster. This will be the final decision made	 * before we go ahead and wipe the inode. */	status = ocfs2_query_inode_wipe(inode, di_bh, &wipe);	if (!wipe || status < 0) {		/* Error and remote inode busy both mean we won't be		 * removing the inode, so they take almost the same		 * path. */		if (status < 0)			mlog_errno(status);		/* Someone in the cluster has disallowed a wipe of		 * this inode, or it was never completely		 * orphaned. Write out the pages and exit now. */		ocfs2_cleanup_delete_inode(inode, 1);		goto bail_unlock_inode;	}	ocfs2_cleanup_delete_inode(inode, 0);	status = ocfs2_wipe_inode(inode, di_bh);	if (status < 0) {		if (status != -EDEADLK)			mlog_errno(status);		goto bail_unlock_inode;	}	/*	 * Mark the inode as successfully deleted.	 *	 * This is important for ocfs2_clear_inode() as it will check	 * this flag and skip any checkpointing work	 *	 * ocfs2_stuff_meta_lvb() also uses this flag to invalidate	 * the LVB for other nodes.	 */	OCFS2_I(inode)->ip_flags |= OCFS2_INODE_DELETED;bail_unlock_inode:	ocfs2_inode_unlock(inode, 1);	brelse(di_bh);bail_unblock:	status = sigprocmask(SIG_SETMASK, &oldset, NULL);	if (status < 0)		mlog_errno(status);bail:	clear_inode(inode);	mlog_exit_void();}void ocfs2_clear_inode(struct inode *inode){	int status;	struct ocfs2_inode_info *oi = OCFS2_I(inode);	mlog_entry_void();	if (!inode)		goto bail;	mlog(0, "Clearing inode: %llu, nlink = %u\n",	     (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_nlink);	mlog_bug_on_msg(OCFS2_SB(inode->i_sb) == NULL,			"Inode=%lu\n", inode->i_ino);	/* To preven remote deletes we hold open lock before, now it	 * is time to unlock PR and EX open locks. */	ocfs2_open_unlock(inode);	/* Do these before all the other work so that we don't bounce	 * the downconvert thread while waiting to destroy the locks. */	ocfs2_mark_lockres_freeing(&oi->ip_rw_lockres);	ocfs2_mark_lockres_freeing(&oi->ip_inode_lockres);	ocfs2_mark_lockres_freeing(&oi->ip_open_lockres);	/* We very well may get a clear_inode before all an inodes	 * metadata has hit disk. Of course, we can't drop any cluster	 * locks until the journal has finished with it. The only	 * exception here are successfully wiped inodes - their	 * metadata can now be considered to be part of the system	 * inodes from which it came. */	if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED))		ocfs2_checkpoint_inode(inode);	mlog_bug_on_msg(!list_empty(&oi->ip_io_markers),			"Clear inode of %llu, inode has io markers\n",			(unsigned long long)oi->ip_blkno);	ocfs2_extent_map_trunc(inode, 0);	status = ocfs2_drop_inode_locks(inode);	if (status < 0)		mlog_errno(status);	ocfs2_lock_res_free(&oi->ip_rw_lockres);	ocfs2_lock_res_free(&oi->ip_inode_lockres);	ocfs2_lock_res_free(&oi->ip_open_lockres);	ocfs2_metadata_cache_purge(inode);	mlog_bug_on_msg(oi->ip_metadata_cache.ci_num_cached,			"Clear inode of %llu, inode has %u cache items\n",			(unsigned long long)oi->ip_blkno, oi->ip_metadata_cache.ci_num_cached);	mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE),			"Clear inode of %llu, inode has a bad flag\n",			(unsigned long long)oi->ip_blkno);	mlog_bug_on_msg(spin_is_locked(&oi->ip_lock),			"Clear inode of %llu, inode is locked\n",			(unsigned long long)oi->ip_blkno);	mlog_bug_on_msg(!mutex_trylock(&oi->ip_io_mutex),			"Clear inode of %llu, io_mutex is locked\n",			(unsigned long long)oi->ip_blkno);	mutex_unlock(&oi->ip_io_mutex);	/*	 * down_trylock() returns 0, down_write_trylock() returns 1	 * kernel 1, world 0	 */	mlog_bug_on_msg(!down_write_trylock(&oi->ip_alloc_sem),			"Clear inode of %llu, alloc_sem is locked\n",			(unsigned long long)oi->ip_blkno);	up_write(&oi->ip_alloc_sem);	mlog_bug_on_msg(oi->ip_open_count,			"Clear inode of %llu has open count %d\n",			(unsigned long long)oi->ip_blkno, oi->ip_open_count);	/* Clear all other flags. */	oi->ip_flags = OCFS2_INODE_CACHE_INLINE;	oi->ip_created_trans = 0;	oi->ip_last_trans = 0;	oi->ip_dir_start_lookup = 0;	oi->ip_blkno = 0ULL;bail:	mlog_exit_void();}/* Called under inode_lock, with no more references on the * struct inode, so it's safe here to check the flags field * and to manipulate i_nlink without any other locks. */void ocfs2_drop_inode(struct inode *inode){	struct ocfs2_inode_info *oi = OCFS2_I(inode);	mlog_entry_void();	mlog(0, "Drop inode %llu, nlink = %u, ip_flags = 0x%x\n",	     (unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags);	if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)		generic_delete_inode(inode);	else		generic_drop_inode(inode);	mlog_exit_void();}/* * TODO: this should probably be merged into ocfs2_get_block * * However, you now need to pay attention to the cont_prepare_write() * stuff in ocfs2_get_block (that is, ocfs2_get_block pretty much * expects never to extend). */struct buffer_head *ocfs2_bread(struct inode *inode,				int block, int *err, int reada){	struct buffer_head *bh = NULL;	int tmperr;	u64 p_blkno;	int readflags = OCFS2_BH_CACHED;	if (reada)		readflags |= OCFS2_BH_READAHEAD;	if (((u64)block << inode->i_sb->s_blocksize_bits) >=	    i_size_read(inode)) {		BUG_ON(!reada);		return NULL;	}	down_read(&OCFS2_I(inode)->ip_alloc_sem);	tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,					     NULL);	up_read(&OCFS2_I(inode)->ip_alloc_sem);	if (tmperr < 0) {		mlog_errno(tmperr);		goto fail;	}	tmperr = ocfs2_read_block(OCFS2_SB(inode->i_sb), p_blkno, &bh,				  readflags, inode);	if (tmperr < 0)		goto fail;	tmperr = 0;	*err = 0;	return bh;fail:	if (bh) {		brelse(bh);		bh = NULL;	}	*err = -EIO;	return NULL;}/* * This is called from our getattr. */int ocfs2_inode_revalidate(struct dentry *dentry){	struct inode *inode = dentry->d_inode;	int status = 0;	mlog_entry("(inode = 0x%p, ino = %llu)\n", inode,		   inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL);	if (!inode) {		mlog(0, "eep, no inode!\n");		status = -ENOENT;		goto bail;	}	spin_lock(&OCFS2_I(inode)->ip_lock);	if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {		spin_unlock(&OCFS2_I(inode)->ip_lock);		mlog(0, "inode deleted!\n");		status = -ENOENT;		goto bail;	}	spin_unlock(&OCFS2_I(inode)->ip_lock);	/* Let ocfs2_inode_lock do the work of updating our struct	 * inode for us. */	status = ocfs2_inode_lock(inode, NULL, 0);	if (status < 0) {		if (status != -ENOENT)			mlog_errno(status);		goto bail;	}	ocfs2_inode_unlock(inode, 0);bail:	mlog_exit(status);	return status;}/* * Updates a disk inode from a * struct inode. * Only takes ip_lock. */int ocfs2_mark_inode_dirty(handle_t *handle,			   struct inode *inode,			   struct buffer_head *bh){	int status;	struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;	mlog_entry("(inode %llu)\n",		   (unsigned long long)OCFS2_I(inode)->ip_blkno);	status = ocfs2_journal_access(handle, inode, bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto leave;	}	spin_lock(&OCFS2_I(inode)->ip_lock);	fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);	ocfs2_get_inode_flags(OCFS2_I(inode));	fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr);	fe->i_dyn_features = cpu_to_le16(OCFS2_I(inode)->ip_dyn_features);	spin_unlock(&OCFS2_I(inode)->ip_lock);	fe->i_size = cpu_to_le64(i_size_read(inode));	fe->i_links_count = cpu_to_le16(inode->i_nlink);	fe->i_uid = cpu_to_le32(inode->i_uid);	fe->i_gid = cpu_to_le32(inode->i_gid);	fe->i_mode = cpu_to_le16(inode->i_mode);	fe->i_atime = cpu_to_le64(inode->i_atime.tv_sec);	fe->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);	fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);	fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);	fe->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);	fe->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);	status = ocfs2_journal_dirty(handle, bh);	if (status < 0)		mlog_errno(status);	status = 0;leave:	mlog_exit(status);	return status;}/* * * Updates a struct inode from a disk inode. * does no i/o, only takes ip_lock. */void ocfs2_refresh_inode(struct inode *inode,			 struct ocfs2_dinode *fe){	spin_lock(&OCFS2_I(inode)->ip_lock);	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);	OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr);	OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);	ocfs2_set_inode_flags(inode);	i_size_write(inode, le64_to_cpu(fe->i_size));	inode->i_nlink = le16_to_cpu(fe->i_links_count);	inode->i_uid = le32_to_cpu(fe->i_uid);	inode->i_gid = le32_to_cpu(fe->i_gid);	inode->i_mode = le16_to_cpu(fe->i_mode);	if (S_ISLNK(inode->i_mode) && le32_to_cpu(fe->i_clusters) == 0)		inode->i_blocks = 0;	else		inode->i_blocks = ocfs2_inode_sector_count(inode);	inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);	inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);	inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);	inode->i_mtime.tv_nsec = le32_to_cpu(fe->i_mtime_nsec);	inode->i_ctime.tv_sec = le64_to_cpu(fe->i_ctime);	inode->i_ctime.tv_nsec = le32_to_cpu(fe->i_ctime_nsec);	spin_unlock(&OCFS2_I(inode)->ip_lock);}

⌨️ 快捷键说明

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