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

Commit f5d36202 authored by Tiger Yang's avatar Tiger Yang Committed by Mark Fasheh
Browse files

ocfs2: move new inode allocation out of the transaction



Move out inode allocation from ocfs2_mknod_locked() because
vfs_dq_init() must be called outside of a transaction.

Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarTiger Yang <tiger.yang@oracle.com>
Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
parent fecc0112
Loading
Loading
Loading
Loading
+64 −44
Original line number Diff line number Diff line
@@ -66,12 +66,12 @@

static int ocfs2_mknod_locked(struct ocfs2_super *osb,
			      struct inode *dir,
			      struct dentry *dentry, int mode,
			      struct inode *inode,
			      struct dentry *dentry,
			      dev_t dev,
			      struct buffer_head **new_fe_bh,
			      struct buffer_head *parent_fe_bh,
			      handle_t *handle,
			      struct inode **ret_inode,
			      struct ocfs2_alloc_context *inode_ac);

static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
@@ -186,6 +186,34 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
	return ret;
}

static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode)
{
	struct inode *inode;

	inode = new_inode(dir->i_sb);
	if (!inode) {
		mlog(ML_ERROR, "new_inode failed!\n");
		return NULL;
	}

	/* populate as many fields early on as possible - many of
	 * these are used by the support functions here and in
	 * callers. */
	if (S_ISDIR(mode))
		inode->i_nlink = 2;
	else
		inode->i_nlink = 1;
	inode->i_uid = current_fsuid();
	if (dir->i_mode & S_ISGID) {
		inode->i_gid = dir->i_gid;
		if (S_ISDIR(mode))
			mode |= S_ISGID;
	} else
		inode->i_gid = current_fsgid();
	inode->i_mode = mode;
	return inode;
}

static int ocfs2_mknod(struct inode *dir,
		       struct dentry *dentry,
		       int mode,
@@ -250,6 +278,13 @@ static int ocfs2_mknod(struct inode *dir,
		goto leave;
	}

	inode = ocfs2_get_init_inode(dir, mode);
	if (!inode) {
		status = -ENOMEM;
		mlog_errno(status);
		goto leave;
	}

	/* Reserve a cluster if creating an extent based directory. */
	if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) {
		status = ocfs2_reserve_clusters(osb, 1, &data_ac);
@@ -269,9 +304,9 @@ static int ocfs2_mknod(struct inode *dir,
	}

	/* do the real work now. */
	status = ocfs2_mknod_locked(osb, dir, dentry, mode, dev,
	status = ocfs2_mknod_locked(osb, dir, inode, dentry, dev,
				    &new_fe_bh, parent_fe_bh, handle,
				    &inode, inode_ac);
				    inode_ac);
	if (status < 0) {
		mlog_errno(status);
		goto leave;
@@ -332,8 +367,10 @@ static int ocfs2_mknod(struct inode *dir,
	brelse(de_bh);
	brelse(parent_fe_bh);

	if ((status < 0) && inode)
	if ((status < 0) && inode) {
		clear_nlink(inode);
		iput(inode);
	}

	if (inode_ac)
		ocfs2_free_alloc_context(inode_ac);
@@ -348,12 +385,12 @@ static int ocfs2_mknod(struct inode *dir,

static int ocfs2_mknod_locked(struct ocfs2_super *osb,
			      struct inode *dir,
			      struct dentry *dentry, int mode,
			      struct inode *inode,
			      struct dentry *dentry,
			      dev_t dev,
			      struct buffer_head **new_fe_bh,
			      struct buffer_head *parent_fe_bh,
			      handle_t *handle,
			      struct inode **ret_inode,
			      struct ocfs2_alloc_context *inode_ac)
{
	int status = 0;
@@ -361,14 +398,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
	struct ocfs2_extent_list *fel;
	u64 fe_blkno = 0;
	u16 suballoc_bit;
	struct inode *inode = NULL;

	mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
		   (unsigned long)dev, dentry->d_name.len,
	mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry,
		   inode->i_mode, (unsigned long)dev, dentry->d_name.len,
		   dentry->d_name.name);

	*new_fe_bh = NULL;
	*ret_inode = NULL;

	status = ocfs2_claim_new_inode(osb, handle, inode_ac, &suballoc_bit,
				       &fe_blkno);
@@ -377,23 +412,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
		goto leave;
	}

	inode = new_inode(dir->i_sb);
	if (!inode) {
		status = -ENOMEM;
		mlog(ML_ERROR, "new_inode failed!\n");
		goto leave;
	}

	/* populate as many fields early on as possible - many of
	 * these are used by the support functions here and in
	 * callers. */
	inode->i_ino = ino_from_blkno(osb->sb, fe_blkno);
	OCFS2_I(inode)->ip_blkno = fe_blkno;
	if (S_ISDIR(mode))
		inode->i_nlink = 2;
	else
		inode->i_nlink = 1;
	inode->i_mode = mode;
	spin_lock(&osb->osb_lock);
	inode->i_generation = osb->s_next_generation++;
	spin_unlock(&osb->osb_lock);
@@ -421,17 +444,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
	fe->i_blkno = cpu_to_le64(fe_blkno);
	fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
	fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
	fe->i_uid = cpu_to_le32(current_fsuid());
	if (dir->i_mode & S_ISGID) {
		fe->i_gid = cpu_to_le32(dir->i_gid);
		if (S_ISDIR(mode))
			mode |= S_ISGID;
	} else
		fe->i_gid = cpu_to_le32(current_fsgid());
	fe->i_mode = cpu_to_le16(mode);
	if (S_ISCHR(mode) || S_ISBLK(mode))
	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);
	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
		fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));

	fe->i_links_count = cpu_to_le16(inode->i_nlink);

	fe->i_last_eb_blk = 0;
@@ -446,7 +463,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
	/*
	 * If supported, directories start with inline data.
	 */
	if (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) {
	if (S_ISDIR(inode->i_mode) && ocfs2_supports_inline_data(osb)) {
		u16 feat = le16_to_cpu(fe->i_dyn_features);

		fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL);
@@ -484,17 +501,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
	status = 0; /* error in ocfs2_create_new_inode_locks is not
		     * critical */

	*ret_inode = inode;
leave:
	if (status < 0) {
		if (*new_fe_bh) {
			brelse(*new_fe_bh);
			*new_fe_bh = NULL;
		}
		if (inode) {
			clear_nlink(inode);
			iput(inode);
		}
	}

	mlog_exit(status);
@@ -1542,6 +1554,13 @@ static int ocfs2_symlink(struct inode *dir,
		goto bail;
	}

	inode = ocfs2_get_init_inode(dir, S_IFLNK | S_IRWXUGO);
	if (!inode) {
		status = -ENOMEM;
		mlog_errno(status);
		goto bail;
	}

	/* don't reserve bitmap space for fast symlinks. */
	if (l > ocfs2_fast_symlink_chars(sb)) {
		status = ocfs2_reserve_clusters(osb, 1, &data_ac);
@@ -1560,10 +1579,9 @@ static int ocfs2_symlink(struct inode *dir,
		goto bail;
	}

	status = ocfs2_mknod_locked(osb, dir, dentry,
				    S_IFLNK | S_IRWXUGO, 0,
				    &new_fe_bh, parent_fe_bh, handle,
				    &inode, inode_ac);
	status = ocfs2_mknod_locked(osb, dir, inode, dentry,
				    0, &new_fe_bh, parent_fe_bh, handle,
				    inode_ac);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
@@ -1644,8 +1662,10 @@ static int ocfs2_symlink(struct inode *dir,
		ocfs2_free_alloc_context(inode_ac);
	if (data_ac)
		ocfs2_free_alloc_context(data_ac);
	if ((status < 0) && inode)
	if ((status < 0) && inode) {
		clear_nlink(inode);
		iput(inode);
	}

	mlog_exit(status);