struct f2fs_inode_info *fi = F2FS_I(dn->inode);
        struct f2fs_summary sum;
        struct node_info ni;
+       int seg = CURSEG_WARM_DATA;
        pgoff_t fofs;
 
        if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
        get_node_info(sbi, dn->nid, &ni);
        set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
 
-       allocate_data_block(sbi, NULL, NULL_ADDR, &dn->data_blkaddr, &sum,
-                                                       CURSEG_WARM_DATA);
+       if (dn->ofs_in_node == 0 && dn->inode_page == dn->node_page)
+               seg = CURSEG_DIRECT_IO;
+
+       allocate_data_block(sbi, NULL, NULL_ADDR, &dn->data_blkaddr, &sum, seg);
 
        /* direct IO doesn't use extent cache to maximize the performance */
        __set_data_blkaddr(dn);
 
        CURSEG_HOT_NODE,        /* direct node blocks of directory files */
        CURSEG_WARM_NODE,       /* direct node blocks of normal files */
        CURSEG_COLD_NODE,       /* indirect node blocks */
-       NO_CHECK_TYPE
+       NO_CHECK_TYPE,
+       CURSEG_DIRECT_IO,       /* to use for the direct IO path */
 };
 
 struct flush_cmd {
 
        stat_inc_seg_type(sbi, curseg);
 }
 
+static void __allocate_new_segments(struct f2fs_sb_info *sbi, int type)
+{
+       struct curseg_info *curseg = CURSEG_I(sbi, type);
+       unsigned int old_segno;
+
+       old_segno = curseg->segno;
+       SIT_I(sbi)->s_ops->allocate_segment(sbi, type, true);
+       locate_dirty_segment(sbi, old_segno);
+}
+
 void allocate_new_segments(struct f2fs_sb_info *sbi)
 {
-       struct curseg_info *curseg;
-       unsigned int old_curseg;
        int i;
 
-       for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
-               curseg = CURSEG_I(sbi, i);
-               old_curseg = curseg->segno;
-               SIT_I(sbi)->s_ops->allocate_segment(sbi, i, true);
-               locate_dirty_segment(sbi, old_curseg);
-       }
+       for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++)
+               __allocate_new_segments(sbi, i);
 }
 
 static const struct segment_allocation default_salloc_ops = {
 {
        struct sit_info *sit_i = SIT_I(sbi);
        struct curseg_info *curseg;
+       bool direct_io = (type == CURSEG_DIRECT_IO);
+
+       type = direct_io ? CURSEG_WARM_DATA : type;
 
        curseg = CURSEG_I(sbi, type);
 
        mutex_lock(&curseg->curseg_mutex);
 
+       /* direct_io'ed data is aligned to the segment for better performance */
+       if (direct_io && curseg->next_blkoff)
+               __allocate_new_segments(sbi, type);
+
        *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
 
        /*