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: Mark Fasheh <mfasheh@suse.com> Signed-off-by: Tao Ma <tao.ma@oracle.com>
This commit is contained in:
parent
e49e27674d
commit
dd43bcde23
130
fs/ocfs2/namei.c
130
fs/ocfs2/namei.c
|
@ -1871,61 +1871,117 @@ bail:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ocfs2_lookup_lock_orphan_dir(struct ocfs2_super *osb,
|
||||||
|
struct inode **ret_orphan_dir,
|
||||||
|
struct buffer_head **ret_orphan_dir_bh)
|
||||||
|
{
|
||||||
|
struct inode *orphan_dir_inode;
|
||||||
|
struct buffer_head *orphan_dir_bh = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
orphan_dir_inode = ocfs2_get_system_file_inode(osb,
|
||||||
|
ORPHAN_DIR_SYSTEM_INODE,
|
||||||
|
osb->slot_num);
|
||||||
|
if (!orphan_dir_inode) {
|
||||||
|
ret = -ENOENT;
|
||||||
|
mlog_errno(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&orphan_dir_inode->i_mutex);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode,
|
||||||
|
orphan_dir_bh, name,
|
||||||
|
OCFS2_ORPHAN_NAMELEN, lookup);
|
||||||
|
if (ret < 0) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
|
||||||
struct inode **ret_orphan_dir,
|
struct inode **ret_orphan_dir,
|
||||||
u64 blkno,
|
u64 blkno,
|
||||||
char *name,
|
char *name,
|
||||||
struct ocfs2_dir_lookup_result *lookup)
|
struct ocfs2_dir_lookup_result *lookup)
|
||||||
{
|
{
|
||||||
struct inode *orphan_dir_inode;
|
struct inode *orphan_dir_inode = NULL;
|
||||||
struct buffer_head *orphan_dir_bh = NULL;
|
struct buffer_head *orphan_dir_bh = NULL;
|
||||||
int status = 0;
|
int ret = 0;
|
||||||
|
|
||||||
status = ocfs2_blkno_stringify(blkno, name);
|
ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir_inode,
|
||||||
if (status < 0) {
|
&orphan_dir_bh);
|
||||||
mlog_errno(status);
|
if (ret < 0) {
|
||||||
return status;
|
mlog_errno(ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
orphan_dir_inode = ocfs2_get_system_file_inode(osb,
|
ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh,
|
||||||
ORPHAN_DIR_SYSTEM_INODE,
|
blkno, name, lookup);
|
||||||
osb->slot_num);
|
if (ret < 0) {
|
||||||
if (!orphan_dir_inode) {
|
mlog_errno(ret);
|
||||||
status = -ENOENT;
|
goto out;
|
||||||
mlog_errno(status);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = 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);
|
|
||||||
|
|
||||||
mlog_errno(status);
|
|
||||||
goto leave;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret_orphan_dir = orphan_dir_inode;
|
*ret_orphan_dir = orphan_dir_inode;
|
||||||
|
|
||||||
leave:
|
out:
|
||||||
if (status) {
|
brelse(orphan_dir_bh);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
ocfs2_inode_unlock(orphan_dir_inode, 1);
|
||||||
mutex_unlock(&orphan_dir_inode->i_mutex);
|
mutex_unlock(&orphan_dir_inode->i_mutex);
|
||||||
iput(orphan_dir_inode);
|
iput(orphan_dir_inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
brelse(orphan_dir_bh);
|
mlog_exit(ret);
|
||||||
|
return ret;
|
||||||
mlog_exit(status);
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
||||||
|
|
Loading…
Reference in New Issue