[Ocfs2-devel] [PATCH 2/7 v4] ocfs2: add two functions of add and remove inode in orphan dir

Joseph Qi joseph.qi at huawei.com
Wed Oct 22 05:04:46 PDT 2014


Since dinode has only one copy on disk, add inode to orphan dir
temporarily will conflict with unlink, which both will modify the
dinode, such as i_orphaned_slot, i_flags, etc.

On 2014/10/11 20:26, WeiWei Wang wrote:
> Add two functions to add inode to orphan dir and remove inode from
> orphan dir.
> Here the original functions ocfs2_orphan_add and ocfs2_orphan_del are
> called respectively.
> 
> Signed-off-by: Weiwei Wang <wangww631 at huawei.com>
> Reviewed-by: Joseph Qi <joseph.qi at huawei.com>
> ---
>  fs/ocfs2/journal.h |   5 ++
>  fs/ocfs2/namei.c   | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/ocfs2/namei.h   |   5 ++
>  3 files changed, 157 insertions(+)
> 
> diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
> index 7f8cde9..f4cd3c3 100644
> --- a/fs/ocfs2/journal.h
> +++ b/fs/ocfs2/journal.h
> @@ -472,6 +472,11 @@ static inline int ocfs2_unlink_credits(struct super_block *sb)
>   * orphan dir index leaf */
>  #define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 4)
> 
> +/* dinode + orphan dir dinode + extent tree leaf block + orphan dir entry +
> + * orphan dir index root + orphan dir index leaf */
> +#define OCFS2_INODE_ADD_TO_ORPHAN_CREDITS  (2 * OCFS2_INODE_UPDATE_CREDITS + 4)
> +#define OCFS2_INODE_DEL_FROM_ORPHAN_CREDITS  OCFS2_INODE_ADD_TO_ORPHAN_CREDITS
> +
>  /* dinode update, old dir dinode update, new dir dinode update, old
>   * dir dir entry, new dir dir entry, dir entry update for renaming
>   * directory + target unlink + 3 x dir index leaves */
> diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
> index 2666dce..597692f 100644
> --- a/fs/ocfs2/namei.c
> +++ b/fs/ocfs2/namei.c
> @@ -2486,6 +2486,153 @@ leave:
>  	return status;
>  }
> 
> +/* An orphan dir name is an 8 byte value, printed as a hex string */
> +#define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64)))
> +int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb,
> +		struct inode *inode)
> +{
> +	char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
> +	struct inode *orphan_dir_inode = NULL;
> +	struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
> +	struct buffer_head *di_bh = NULL;
> +	int status = 0;
> +	handle_t *handle = NULL;
> +
> +	status = ocfs2_inode_lock(inode, &di_bh, 1);
> +	if (status < 0) {
> +		mlog_errno(status);
> +		goto bail;
> +	}
> +
> +	status = ocfs2_prepare_orphan_dir(osb, &orphan_dir_inode,
> +			OCFS2_I(inode)->ip_blkno,
> +			orphan_name,
> +			&orphan_insert);
> +	if (status < 0) {
> +		mlog_errno(status);
> +		goto bail_unlock_inode;
> +	}
> +
> +	handle = ocfs2_start_trans(osb, OCFS2_INODE_ADD_TO_ORPHAN_CREDITS);
> +	if (IS_ERR(handle)) {
> +		status = PTR_ERR(handle);
> +		goto bail_unlock_orphan;
> +	}
> +
> +	status = ocfs2_orphan_add(osb, handle, inode, di_bh, orphan_name,
> +			&orphan_insert, orphan_dir_inode);
> +	if (status)
> +		mlog_errno(status);
> +
> +	ocfs2_commit_trans(osb, handle);
> +
> +bail_unlock_orphan:
> +	ocfs2_inode_unlock(orphan_dir_inode, 1);
> +	mutex_unlock(&orphan_dir_inode->i_mutex);
> +	iput(orphan_dir_inode);
> +
> +	ocfs2_free_dir_lookup_result(&orphan_insert);
> +
> +bail_unlock_inode:
> +	ocfs2_inode_unlock(inode, 1);
> +	brelse(di_bh);
> +
> +bail:
> +	return status;
> +}
> +
> +int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb,
> +		struct inode *inode, int update_isize,
> +		loff_t end)
> +{
> +	struct inode *orphan_dir_inode = NULL;
> +	struct buffer_head *orphan_dir_bh = NULL;
> +	struct buffer_head *di_bh = NULL;
> +	struct ocfs2_dinode *di = NULL;
> +	handle_t *handle = NULL;
> +	int status = 0;
> +
> +	status = ocfs2_inode_lock(inode, &di_bh, 1);
> +	if (status < 0) {
> +		mlog_errno(status);
> +		goto bail;
> +	}
> +	di = (struct ocfs2_dinode *) di_bh->b_data;
> +
> +	orphan_dir_inode = ocfs2_get_system_file_inode(osb,
> +			ORPHAN_DIR_SYSTEM_INODE,
> +			osb->slot_num);
> +	if (!orphan_dir_inode) {
> +		status = -EEXIST;
> +		mlog_errno(status);
> +		goto bail_unlock_inode;
> +	}
> +
> +	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);
> +		iput(orphan_dir_inode);
> +		mlog_errno(status);
> +		goto bail_unlock_inode;
> +	}
> +
> +	handle = ocfs2_start_trans(osb, OCFS2_INODE_DEL_FROM_ORPHAN_CREDITS);
> +	if (IS_ERR(handle)) {
> +		status = PTR_ERR(handle);
> +		goto bail_unlock_orphan;
> +	}
> +
> +	status = ocfs2_orphan_del(osb, handle, orphan_dir_inode,
> +			inode, orphan_dir_bh);
> +	if (status < 0) {
> +		mlog_errno(status);
> +		goto bail_commit;
> +	}
> +
> +	/*
> +	 * We're going to journal the change of i_flags and i_orphaned_slot.
> +	 * It's safe anyway, though some callers may duplicate the journaling.
> +	 * Journaling within the func just make the logic look more
> +	 * straightforward.
> +	 */
> +	status = ocfs2_journal_access_di(handle,
> +			INODE_CACHE(inode),
> +			di_bh,
> +			OCFS2_JOURNAL_ACCESS_WRITE);
> +	if (status < 0) {
> +		mlog_errno(status);
> +		goto bail_commit;
> +	}
> +
> +	di->i_flags &= ~cpu_to_le32(OCFS2_ORPHANED_FL);
> +	OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR;
> +	di->i_orphaned_slot = 0;
> +
> +	if (update_isize) {
> +		status = ocfs2_set_inode_size(handle, inode, di_bh, end);
> +		if (status)
> +			mlog_errno(status);
> +	} else
> +		ocfs2_journal_dirty(handle, di_bh);
> +
> +bail_commit:
> +	ocfs2_commit_trans(osb, handle);
> +
> +bail_unlock_orphan:
> +	ocfs2_inode_unlock(orphan_dir_inode, 1);
> +	mutex_unlock(&orphan_dir_inode->i_mutex);
> +	brelse(orphan_dir_bh);
> +	iput(orphan_dir_inode);
> +
> +bail_unlock_inode:
> +	ocfs2_inode_unlock(inode, 1);
> +	brelse(di_bh);
> +
> +bail:
> +	return status;
> +}
> +
>  int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
>  				   struct inode *inode,
>  				   struct dentry *dentry)
> diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h
> index 052a323..5dcbd4b 100644
> --- a/fs/ocfs2/namei.h
> +++ b/fs/ocfs2/namei.h
> @@ -51,6 +51,11 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
>  int ocfs2_create_inode_in_orphan(struct inode *dir,
>  				 int mode,
>  				 struct inode **new_inode);
> +int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb,
> +		struct inode *inode);
> +int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb,
> +		struct inode *inode, int update_isize,
> +		loff_t end);
>  int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
>  				   struct inode *new_inode,
>  				   struct dentry *new_dentry);
> 





More information about the Ocfs2-devel mailing list