aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/f2fs/data.c6
-rw-r--r--fs/f2fs/f2fs.h1
-rw-r--r--fs/f2fs/gc.c20
-rw-r--r--fs/f2fs/super.c2
4 files changed, 28 insertions, 1 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 650099597dd2..adfe47b21991 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1716,6 +1716,7 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
1716 struct inode *inode = mapping->host; 1716 struct inode *inode = mapping->host;
1717 size_t count = iov_iter_count(iter); 1717 size_t count = iov_iter_count(iter);
1718 loff_t offset = iocb->ki_pos; 1718 loff_t offset = iocb->ki_pos;
1719 int rw = iov_iter_rw(iter);
1719 int err; 1720 int err;
1720 1721
1721 err = check_direct_IO(inode, iter, offset); 1722 err = check_direct_IO(inode, iter, offset);
@@ -1729,8 +1730,11 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
1729 1730
1730 trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter)); 1731 trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
1731 1732
1733 down_read(&F2FS_I(inode)->dio_rwsem[rw]);
1732 err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio); 1734 err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio);
1733 if (iov_iter_rw(iter) == WRITE) { 1735 up_read(&F2FS_I(inode)->dio_rwsem[rw]);
1736
1737 if (rw == WRITE) {
1734 if (err > 0) 1738 if (err > 0)
1735 set_inode_flag(inode, FI_UPDATE_WRITE); 1739 set_inode_flag(inode, FI_UPDATE_WRITE);
1736 else if (err < 0) 1740 else if (err < 0)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index b4a46b6823dc..211183c4e5c3 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -454,6 +454,7 @@ struct f2fs_inode_info {
454 struct list_head inmem_pages; /* inmemory pages managed by f2fs */ 454 struct list_head inmem_pages; /* inmemory pages managed by f2fs */
455 struct mutex inmem_lock; /* lock for inmemory pages */ 455 struct mutex inmem_lock; /* lock for inmemory pages */
456 struct extent_tree *extent_tree; /* cached extent_tree entry */ 456 struct extent_tree *extent_tree; /* cached extent_tree entry */
457 struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */
457}; 458};
458 459
459static inline void get_extent_info(struct extent_info *ext, 460static inline void get_extent_info(struct extent_info *ext,
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index c61213785914..5c8acf754513 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -755,12 +755,32 @@ next_step:
755 /* phase 3 */ 755 /* phase 3 */
756 inode = find_gc_inode(gc_list, dni.ino); 756 inode = find_gc_inode(gc_list, dni.ino);
757 if (inode) { 757 if (inode) {
758 struct f2fs_inode_info *fi = F2FS_I(inode);
759 bool locked = false;
760
761 if (S_ISREG(inode->i_mode)) {
762 if (!down_write_trylock(&fi->dio_rwsem[READ]))
763 continue;
764 if (!down_write_trylock(
765 &fi->dio_rwsem[WRITE])) {
766 up_write(&fi->dio_rwsem[READ]);
767 continue;
768 }
769 locked = true;
770 }
771
758 start_bidx = start_bidx_of_node(nofs, inode) 772 start_bidx = start_bidx_of_node(nofs, inode)
759 + ofs_in_node; 773 + ofs_in_node;
760 if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) 774 if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
761 move_encrypted_block(inode, start_bidx); 775 move_encrypted_block(inode, start_bidx);
762 else 776 else
763 move_data_page(inode, start_bidx, gc_type); 777 move_data_page(inode, start_bidx, gc_type);
778
779 if (locked) {
780 up_write(&fi->dio_rwsem[WRITE]);
781 up_write(&fi->dio_rwsem[READ]);
782 }
783
764 stat_inc_data_blk_count(sbi, 1, gc_type); 784 stat_inc_data_blk_count(sbi, 1, gc_type);
765 } 785 }
766 } 786 }
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 451dfb4041e8..b97c065cbe74 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -579,6 +579,8 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
579 INIT_LIST_HEAD(&fi->gdirty_list); 579 INIT_LIST_HEAD(&fi->gdirty_list);
580 INIT_LIST_HEAD(&fi->inmem_pages); 580 INIT_LIST_HEAD(&fi->inmem_pages);
581 mutex_init(&fi->inmem_lock); 581 mutex_init(&fi->inmem_lock);
582 init_rwsem(&fi->dio_rwsem[READ]);
583 init_rwsem(&fi->dio_rwsem[WRITE]);
582 584
583 /* Will be used by directory only */ 585 /* Will be used by directory only */
584 fi->i_dir_level = F2FS_SB(sb)->dir_level; 586 fi->i_dir_level = F2FS_SB(sb)->dir_level;