Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 210393
b: refs/heads/master
c: 97b8f4a
h: refs/heads/master
i:
  210391: f8fdd62
v: v3
  • Loading branch information
Mark Fasheh authored and Tao Ma committed Sep 8, 2010
1 parent 36b960c commit d0d1c21
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 21 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dd43bcde23c527f64897eef41aa1fed2c9905ea9
refs/heads/master: 97b8f4a9dfd932997677136e11980eb2fafea91d
127 changes: 107 additions & 20 deletions trunk/fs/ocfs2/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,99 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
return status;
}

/**
* ocfs2_prep_new_orphaned_file() - Prepare the orphan dir to recieve a newly
* allocated file. This is different from the typical 'add to orphan dir'
* operation in that the inode does not yet exist. This is a problem because
* the orphan dir stringifies the inode block number to come up with it's
* dirent. Obviously if the inode does not yet exist we have a chicken and egg
* problem. This function works around it by calling deeper into the orphan
* and suballoc code than other callers. Use this only by necessity.
* @dir: The directory which this inode will ultimately wind up under - not the
* orphan dir!
* @dir_bh: buffer_head the @dir inode block
* @orphan_name: string of length (CFS2_ORPHAN_NAMELEN + 1). Will be filled
* with the string to be used for orphan dirent. Pass back to the orphan dir
* code.
* @ret_orphan_dir: orphan dir inode returned to be passed back into orphan
* dir code.
* @ret_di_blkno: block number where the new inode will be allocated.
* @orphan_insert: Dir insert context to be passed back into orphan dir code.
* @ret_inode_ac: Inode alloc context to be passed back to the allocator.
*
* Returns zero on success and the ret_orphan_dir, name and lookup
* fields will be populated.
*
* Returns non-zero on failure.
*/
static int ocfs2_prep_new_orphaned_file(struct inode *dir,
struct buffer_head *dir_bh,
char *orphan_name,
struct inode **ret_orphan_dir,
u64 *ret_di_blkno,
struct ocfs2_dir_lookup_result *orphan_insert,
struct ocfs2_alloc_context **ret_inode_ac)
{
int ret;
u64 di_blkno;
struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
struct inode *orphan_dir = NULL;
struct buffer_head *orphan_dir_bh = NULL;
struct ocfs2_alloc_context *inode_ac = NULL;

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

/* reserve an inode spot */
ret = ocfs2_reserve_new_inode(osb, &inode_ac);
if (ret < 0) {
if (ret != -ENOSPC)
mlog_errno(ret);
goto out;
}

ret = ocfs2_find_new_inode_loc(dir, dir_bh, inode_ac,
&di_blkno);
if (ret) {
mlog_errno(ret);
goto out;
}

ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh,
di_blkno, orphan_name, orphan_insert);
if (ret < 0) {
mlog_errno(ret);
goto out;
}

out:
if (ret == 0) {
*ret_orphan_dir = orphan_dir;
*ret_di_blkno = di_blkno;
*ret_inode_ac = inode_ac;
/*
* orphan_name and orphan_insert are already up to
* date via prepare_orphan_dir
*/
} else {
/* Unroll reserve_new_inode* */
if (inode_ac)
ocfs2_free_alloc_context(inode_ac);

/* Unroll orphan dir locking */
mutex_unlock(&orphan_dir->i_mutex);
ocfs2_inode_unlock(orphan_dir, 1);
iput(orphan_dir);
}

brelse(orphan_dir_bh);

return 0;
}

int ocfs2_create_inode_in_orphan(struct inode *dir,
int mode,
struct inode **new_inode)
Expand All @@ -2143,6 +2236,8 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
struct buffer_head *new_di_bh = NULL;
struct ocfs2_alloc_context *inode_ac = NULL;
struct ocfs2_dir_lookup_result orphan_insert = { NULL, };
u64 uninitialized_var(di_blkno), suballoc_loc;
u16 suballoc_bit;

status = ocfs2_inode_lock(dir, &parent_di_bh, 1);
if (status < 0) {
Expand All @@ -2151,20 +2246,9 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
return status;
}

/*
* We give the orphan dir the root blkno to fake an orphan name,
* and allocate enough space for our insertion.
*/
status = ocfs2_prepare_orphan_dir(osb, &orphan_dir,
osb->root_blkno,
orphan_name, &orphan_insert);
if (status < 0) {
mlog_errno(status);
goto leave;
}

/* reserve an inode spot */
status = ocfs2_reserve_new_inode(osb, &inode_ac);
status = ocfs2_prep_new_orphaned_file(dir, parent_di_bh,
orphan_name, &orphan_dir,
&di_blkno, &orphan_insert, &inode_ac);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
Expand All @@ -2191,17 +2275,20 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
goto leave;
did_quota_inode = 1;

inode->i_nlink = 0;
/* do the real work now. */
status = ocfs2_mknod_locked(osb, dir, inode,
0, &new_di_bh, parent_di_bh, handle,
inode_ac);
status = ocfs2_claim_new_inode_at_loc(handle, dir, inode_ac,
&suballoc_loc,
&suballoc_bit, di_blkno);
if (status < 0) {
mlog_errno(status);
goto leave;
}

status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, orphan_name);
inode->i_nlink = 0;
/* do the real work now. */
status = __ocfs2_mknod_locked(dir, inode,
0, &new_di_bh, parent_di_bh, handle,
inode_ac, di_blkno, suballoc_loc,
suballoc_bit);
if (status < 0) {
mlog_errno(status);
goto leave;
Expand Down

0 comments on commit d0d1c21

Please sign in to comment.