struct ext4_inode_info *ei)
 {
        blkcnt_t i_blocks ;
-       struct super_block *sb = ei->vfs_inode.i_sb;
+       struct inode *inode = &(ei->vfs_inode);
+       struct super_block *sb = inode->i_sb;
 
        if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
                                EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
                /* we are using combined 48 bit field */
                i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 |
                                        le32_to_cpu(raw_inode->i_blocks_lo);
-               return i_blocks;
+               if (ei->i_flags & EXT4_HUGE_FILE_FL) {
+                       /* i_blocks represent file system block size */
+                       return i_blocks  << (inode->i_blkbits - 9);
+               } else {
+                       return i_blocks;
+               }
        } else {
                return le32_to_cpu(raw_inode->i_blocks_lo);
        }
                 * i_blocks can be represnted in a 32 bit variable
                 * as multiple of 512 bytes
                 */
-               raw_inode->i_blocks_lo   = cpu_to_le32((u32)i_blocks);
+               raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
                raw_inode->i_blocks_high = 0;
+               ei->i_flags &= ~EXT4_HUGE_FILE_FL;
        } else if (i_blocks <= 0xffffffffffffULL) {
                /*
                 * i_blocks can be represented in a 48 bit variable
                if (err)
                        goto  err_out;
                /* i_block is stored in the split  48 bit fields */
-               raw_inode->i_blocks_lo   = cpu_to_le32((u32)i_blocks);
+               raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
                raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
+               ei->i_flags &= ~EXT4_HUGE_FILE_FL;
        } else {
-               ext4_error(sb, __FUNCTION__,
-                               "Wrong inode i_blocks count  %llu\n",
-                               (unsigned long long)inode->i_blocks);
+               /*
+                * i_blocks should be represented in a 48 bit variable
+                * as multiple of  file system block size
+                */
+               err = ext4_update_rocompat_feature(handle, sb,
+                                           EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
+               if (err)
+                       goto  err_out;
+               ei->i_flags |= EXT4_HUGE_FILE_FL;
+               /* i_block is stored in file system block size */
+               i_blocks = i_blocks >> (inode->i_blkbits - 9);
+               raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
+               raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
        }
 err_out:
        return err;
 
                upper_limit >>= (bits - 9);
 
        } else {
-               /* We use 48 bit ext4_inode i_blocks */
+               /*
+                * We use 48 bit ext4_inode i_blocks
+                * With EXT4_HUGE_FILE_FL set the i_blocks
+                * represent total number of blocks in
+                * file system block size
+                */
                upper_limit = (1LL << 48) - 1;
 
-               /* total blocks in file system block size */
-               upper_limit >>= (bits - 9);
        }
 
        /* indirect blocks */
 
 #define EXT4_NOTAIL_FL                 0x00008000 /* file tail should not be merged */
 #define EXT4_DIRSYNC_FL                        0x00010000 /* dirsync behaviour (directories only) */
 #define EXT4_TOPDIR_FL                 0x00020000 /* Top of directory hierarchies*/
-#define EXT4_RESERVED_FL               0x80000000 /* reserved for ext4 lib */
+#define EXT4_HUGE_FILE_FL               0x00040000 /* Set to each huge file */
 #define EXT4_EXTENTS_FL                        0x00080000 /* Inode uses extents */
+#define EXT4_RESERVED_FL               0x80000000 /* reserved for ext4 lib */
 
 #define EXT4_FL_USER_VISIBLE           0x000BDFFF /* User visible flags */
 #define EXT4_FL_USER_MODIFIABLE                0x000380FF /* User modifiable flags */