Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[sfrench/cifs-2.6.git] / fs / ext4 / namei.c
index aba86e8ef1efe959bae6fd9d6afaa5d2dc10b6f6..123798c5ac314c3ff7522c84de2907c6e7587800 100644 (file)
@@ -53,7 +53,7 @@ static struct buffer_head *ext4_append(handle_t *handle,
                                        ext4_lblk_t *block)
 {
        struct buffer_head *bh;
-       int err = 0;
+       int err;
 
        if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb &&
                     ((inode->i_size >> 10) >=
@@ -62,9 +62,9 @@ static struct buffer_head *ext4_append(handle_t *handle,
 
        *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
 
-       bh = ext4_bread(handle, inode, *block, 1, &err);
-       if (!bh)
-               return ERR_PTR(err);
+       bh = ext4_bread(handle, inode, *block, 1);
+       if (IS_ERR(bh))
+               return bh;
        inode->i_size += inode->i_sb->s_blocksize;
        EXT4_I(inode)->i_disksize = inode->i_size;
        BUFFER_TRACE(bh, "get_write_access");
@@ -94,20 +94,20 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
 {
        struct buffer_head *bh;
        struct ext4_dir_entry *dirent;
-       int err = 0, is_dx_block = 0;
+       int is_dx_block = 0;
 
-       bh = ext4_bread(NULL, inode, block, 0, &err);
-       if (!bh) {
-               if (err == 0) {
-                       ext4_error_inode(inode, __func__, line, block,
-                                              "Directory hole found");
-                       return ERR_PTR(-EIO);
-               }
+       bh = ext4_bread(NULL, inode, block, 0);
+       if (IS_ERR(bh)) {
                __ext4_warning(inode->i_sb, __func__, line,
-                              "error reading directory block "
-                              "(ino %lu, block %lu)", inode->i_ino,
+                              "error %ld reading directory block "
+                              "(ino %lu, block %lu)", PTR_ERR(bh), inode->i_ino,
                               (unsigned long) block);
-               return ERR_PTR(err);
+
+               return bh;
+       }
+       if (!bh) {
+               ext4_error_inode(inode, __func__, line, block, "Directory hole found");
+               return ERR_PTR(-EIO);
        }
        dirent = (struct ext4_dir_entry *) bh->b_data;
        /* Determine whether or not we have an index block */
@@ -124,8 +124,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
                       "directory leaf block found instead of index block");
                return ERR_PTR(-EIO);
        }
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) ||
+       if (!ext4_has_metadata_csum(inode->i_sb) ||
            buffer_verified(bh))
                return bh;
 
@@ -253,8 +252,7 @@ static unsigned dx_node_limit(struct inode *dir);
 static struct dx_frame *dx_probe(const struct qstr *d_name,
                                 struct inode *dir,
                                 struct dx_hash_info *hinfo,
-                                struct dx_frame *frame,
-                                int *err);
+                                struct dx_frame *frame);
 static void dx_release(struct dx_frame *frames);
 static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
                       struct dx_hash_info *hinfo, struct dx_map_entry map[]);
@@ -270,8 +268,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
                                 __u32 *start_hash);
 static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
                const struct qstr *d_name,
-               struct ext4_dir_entry_2 **res_dir,
-               int *err);
+               struct ext4_dir_entry_2 **res_dir);
 static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
                             struct inode *inode);
 
@@ -340,8 +337,7 @@ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
 {
        struct ext4_dir_entry_tail *t;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return 1;
 
        t = get_dirent_tail(inode, dirent);
@@ -362,8 +358,7 @@ static void ext4_dirent_csum_set(struct inode *inode,
 {
        struct ext4_dir_entry_tail *t;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return;
 
        t = get_dirent_tail(inode, dirent);
@@ -438,8 +433,7 @@ static int ext4_dx_csum_verify(struct inode *inode,
        struct dx_tail *t;
        int count_offset, limit, count;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return 1;
 
        c = get_dx_countlimit(inode, dirent, &count_offset);
@@ -468,8 +462,7 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent)
        struct dx_tail *t;
        int count_offset, limit, count;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return;
 
        c = get_dx_countlimit(inode, dirent, &count_offset);
@@ -557,8 +550,7 @@ static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize)
        unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) -
                EXT4_DIR_REC_LEN(2) - infosize;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                entry_space -= sizeof(struct dx_tail);
        return entry_space / sizeof(struct dx_entry);
 }
@@ -567,8 +559,7 @@ static inline unsigned dx_node_limit(struct inode *dir)
 {
        unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0);
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                entry_space -= sizeof(struct dx_tail);
        return entry_space / sizeof(struct dx_entry);
 }
@@ -641,7 +632,9 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
                u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
                struct stats stats;
                printk("%s%3u:%03u hash %8x/%8x ",levels?"":"   ", i, block, hash, range);
-               if (!(bh = ext4_bread (NULL,dir, block, 0,&err))) continue;
+               bh = ext4_bread(NULL,dir, block, 0);
+               if (!bh || IS_ERR(bh))
+                       continue;
                stats = levels?
                   dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
                   dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0);
@@ -669,29 +662,25 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
  */
 static struct dx_frame *
 dx_probe(const struct qstr *d_name, struct inode *dir,
-        struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
+        struct dx_hash_info *hinfo, struct dx_frame *frame_in)
 {
        unsigned count, indirect;
        struct dx_entry *at, *entries, *p, *q, *m;
        struct dx_root *root;
-       struct buffer_head *bh;
        struct dx_frame *frame = frame_in;
+       struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR);
        u32 hash;
 
-       frame->bh = NULL;
-       bh = ext4_read_dirblock(dir, 0, INDEX);
-       if (IS_ERR(bh)) {
-               *err = PTR_ERR(bh);
-               goto fail;
-       }
-       root = (struct dx_root *) bh->b_data;
+       frame->bh = ext4_read_dirblock(dir, 0, INDEX);
+       if (IS_ERR(frame->bh))
+               return (struct dx_frame *) frame->bh;
+
+       root = (struct dx_root *) frame->bh->b_data;
        if (root->info.hash_version != DX_HASH_TEA &&
            root->info.hash_version != DX_HASH_HALF_MD4 &&
            root->info.hash_version != DX_HASH_LEGACY) {
                ext4_warning(dir->i_sb, "Unrecognised inode hash code %d",
                             root->info.hash_version);
-               brelse(bh);
-               *err = ERR_BAD_DX_DIR;
                goto fail;
        }
        hinfo->hash_version = root->info.hash_version;
@@ -705,16 +694,12 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
        if (root->info.unused_flags & 1) {
                ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x",
                             root->info.unused_flags);
-               brelse(bh);
-               *err = ERR_BAD_DX_DIR;
                goto fail;
        }
 
        if ((indirect = root->info.indirect_levels) > 1) {
                ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x",
                             root->info.indirect_levels);
-               brelse(bh);
-               *err = ERR_BAD_DX_DIR;
                goto fail;
        }
 
@@ -724,27 +709,21 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
        if (dx_get_limit(entries) != dx_root_limit(dir,
                                                   root->info.info_length)) {
                ext4_warning(dir->i_sb, "dx entry: limit != root limit");
-               brelse(bh);
-               *err = ERR_BAD_DX_DIR;
                goto fail;
        }
 
        dxtrace(printk("Look up %x", hash));
-       while (1)
-       {
+       while (1) {
                count = dx_get_count(entries);
                if (!count || count > dx_get_limit(entries)) {
                        ext4_warning(dir->i_sb,
                                     "dx entry: no count or count > limit");
-                       brelse(bh);
-                       *err = ERR_BAD_DX_DIR;
-                       goto fail2;
+                       goto fail;
                }
 
                p = entries + 1;
                q = entries + count - 1;
-               while (p <= q)
-               {
+               while (p <= q) {
                        m = p + (q - p)/2;
                        dxtrace(printk("."));
                        if (dx_get_hash(m) > hash)
@@ -753,8 +732,7 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
                                p = m + 1;
                }
 
-               if (0) // linear search cross check
-               {
+               if (0) { // linear search cross check
                        unsigned n = count - 1;
                        at = entries;
                        while (n--)
@@ -771,38 +749,35 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
 
                at = p - 1;
                dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
-               frame->bh = bh;
                frame->entries = entries;
                frame->at = at;
-               if (!indirect--) return frame;
-               bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
-               if (IS_ERR(bh)) {
-                       *err = PTR_ERR(bh);
-                       goto fail2;
+               if (!indirect--)
+                       return frame;
+               frame++;
+               frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
+               if (IS_ERR(frame->bh)) {
+                       ret_err = (struct dx_frame *) frame->bh;
+                       frame->bh = NULL;
+                       goto fail;
                }
-               entries = ((struct dx_node *) bh->b_data)->entries;
+               entries = ((struct dx_node *) frame->bh->b_data)->entries;
 
                if (dx_get_limit(entries) != dx_node_limit (dir)) {
                        ext4_warning(dir->i_sb,
                                     "dx entry: limit != node limit");
-                       brelse(bh);
-                       *err = ERR_BAD_DX_DIR;
-                       goto fail2;
+                       goto fail;
                }
-               frame++;
-               frame->bh = NULL;
        }
-fail2:
+fail:
        while (frame >= frame_in) {
                brelse(frame->bh);
                frame--;
        }
-fail:
-       if (*err == ERR_BAD_DX_DIR)
+       if (ret_err == ERR_PTR(ERR_BAD_DX_DIR))
                ext4_warning(dir->i_sb,
                             "Corrupt dir inode %lu, running e2fsck is "
                             "recommended.", dir->i_ino);
-       return NULL;
+       return ret_err;
 }
 
 static void dx_release (struct dx_frame *frames)
@@ -988,9 +963,9 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
        }
        hinfo.hash = start_hash;
        hinfo.minor_hash = 0;
-       frame = dx_probe(NULL, dir, &hinfo, frames, &err);
-       if (!frame)
-               return err;
+       frame = dx_probe(NULL, dir, &hinfo, frames);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
 
        /* Add '.' and '..' from the htree header */
        if (!start_hash && !start_minor_hash) {
@@ -1227,8 +1202,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
                                   buffer */
        int num = 0;
        ext4_lblk_t  nblocks;
-       int i, err = 0;
-       int namelen;
+       int i, namelen;
 
        *res_dir = NULL;
        sb = dir->i_sb;
@@ -1258,17 +1232,13 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
                goto restart;
        }
        if (is_dx(dir)) {
-               bh = ext4_dx_find_entry(dir, d_name, res_dir, &err);
+               bh = ext4_dx_find_entry(dir, d_name, res_dir);
                /*
                 * On success, or if the error was file not found,
                 * return.  Otherwise, fall back to doing a search the
                 * old fashioned way.
                 */
-               if (err == -ENOENT)
-                       return NULL;
-               if (err && err != ERR_BAD_DX_DIR)
-                       return ERR_PTR(err);
-               if (bh)
+               if (!IS_ERR(bh) || PTR_ERR(bh) != ERR_BAD_DX_DIR)
                        return bh;
                dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
                               "falling back\n"));
@@ -1298,10 +1268,10 @@ restart:
                                        break;
                                }
                                num++;
-                               bh = ext4_getblk(NULL, dir, b++, 0, &err);
-                               if (unlikely(err)) {
+                               bh = ext4_getblk(NULL, dir, b++, 0);
+                               if (unlikely(IS_ERR(bh))) {
                                        if (ra_max == 0)
-                                               return ERR_PTR(err);
+                                               return bh;
                                        break;
                                }
                                bh_use[ra_max] = bh;
@@ -1366,7 +1336,7 @@ cleanup_and_exit:
 }
 
 static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name,
-                      struct ext4_dir_entry_2 **res_dir, int *err)
+                      struct ext4_dir_entry_2 **res_dir)
 {
        struct super_block * sb = dir->i_sb;
        struct dx_hash_info     hinfo;
@@ -1375,25 +1345,23 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
        ext4_lblk_t block;
        int retval;
 
-       if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
-               return NULL;
+       frame = dx_probe(d_name, dir, &hinfo, frames);
+       if (IS_ERR(frame))
+               return (struct buffer_head *) frame;
        do {
                block = dx_get_block(frame->at);
                bh = ext4_read_dirblock(dir, block, DIRENT);
-               if (IS_ERR(bh)) {
-                       *err = PTR_ERR(bh);
+               if (IS_ERR(bh))
                        goto errout;
-               }
+
                retval = search_dirblock(bh, dir, d_name,
                                         block << EXT4_BLOCK_SIZE_BITS(sb),
                                         res_dir);
-               if (retval == 1) {      /* Success! */
-                       dx_release(frames);
-                       return bh;
-               }
+               if (retval == 1)
+                       goto success;
                brelse(bh);
                if (retval == -1) {
-                       *err = ERR_BAD_DX_DIR;
+                       bh = ERR_PTR(ERR_BAD_DX_DIR);
                        goto errout;
                }
 
@@ -1402,18 +1370,19 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
                                               frames, NULL);
                if (retval < 0) {
                        ext4_warning(sb,
-                            "error reading index page in directory #%lu",
-                            dir->i_ino);
-                       *err = retval;
+                            "error %d reading index page in directory #%lu",
+                            retval, dir->i_ino);
+                       bh = ERR_PTR(retval);
                        goto errout;
                }
        } while (retval == 1);
 
-       *err = -ENOENT;
+       bh = NULL;
 errout:
        dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name));
-       dx_release (frames);
-       return NULL;
+success:
+       dx_release(frames);
+       return bh;
 }
 
 static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
@@ -1441,7 +1410,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
                                         dentry);
                        return ERR_PTR(-EIO);
                }
-               inode = ext4_iget(dir->i_sb, ino);
+               inode = ext4_iget_normal(dir->i_sb, ino);
                if (inode == ERR_PTR(-ESTALE)) {
                        EXT4_ERROR_INODE(dir,
                                         "deleted inode referenced: %u",
@@ -1474,7 +1443,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
                return ERR_PTR(-EIO);
        }
 
-       return d_obtain_alias(ext4_iget(child->d_inode->i_sb, ino));
+       return d_obtain_alias(ext4_iget_normal(child->d_inode->i_sb, ino));
 }
 
 /*
@@ -1533,7 +1502,7 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize)
  */
 static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
                        struct buffer_head **bh,struct dx_frame *frame,
-                       struct dx_hash_info *hinfo, int *error)
+                       struct dx_hash_info *hinfo)
 {
        unsigned blocksize = dir->i_sb->s_blocksize;
        unsigned count, continued;
@@ -1548,16 +1517,14 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        int     csum_size = 0;
        int     err = 0, i;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        bh2 = ext4_append(handle, dir, &newblock);
        if (IS_ERR(bh2)) {
                brelse(*bh);
                *bh = NULL;
-               *error = PTR_ERR(bh2);
-               return NULL;
+               return (struct ext4_dir_entry_2 *) bh2;
        }
 
        BUFFER_TRACE(*bh, "get_write_access");
@@ -1617,8 +1584,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1));
 
        /* Which block gets the new entry? */
-       if (hinfo->hash >= hash2)
-       {
+       if (hinfo->hash >= hash2) {
                swap(*bh, bh2);
                de = de2;
        }
@@ -1638,8 +1604,7 @@ journal_error:
        brelse(bh2);
        *bh = NULL;
        ext4_std_error(dir->i_sb, err);
-       *error = err;
-       return NULL;
+       return ERR_PTR(err);
 }
 
 int ext4_find_dest_de(struct inode *dir, struct inode *inode,
@@ -1718,8 +1683,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
        int             csum_size = 0;
        int             err;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(inode->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        if (!de) {
@@ -1786,8 +1750,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
        struct fake_dirent *fde;
        int             csum_size = 0;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(inode->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        blocksize =  dir->i_sb->s_blocksize;
@@ -1862,8 +1825,8 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
        ext4_handle_dirty_dx_node(handle, dir, frame->bh);
        ext4_handle_dirty_dirent_node(handle, dir, bh);
 
-       de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
-       if (!de) {
+       de = do_split(handle,dir, &bh, frame, &hinfo);
+       if (IS_ERR(de)) {
                /*
                 * Even if the block split failed, we have to properly write
                 * out all the changes we did so far. Otherwise we can end up
@@ -1871,7 +1834,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
                 */
                ext4_mark_inode_dirty(handle, dir);
                dx_release(frames);
-               return retval;
+               return PTR_ERR(de);
        }
        dx_release(frames);
 
@@ -1904,8 +1867,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        ext4_lblk_t block, blocks;
        int     csum_size = 0;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(inode->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        sb = dir->i_sb;
@@ -1982,9 +1944,9 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
        struct ext4_dir_entry_2 *de;
        int err;
 
-       frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err);
-       if (!frame)
-               return err;
+       frame = dx_probe(&dentry->d_name, dir, &hinfo, frames);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
        entries = frame->entries;
        at = frame->at;
        bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);
@@ -2095,9 +2057,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
                        goto cleanup;
                }
        }
-       de = do_split(handle, dir, &bh, frame, &hinfo, &err);
-       if (!de)
+       de = do_split(handle, dir, &bh, frame, &hinfo);
+       if (IS_ERR(de)) {
+               err = PTR_ERR(de);
                goto cleanup;
+       }
        err = add_dirent_to_buf(handle, dentry, inode, de, bh);
        goto cleanup;
 
@@ -2167,8 +2131,7 @@ static int ext4_delete_entry(handle_t *handle,
                        return err;
        }
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        BUFFER_TRACE(bh, "get_write_access");
@@ -2387,8 +2350,7 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
        int csum_size = 0;
        int err;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
@@ -2403,10 +2365,6 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
        dir_block = ext4_append(handle, inode, &block);
        if (IS_ERR(dir_block))
                return PTR_ERR(dir_block);
-       BUFFER_TRACE(dir_block, "get_write_access");
-       err = ext4_journal_get_write_access(handle, dir_block);
-       if (err)
-               goto out;
        de = (struct ext4_dir_entry_2 *)dir_block->b_data;
        ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0);
        set_nlink(inode, 2);
@@ -2573,7 +2531,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
        int err = 0, rc;
        bool dirty = false;
 
-       if (!sbi->s_journal)
+       if (!sbi->s_journal || is_bad_inode(inode))
                return 0;
 
        WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&