Signed-off-by: Kalpak Shah <kalpak.shah@sun.com>
Signed-off-by: Andreas Dilger <adilger@sun.com>
===================================================================
@@ -578,8 +578,12 @@ static int find_group_other(struct super
*
* For other inodes, search forward from the parent directory's block
* group to find a free inode.
+ *
+ * If a goal inode is specified then try to allocate it else continue
+ * allocation as is.
*/
-struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
+struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
+ unsigned long goal)
{
struct super_block *sb;
struct buffer_head *bitmap_bh = NULL;
@@ -591,7 +595,7 @@ struct inode *ext4_new_inode(handle_t *h
struct ext4_super_block *es;
struct ext4_inode_info *ei;
struct ext4_sb_info *sbi;
- int ret2, err = 0;
+ int ret2 = 0, err = 0;
struct inode *ret;
ext4_group_t i;
int free = 0;
@@ -610,6 +614,43 @@ struct inode *ext4_new_inode(handle_t *h
sbi = EXT4_SB(sb);
es = sbi->s_es;
+ if (goal) {
+ group = (goal - 1) / EXT4_INODES_PER_GROUP(sb);
+ ino = (goal - 1) % EXT4_INODES_PER_GROUP(sb);
+
+ err = -EIO;
+ gdp = ext4_get_group_desc(sb, group, &bh2);
+ if (!gdp)
+ goto fail;
+
+ bitmap_bh = ext4_read_inode_bitmap(sb, group);
+ if (!bitmap_bh)
+ goto fail;
+
+ BUFFER_TRACE(bh, "get_write_access");
+ err = ext4_journal_get_write_access(handle, bitmap_bh);
+ if (err)
+ goto fail;
+
+ if (ext4_set_bit_atomic(sb_bgl_lock(sbi, group),
+ ino, bitmap_bh->b_data)) {
+ goto continue_allocation;
+ }
+
+ BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
+ err = ext4_journal_dirty_metadata(handle, bitmap_bh);
+ if (err)
+ goto fail;
+
+ /*
+ * We've shortcircuited the allocation system successfully,
+ * now finish filling in the inode.
+ */
+ goto got;
+ }
+
+continue_allocation:
+
if (sbi->s_log_groups_per_flex) {
ret2 = find_group_flex(sb, dir, &group);
goto got_group;
===================================================================
@@ -1725,7 +1725,7 @@ retry:
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
- inode = ext4_new_inode (handle, dir, mode);
+ inode = ext4_new_inode (handle, dir, mode, 0);
err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
inode->i_op = &ext4_file_inode_operations;
@@ -1759,7 +1759,7 @@ retry:
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
- inode = ext4_new_inode(handle, dir, mode);
+ inode = ext4_new_inode(handle, dir, mode, 0);
err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
init_special_inode(inode, inode->i_mode, rdev);
@@ -1795,7 +1795,7 @@ retry:
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
- inode = ext4_new_inode(handle, dir, S_IFDIR | mode);
+ inode = ext4_new_inode(handle, dir, S_IFDIR | mode, 0);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out_stop;
@@ -2195,7 +2195,7 @@ retry:
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
- inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO);
+ inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO, 0);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out_stop;
===================================================================
@@ -482,9 +482,8 @@ int ext4_ext_migrate(struct inode *inode
retval = PTR_ERR(handle);
goto err_out;
}
- tmp_inode = ext4_new_inode(handle,
- inode->i_sb->s_root->d_inode,
- S_IFREG);
+ tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode,
+ S_IFREG, 0);
if (IS_ERR(tmp_inode)) {
retval = -ENOMEM;
ext4_journal_stop(handle);
===================================================================
@@ -1033,7 +1033,8 @@ extern int ext4fs_dirhash(const char *na
dx_hash_info *hinfo);
/* ialloc.c */
-extern struct inode * ext4_new_inode(handle_t *, struct inode *, int);
+extern struct inode * ext4_new_inode(handle_t *, struct inode *, int,
+ unsigned long);
extern void ext4_free_inode(handle_t *, struct inode *);
extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
extern unsigned long ext4_count_free_inodes(struct super_block *);