Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a48006c5 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "f2fs: avoid infinite GC loop due to stale atomic files"

parents 4acd8ac5 dd9d552f
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -1741,6 +1741,8 @@ static int f2fs_ioc_getversion(struct file *filp, unsigned long arg)
static int f2fs_ioc_start_atomic_write(struct file *filp)
{
	struct inode *inode = file_inode(filp);
	struct f2fs_inode_info *fi = F2FS_I(inode);
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	int ret;

	if (!inode_owner_or_capable(inode))
@@ -1781,6 +1783,12 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
		goto out;
	}

	spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
	if (list_empty(&fi->inmem_ilist))
		list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]);
	spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);

	/* add inode in inmem_list first and set atomic_file */
	set_inode_flag(inode, FI_ATOMIC_FILE);
	clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
	up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
@@ -1822,11 +1830,8 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
			goto err_out;

		ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true);
		if (!ret) {
			clear_inode_flag(inode, FI_ATOMIC_FILE);
			F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
			stat_dec_atomic_write(inode);
		}
		if (!ret)
			f2fs_drop_inmem_pages(inode);
	} else {
		ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 1, false);
	}
+8 −21
Original line number Diff line number Diff line
@@ -185,8 +185,6 @@ bool f2fs_need_SSR(struct f2fs_sb_info *sbi)

void f2fs_register_inmem_page(struct inode *inode, struct page *page)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	struct f2fs_inode_info *fi = F2FS_I(inode);
	struct inmem_pages *new;

	f2fs_trace_pid(page);
@@ -200,15 +198,11 @@ void f2fs_register_inmem_page(struct inode *inode, struct page *page)
	INIT_LIST_HEAD(&new->list);

	/* increase reference count with clean state */
	mutex_lock(&fi->inmem_lock);
	get_page(page);
	list_add_tail(&new->list, &fi->inmem_pages);
	spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
	if (list_empty(&fi->inmem_ilist))
		list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]);
	spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
	mutex_lock(&F2FS_I(inode)->inmem_lock);
	list_add_tail(&new->list, &F2FS_I(inode)->inmem_pages);
	inc_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES);
	mutex_unlock(&fi->inmem_lock);
	mutex_unlock(&F2FS_I(inode)->inmem_lock);

	trace_f2fs_register_inmem_page(page, INMEM);
}
@@ -330,19 +324,17 @@ void f2fs_drop_inmem_pages(struct inode *inode)
		mutex_lock(&fi->inmem_lock);
		__revoke_inmem_pages(inode, &fi->inmem_pages,
						true, false, true);

		if (list_empty(&fi->inmem_pages)) {
			spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
			if (!list_empty(&fi->inmem_ilist))
				list_del_init(&fi->inmem_ilist);
			spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
		}
		mutex_unlock(&fi->inmem_lock);
	}

	clear_inode_flag(inode, FI_ATOMIC_FILE);
	fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
	stat_dec_atomic_write(inode);

	spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
	if (!list_empty(&fi->inmem_ilist))
		list_del_init(&fi->inmem_ilist);
	spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
}

void f2fs_drop_inmem_page(struct inode *inode, struct page *page)
@@ -471,11 +463,6 @@ int f2fs_commit_inmem_pages(struct inode *inode)

	mutex_lock(&fi->inmem_lock);
	err = __f2fs_commit_inmem_pages(inode);

	spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
	if (!list_empty(&fi->inmem_ilist))
		list_del_init(&fi->inmem_ilist);
	spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
	mutex_unlock(&fi->inmem_lock);

	clear_inode_flag(inode, FI_ATOMIC_COMMIT);