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: Jan Kara <jack@suse.cz> Signed-off-by: Tiger Yang <tiger.yang@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
This commit is contained in:
parent
fecc01126d
commit
f5d362022a
108
fs/ocfs2/namei.c
108
fs/ocfs2/namei.c
@ -66,12 +66,12 @@
|
|||||||
|
|
||||||
static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
||||||
struct inode *dir,
|
struct inode *dir,
|
||||||
struct dentry *dentry, int mode,
|
struct inode *inode,
|
||||||
|
struct dentry *dentry,
|
||||||
dev_t dev,
|
dev_t dev,
|
||||||
struct buffer_head **new_fe_bh,
|
struct buffer_head **new_fe_bh,
|
||||||
struct buffer_head *parent_fe_bh,
|
struct buffer_head *parent_fe_bh,
|
||||||
handle_t *handle,
|
handle_t *handle,
|
||||||
struct inode **ret_inode,
|
|
||||||
struct ocfs2_alloc_context *inode_ac);
|
struct ocfs2_alloc_context *inode_ac);
|
||||||
|
|
||||||
static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
|
static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
|
||||||
@ -186,6 +186,34 @@ bail:
|
|||||||
return ret;
|
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,
|
static int ocfs2_mknod(struct inode *dir,
|
||||||
struct dentry *dentry,
|
struct dentry *dentry,
|
||||||
int mode,
|
int mode,
|
||||||
@ -250,6 +278,13 @@ static int ocfs2_mknod(struct inode *dir,
|
|||||||
goto leave;
|
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. */
|
/* Reserve a cluster if creating an extent based directory. */
|
||||||
if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) {
|
if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) {
|
||||||
status = ocfs2_reserve_clusters(osb, 1, &data_ac);
|
status = ocfs2_reserve_clusters(osb, 1, &data_ac);
|
||||||
@ -269,9 +304,9 @@ static int ocfs2_mknod(struct inode *dir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* do the real work now. */
|
/* 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,
|
&new_fe_bh, parent_fe_bh, handle,
|
||||||
&inode, inode_ac);
|
inode_ac);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -332,8 +367,10 @@ leave:
|
|||||||
brelse(de_bh);
|
brelse(de_bh);
|
||||||
brelse(parent_fe_bh);
|
brelse(parent_fe_bh);
|
||||||
|
|
||||||
if ((status < 0) && inode)
|
if ((status < 0) && inode) {
|
||||||
|
clear_nlink(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
|
}
|
||||||
|
|
||||||
if (inode_ac)
|
if (inode_ac)
|
||||||
ocfs2_free_alloc_context(inode_ac);
|
ocfs2_free_alloc_context(inode_ac);
|
||||||
@ -348,12 +385,12 @@ leave:
|
|||||||
|
|
||||||
static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
||||||
struct inode *dir,
|
struct inode *dir,
|
||||||
struct dentry *dentry, int mode,
|
struct inode *inode,
|
||||||
|
struct dentry *dentry,
|
||||||
dev_t dev,
|
dev_t dev,
|
||||||
struct buffer_head **new_fe_bh,
|
struct buffer_head **new_fe_bh,
|
||||||
struct buffer_head *parent_fe_bh,
|
struct buffer_head *parent_fe_bh,
|
||||||
handle_t *handle,
|
handle_t *handle,
|
||||||
struct inode **ret_inode,
|
|
||||||
struct ocfs2_alloc_context *inode_ac)
|
struct ocfs2_alloc_context *inode_ac)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
@ -361,14 +398,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
|||||||
struct ocfs2_extent_list *fel;
|
struct ocfs2_extent_list *fel;
|
||||||
u64 fe_blkno = 0;
|
u64 fe_blkno = 0;
|
||||||
u16 suballoc_bit;
|
u16 suballoc_bit;
|
||||||
struct inode *inode = NULL;
|
|
||||||
|
|
||||||
mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
|
mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry,
|
||||||
(unsigned long)dev, dentry->d_name.len,
|
inode->i_mode, (unsigned long)dev, dentry->d_name.len,
|
||||||
dentry->d_name.name);
|
dentry->d_name.name);
|
||||||
|
|
||||||
*new_fe_bh = NULL;
|
*new_fe_bh = NULL;
|
||||||
*ret_inode = NULL;
|
|
||||||
|
|
||||||
status = ocfs2_claim_new_inode(osb, handle, inode_ac, &suballoc_bit,
|
status = ocfs2_claim_new_inode(osb, handle, inode_ac, &suballoc_bit,
|
||||||
&fe_blkno);
|
&fe_blkno);
|
||||||
@ -377,23 +412,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
|||||||
goto leave;
|
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
|
/* populate as many fields early on as possible - many of
|
||||||
* these are used by the support functions here and in
|
* these are used by the support functions here and in
|
||||||
* callers. */
|
* callers. */
|
||||||
inode->i_ino = ino_from_blkno(osb->sb, fe_blkno);
|
inode->i_ino = ino_from_blkno(osb->sb, fe_blkno);
|
||||||
OCFS2_I(inode)->ip_blkno = 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);
|
spin_lock(&osb->osb_lock);
|
||||||
inode->i_generation = osb->s_next_generation++;
|
inode->i_generation = osb->s_next_generation++;
|
||||||
spin_unlock(&osb->osb_lock);
|
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_blkno = cpu_to_le64(fe_blkno);
|
||||||
fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
|
fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
|
||||||
fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
|
fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
|
||||||
fe->i_uid = cpu_to_le32(current_fsuid());
|
fe->i_uid = cpu_to_le32(inode->i_uid);
|
||||||
if (dir->i_mode & S_ISGID) {
|
fe->i_gid = cpu_to_le32(inode->i_gid);
|
||||||
fe->i_gid = cpu_to_le32(dir->i_gid);
|
fe->i_mode = cpu_to_le16(inode->i_mode);
|
||||||
if (S_ISDIR(mode))
|
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_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->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
|
fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
|
||||||
|
|
||||||
fe->i_links_count = cpu_to_le16(inode->i_nlink);
|
fe->i_links_count = cpu_to_le16(inode->i_nlink);
|
||||||
|
|
||||||
fe->i_last_eb_blk = 0;
|
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 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);
|
u16 feat = le16_to_cpu(fe->i_dyn_features);
|
||||||
|
|
||||||
fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL);
|
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
|
status = 0; /* error in ocfs2_create_new_inode_locks is not
|
||||||
* critical */
|
* critical */
|
||||||
|
|
||||||
*ret_inode = inode;
|
|
||||||
leave:
|
leave:
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
if (*new_fe_bh) {
|
if (*new_fe_bh) {
|
||||||
brelse(*new_fe_bh);
|
brelse(*new_fe_bh);
|
||||||
*new_fe_bh = NULL;
|
*new_fe_bh = NULL;
|
||||||
}
|
}
|
||||||
if (inode) {
|
|
||||||
clear_nlink(inode);
|
|
||||||
iput(inode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
@ -1542,6 +1554,13 @@ static int ocfs2_symlink(struct inode *dir,
|
|||||||
goto bail;
|
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. */
|
/* don't reserve bitmap space for fast symlinks. */
|
||||||
if (l > ocfs2_fast_symlink_chars(sb)) {
|
if (l > ocfs2_fast_symlink_chars(sb)) {
|
||||||
status = ocfs2_reserve_clusters(osb, 1, &data_ac);
|
status = ocfs2_reserve_clusters(osb, 1, &data_ac);
|
||||||
@ -1560,10 +1579,9 @@ static int ocfs2_symlink(struct inode *dir,
|
|||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = ocfs2_mknod_locked(osb, dir, dentry,
|
status = ocfs2_mknod_locked(osb, dir, inode, dentry,
|
||||||
S_IFLNK | S_IRWXUGO, 0,
|
0, &new_fe_bh, parent_fe_bh, handle,
|
||||||
&new_fe_bh, parent_fe_bh, handle,
|
inode_ac);
|
||||||
&inode, inode_ac);
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto bail;
|
goto bail;
|
||||||
@ -1644,8 +1662,10 @@ bail:
|
|||||||
ocfs2_free_alloc_context(inode_ac);
|
ocfs2_free_alloc_context(inode_ac);
|
||||||
if (data_ac)
|
if (data_ac)
|
||||||
ocfs2_free_alloc_context(data_ac);
|
ocfs2_free_alloc_context(data_ac);
|
||||||
if ((status < 0) && inode)
|
if ((status < 0) && inode) {
|
||||||
|
clear_nlink(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
|
}
|
||||||
|
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user