et->et_checksum = ext4_extent_block_csum(inode, eh);
 }
 
-static int ext4_split_extent_at(handle_t *handle,
-                            struct inode *inode,
-                            struct ext4_ext_path **ppath,
-                            ext4_lblk_t split,
-                            int split_flag,
-                            int flags);
+static struct ext4_ext_path *ext4_split_extent_at(handle_t *handle,
+                                                 struct inode *inode,
+                                                 struct ext4_ext_path *path,
+                                                 ext4_lblk_t split,
+                                                 int split_flag, int flags);
 
 static int ext4_ext_trunc_restart_fn(struct inode *inode, int *dropped)
 {
        if (nofail)
                flags |= EXT4_GET_BLOCKS_METADATA_NOFAIL | EXT4_EX_NOFAIL;
 
-       return ext4_split_extent_at(handle, inode, ppath, lblk, unwritten ?
+       path = ext4_split_extent_at(handle, inode, path, lblk, unwritten ?
                        EXT4_EXT_MARK_UNWRIT1|EXT4_EXT_MARK_UNWRIT2 : 0,
                        flags);
+       if (IS_ERR(path)) {
+               *ppath = NULL;
+               return PTR_ERR(path);
+       }
+       *ppath = path;
+       return 0;
 }
 
 static int
        struct ext4_extent *ex;
        int i;
 
-       if (!path)
+       if (IS_ERR_OR_NULL(path))
                return;
 
        eh = path[depth].p_hdr;
  *  a> the extent are splitted into two extent.
  *  b> split is not needed, and just mark the extent.
  *
- * return 0 on success.
+ * Return an extent path pointer on success, or an error pointer on failure.
  */
-static int ext4_split_extent_at(handle_t *handle,
-                            struct inode *inode,
-                            struct ext4_ext_path **ppath,
-                            ext4_lblk_t split,
-                            int split_flag,
-                            int flags)
+static struct ext4_ext_path *ext4_split_extent_at(handle_t *handle,
+                                                 struct inode *inode,
+                                                 struct ext4_ext_path *path,
+                                                 ext4_lblk_t split,
+                                                 int split_flag, int flags)
 {
-       struct ext4_ext_path *path = *ppath;
        ext4_fsblk_t newblock;
        ext4_lblk_t ee_block;
        struct ext4_extent *ex, newex, orig_ex, zero_ex;
                ext4_ext_mark_unwritten(ex2);
 
        path = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
-       if (!IS_ERR(path)) {
-               *ppath = path;
+       if (!IS_ERR(path))
                goto out;
-       }
-       *ppath = NULL;
+
        err = PTR_ERR(path);
        if (err != -ENOSPC && err != -EDQUOT && err != -ENOMEM)
-               return err;
+               return path;
 
        /*
         * Get a new path to try to zeroout or fix the extent length.
         * in ext4_da_update_reserve_space() due to an incorrect
         * ee_len causing the i_reserved_data_blocks exception.
         */
-       path = ext4_find_extent(inode, ee_block, NULL,
-                               flags | EXT4_EX_NOFAIL);
+       path = ext4_find_extent(inode, ee_block, NULL, flags | EXT4_EX_NOFAIL);
        if (IS_ERR(path)) {
                EXT4_ERROR_INODE(inode, "Failed split extent on %u, err %ld",
                                 split, PTR_ERR(path));
-               return PTR_ERR(path);
+               return path;
        }
        depth = ext_depth(inode);
        ex = path[depth].p_ext;
-       *ppath = path;
 
        if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
                if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
         * and err is a non-zero error code.
         */
        ext4_ext_dirty(handle, inode, path + path->p_depth);
-       return err;
 out:
+       if (err) {
+               ext4_free_ext_path(path);
+               path = ERR_PTR(err);
+       }
        ext4_ext_show_leaf(inode, path);
-       return err;
+       return path;
 }
 
 /*
                                       EXT4_EXT_MARK_UNWRIT2;
                if (split_flag & EXT4_EXT_DATA_VALID2)
                        split_flag1 |= EXT4_EXT_DATA_VALID1;
-               err = ext4_split_extent_at(handle, inode, ppath,
+               path = ext4_split_extent_at(handle, inode, path,
                                map->m_lblk + map->m_len, split_flag1, flags1);
-               if (err)
+               if (IS_ERR(path)) {
+                       err = PTR_ERR(path);
+                       *ppath = NULL;
                        goto out;
+               }
+               *ppath = path;
        } else {
                allocated = ee_len - (map->m_lblk - ee_block);
        }
         * Update path is required because previous ext4_split_extent_at() may
         * result in split of original leaf or extent zeroout.
         */
-       path = ext4_find_extent(inode, map->m_lblk, *ppath, flags);
+       path = ext4_find_extent(inode, map->m_lblk, path, flags);
        if (IS_ERR(path)) {
                *ppath = NULL;
                return PTR_ERR(path);
                        split_flag1 |= split_flag & (EXT4_EXT_MAY_ZEROOUT |
                                                     EXT4_EXT_MARK_UNWRIT2);
                }
-               err = ext4_split_extent_at(handle, inode, ppath,
+               path = ext4_split_extent_at(handle, inode, path,
                                map->m_lblk, split_flag1, flags);
-               if (err)
+               if (IS_ERR(path)) {
+                       err = PTR_ERR(path);
+                       *ppath = NULL;
                        goto out;
+               }
+               *ppath = path;
        }
 
-       ext4_ext_show_leaf(inode, *ppath);
+       ext4_ext_show_leaf(inode, path);
 out:
        return err ? err : allocated;
 }
                        if (ext4_ext_is_unwritten(extent))
                                split_flag = EXT4_EXT_MARK_UNWRIT1 |
                                        EXT4_EXT_MARK_UNWRIT2;
-                       ret = ext4_split_extent_at(handle, inode, &path,
+                       path = ext4_split_extent_at(handle, inode, path,
                                        offset_lblk, split_flag,
                                        EXT4_EX_NOCACHE |
                                        EXT4_GET_BLOCKS_PRE_IO |
                                        EXT4_GET_BLOCKS_METADATA_NOFAIL);
                }
 
-               ext4_free_ext_path(path);
-               if (ret < 0) {
+               if (IS_ERR(path)) {
                        up_write(&EXT4_I(inode)->i_data_sem);
+                       ret = PTR_ERR(path);
                        goto out_stop;
                }
-       } else {
-               ext4_free_ext_path(path);
        }
 
+       ext4_free_ext_path(path);
        ext4_es_remove_extent(inode, offset_lblk, EXT_MAX_BLOCKS - offset_lblk);
 
        /*