Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd43bcde authored by Mark Fasheh's avatar Mark Fasheh Committed by Tao Ma
Browse files

ocfs2: split out ocfs2_prepare_orphan_dir() into locking and prep functions



We do this because ocfs2_create_inode_in_orphan() wants to order locking of
the orphan dir with respect to locking of the inode allocator *before*
making any changes to the directory.

Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
Signed-off-by: default avatarTao Ma <tao.ma@oracle.com>
parent e49e2767
Loading
Loading
Loading
Loading
+88 −32
Original line number Diff line number Diff line
@@ -1871,61 +1871,117 @@ bail:
	return status;
}

static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
static int ocfs2_lookup_lock_orphan_dir(struct ocfs2_super *osb,
					struct inode **ret_orphan_dir,
				    u64 blkno,
				    char *name,
				    struct ocfs2_dir_lookup_result *lookup)
					struct buffer_head **ret_orphan_dir_bh)
{
	struct inode *orphan_dir_inode;
	struct buffer_head *orphan_dir_bh = NULL;
	int status = 0;

	status = ocfs2_blkno_stringify(blkno, name);
	if (status < 0) {
		mlog_errno(status);
		return status;
	}
	int ret = 0;

	orphan_dir_inode = ocfs2_get_system_file_inode(osb,
						       ORPHAN_DIR_SYSTEM_INODE,
						       osb->slot_num);
	if (!orphan_dir_inode) {
		status = -ENOENT;
		mlog_errno(status);
		return status;
		ret = -ENOENT;
		mlog_errno(ret);
		return ret;
	}

	mutex_lock(&orphan_dir_inode->i_mutex);

	status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
	if (status < 0) {
		mlog_errno(status);
		goto leave;
	ret = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
	if (ret < 0) {
		mutex_unlock(&orphan_dir_inode->i_mutex);
		iput(orphan_dir_inode);

		mlog_errno(ret);
		return ret;
	}

	*ret_orphan_dir = orphan_dir_inode;
	*ret_orphan_dir_bh = orphan_dir_bh;

	return 0;
}

static int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode,
				      struct buffer_head *orphan_dir_bh,
				      u64 blkno,
				      char *name,
				      struct ocfs2_dir_lookup_result *lookup)
{
	int ret;
	struct ocfs2_super *osb = OCFS2_SB(orphan_dir_inode->i_sb);

	ret = ocfs2_blkno_stringify(blkno, name);
	if (ret < 0) {
		mlog_errno(ret);
		return ret;
	}

	status = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode,
	ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode,
					   orphan_dir_bh, name,
					   OCFS2_ORPHAN_NAMELEN, lookup);
	if (status < 0) {
		ocfs2_inode_unlock(orphan_dir_inode, 1);
	if (ret < 0) {
		mlog_errno(ret);
		return ret;
	}

		mlog_errno(status);
		goto leave;
	return 0;
}

/**
 * ocfs2_prepare_orphan_dir() - Prepare an orphan directory for
 * insertion of an orphan.
 * @osb: ocfs2 file system
 * @ret_orphan_dir: Orphan dir inode - returned locked!
 * @blkno: Actual block number of the inode to be inserted into orphan dir.
 * @lookup: dir lookup result, to be passed back into functions like
 *          ocfs2_orphan_add
 *
 * Returns zero on success and the ret_orphan_dir, name and lookup
 * fields will be populated.
 *
 * Returns non-zero on failure. 
 */
static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
				    struct inode **ret_orphan_dir,
				    u64 blkno,
				    char *name,
				    struct ocfs2_dir_lookup_result *lookup)
{
	struct inode *orphan_dir_inode = NULL;
	struct buffer_head *orphan_dir_bh = NULL;
	int ret = 0;

	ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir_inode,
					   &orphan_dir_bh);
	if (ret < 0) {
		mlog_errno(ret);
		return ret;
	}

	ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh,
					 blkno, name, lookup);
	if (ret < 0) {
		mlog_errno(ret);
		goto out;
	}

	*ret_orphan_dir = orphan_dir_inode;

leave:
	if (status) {
out:
	brelse(orphan_dir_bh);

	if (ret) {
		ocfs2_inode_unlock(orphan_dir_inode, 1);
		mutex_unlock(&orphan_dir_inode->i_mutex);
		iput(orphan_dir_inode);
	}

	brelse(orphan_dir_bh);

	mlog_exit(status);
	return status;
	mlog_exit(ret);
	return ret;
}

static int ocfs2_orphan_add(struct ocfs2_super *osb,