Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
[deliverable/linux.git] / fs / f2fs / gc.c
index c6121378591489c29685fb76c9ef382cdb01a109..8f7fa326ce95b169e74d3ac0fcb205648a7fae90 100644 (file)
@@ -538,7 +538,8 @@ static void move_encrypted_block(struct inode *inode, block_t bidx)
        struct f2fs_io_info fio = {
                .sbi = F2FS_I_SB(inode),
                .type = DATA,
-               .rw = READ_SYNC,
+               .op = REQ_OP_READ,
+               .op_flags = READ_SYNC,
                .encrypted_page = NULL,
        };
        struct dnode_of_data dn;
@@ -612,7 +613,8 @@ static void move_encrypted_block(struct inode *inode, block_t bidx)
        /* allocate block address */
        f2fs_wait_on_page_writeback(dn.node_page, NODE, true);
 
-       fio.rw = WRITE_SYNC;
+       fio.op = REQ_OP_WRITE;
+       fio.op_flags = WRITE_SYNC;
        fio.new_blkaddr = newaddr;
        f2fs_submit_page_mbio(&fio);
 
@@ -649,7 +651,8 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type)
                struct f2fs_io_info fio = {
                        .sbi = F2FS_I_SB(inode),
                        .type = DATA,
-                       .rw = WRITE_SYNC,
+                       .op = REQ_OP_WRITE,
+                       .op_flags = WRITE_SYNC,
                        .page = page,
                        .encrypted_page = NULL,
                };
@@ -741,7 +744,8 @@ next_step:
 
                        start_bidx = start_bidx_of_node(nofs, inode);
                        data_page = get_read_data_page(inode,
-                                       start_bidx + ofs_in_node, READA, true);
+                                       start_bidx + ofs_in_node, REQ_RAHEAD,
+                                       true);
                        if (IS_ERR(data_page)) {
                                iput(inode);
                                continue;
@@ -755,12 +759,32 @@ next_step:
                /* phase 3 */
                inode = find_gc_inode(gc_list, dni.ino);
                if (inode) {
+                       struct f2fs_inode_info *fi = F2FS_I(inode);
+                       bool locked = false;
+
+                       if (S_ISREG(inode->i_mode)) {
+                               if (!down_write_trylock(&fi->dio_rwsem[READ]))
+                                       continue;
+                               if (!down_write_trylock(
+                                               &fi->dio_rwsem[WRITE])) {
+                                       up_write(&fi->dio_rwsem[READ]);
+                                       continue;
+                               }
+                               locked = true;
+                       }
+
                        start_bidx = start_bidx_of_node(nofs, inode)
                                                                + ofs_in_node;
                        if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
                                move_encrypted_block(inode, start_bidx);
                        else
                                move_data_page(inode, start_bidx, gc_type);
+
+                       if (locked) {
+                               up_write(&fi->dio_rwsem[WRITE]);
+                               up_write(&fi->dio_rwsem[READ]);
+                       }
+
                        stat_inc_data_blk_count(sbi, 1, gc_type);
                }
        }
@@ -788,6 +812,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
 {
        struct page *sum_page;
        struct f2fs_summary_block *sum;
+       struct blk_plug plug;
        unsigned int segno = start_segno;
        unsigned int end_segno = start_segno + sbi->segs_per_sec;
        int seg_freed = 0;
@@ -805,6 +830,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
                unlock_page(sum_page);
        }
 
+       blk_start_plug(&plug);
+
        for (segno = start_segno; segno < end_segno; segno++) {
 
                if (get_valid_blocks(sbi, segno, 1) == 0)
@@ -842,6 +869,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
                f2fs_submit_merged_bio(sbi,
                                (type == SUM_TYPE_NODE) ? NODE : DATA, WRITE);
 
+       blk_finish_plug(&plug);
+
        if (gc_type == FG_GC) {
                while (start_segno < end_segno)
                        if (get_valid_blocks(sbi, start_segno++, 1) == 0)
@@ -883,10 +912,13 @@ gc_more:
                 * enough free sections, we should flush dent/node blocks and do
                 * garbage collections.
                 */
-               if (__get_victim(sbi, &segno, gc_type) || prefree_segments(sbi))
+               if (__get_victim(sbi, &segno, gc_type) ||
+                                               prefree_segments(sbi)) {
                        write_checkpoint(sbi, &cpc);
-               else if (has_not_enough_free_secs(sbi, 0))
+                       segno = NULL_SEGNO;
+               } else if (has_not_enough_free_secs(sbi, 0)) {
                        write_checkpoint(sbi, &cpc);
+               }
        }
 
        if (segno == NULL_SEGNO && !__get_victim(sbi, &segno, gc_type))
This page took 0.040645 seconds and 5 git commands to generate.