summaryrefslogtreecommitdiff
path: root/fs/f2fs/gc.c
diff options
context:
space:
mode:
authorSrinivasarao P <spathi@codeaurora.org>2018-11-12 11:15:16 +0530
committerSrinivasarao P <spathi@codeaurora.org>2018-11-15 17:07:08 +0530
commitb28608bd1464a2cc09e647cf1e76a70fc05300eb (patch)
treedeaa4be670a2fc234e9e38d55602f67783ea0f32 /fs/f2fs/gc.c
parentf1587d8660239a4371a73d10a2c56834d7daf6cc (diff)
parent0ca3fcabdc05c1db8881aa8a9bae4734911a5597 (diff)
Merge android-4.4.163 (0ca3fca) into msm-4.4
* refs/heads/tmp-0ca3fca Linux 4.4.163 x86/time: Correct the attribute on jiffies' definition l2tp: hold tunnel socket when handling control frames in l2tp_ip and l2tp_ip6 cpuidle: Do not access cpuidle_devices when !CONFIG_CPU_IDLE x86/percpu: Fix this_cpu_read() sched/fair: Fix throttle_list starvation with low CFS quota Input: elan_i2c - add ACPI ID for Lenovo IdeaPad 330-15IGM USB: fix the usbfs flag sanitization for control transfers usb: gadget: storage: Fix Spectre v1 vulnerability cdc-acm: correct counting of UART states in serial state notification IB/ucm: Fix Spectre v1 vulnerability RDMA/ucma: Fix Spectre v1 vulnerability ptp: fix Spectre v1 vulnerability cachefiles: fix the race between cachefiles_bury_object() and rmdir(2) ahci: don't ignore result code of ahci_reset_controller() crypto: shash - Fix a sleep-in-atomic bug in shash_setkey_unaligned mremap: properly flush TLB before releasing the page rtnetlink: Disallow FDB configuration for non-Ethernet device vhost: Fix Spectre V1 vulnerability net: drop skb on failure in ip_check_defrag() sctp: fix race on sctp_id2asoc r8169: fix NAPI handling under high load net: stmmac: Fix stmmac_mdio_reset() when building stmmac as modules net: socket: fix a missing-check bug net: sched: gred: pass the right attribute to gred_change_table_def() net/ipv6: Fix index counter for unicast addresses in in6_dump_addrs ipv6/ndisc: Preserve IPv6 control buffer if protocol error handlers are called ipv6: mcast: fix a use-after-free in inet6_mc_check net: bridge: remove ipv6 zero address check in mcast queries bridge: do not add port to router list when receives query with source 0.0.0.0 perf tools: Disable parallelism for 'make clean' mtd: spi-nor: Add support for is25wp series chips fs/fat/fatent.c: add cond_resched() to fat_count_free_clusters() ARM: dts: imx53-qsb: disable 1.2GHz OPP MIPS: DEC: Fix an int-handler.S CPU_DADDI_WORKAROUNDS regression igb: Remove superfluous reset to PHY and page 0 selection MIPS: microMIPS: Fix decoding of swsp16 instruction scsi: aacraid: Fix typo in blink status bonding: avoid defaulting hard_header_len to ETH_HLEN on slave removal PM / devfreq: tegra: fix error return code in tegra_devfreq_probe() ASoC: spear: fix error return code in spdif_in_probe() spi: xlp: fix error return code in xlp_spi_probe() spi/bcm63xx: fix error return code in bcm63xx_spi_probe() MIPS: Handle non word sized instructions when examining frame spi/bcm63xx-hspi: fix error return code in bcm63xx_hsspi_probe() usb: dwc3: omap: fix error return code in dwc3_omap_probe() usb: ehci-omap: fix error return code in ehci_hcd_omap_probe() usb: imx21-hcd: fix error return code in imx21_probe() gpio: msic: fix error return code in platform_msic_gpio_probe() sparc64: Fix exception handling in UltraSPARC-III memcpy. gpu: host1x: fix error return code in host1x_probe() sparc64 mm: Fix more TSB sizing issues video: fbdev: pxa3xx_gcu: fix error return code in pxa3xx_gcu_probe() tty: serial: sprd: fix error return code in sprd_probe() l2tp: hold socket before dropping lock in l2tp_ip{, 6}_recv() brcmfmac: Fix glom_skb leak in brcmf_sdiod_recv_chain gro: Allow tunnel stacking in the case of FOU/GUE vti6: flush x-netns xfrm cache when vti interface is removed ALSA: timer: Fix zero-division by continue of uninitialized instance ixgbe: Correct X550EM_x revision check ixgbe: fix RSS limit for X550 net/mlx5e: Correctly handle RSS indirection table when changing number of channels net/mlx5e: Fix LRO modify ixgbevf: Fix handling of NAPI budget when multiple queues are enabled per vector fuse: Dont call set_page_dirty_lock() for ITER_BVEC pages for async_dio drm/nouveau/fbcon: fix oops without fbdev emulation bpf: generally move prog destruction to RCU deferral usb-storage: fix bogus hardware error messages for ATA pass-thru devices sch_red: update backlog as well sparc/pci: Refactor dev_archdata initialization into pci_init_dev_archdata scsi: Add STARGET_CREATED_REMOVE state to scsi_target_state xfrm: Clear sk_dst_cache when applying per-socket policy. arm64: Fix potential race with hardware DBM in ptep_set_access_flags() CIFS: handle guest access errors to Windows shares ASoC: wm8940: Enable cache usage to fix crashes on resume ASoC: ak4613: Enable cache usage to fix crashes on resume MIPS: Fix FCSR Cause bit handling for correct SIGFPE issue usbvision: revert commit 588afcc1 perf/core: Don't leak event in the syscall error path aacraid: Start adapter after updating number of MSIX vectors x86/PCI: Mark Broadwell-EP Home Agent 1 as having non-compliant BARs tpm: fix: return rc when devm_add_action() fails thermal: allow u8500-thermal driver to be a module thermal: allow spear-thermal driver to be a module btrfs: don't create or leak aliased root while cleaning up orphans sched/cgroup: Fix cgroup entity load tracking tear-down um: Avoid longjmp/setjmp symbol clashes with libpthread.a ipv6: orphan skbs in reassembly unit net/mlx4_en: Resolve dividing by zero in 32-bit system af_iucv: Move sockaddr length checks to before accessing sa_family in bind and connect handlers radix-tree: fix radix_tree_iter_retry() for tagged iterators. x86/mm/pat: Prevent hang during boot when mapping pages ARM: dts: apq8064: add ahci ports-implemented mask tracing: Skip more functions when doing stack tracing of events ser_gigaset: use container_of() instead of detour net: drop write-only stack variable ipv6: suppress sparse warnings in IP6_ECN_set_ce() KEYS: put keyring if install_session_keyring_to_cred() fails net: cxgb3_main: fix a missing-check bug perf/ring_buffer: Prevent concurent ring buffer access smsc95xx: Check for Wake-on-LAN modes smsc75xx: Check for Wake-on-LAN modes r8152: Check for supported Wake-on-LAN Modes sr9800: Check for supported Wake-on-LAN modes lan78xx: Check for supported Wake-on-LAN modes ax88179_178a: Check for supported Wake-on-LAN modes asix: Check for supported Wake-on-LAN modes pxa168fb: prepare the clock Bluetooth: SMP: fix crash in unpairing mac80211_hwsim: do not omit multicast announce of first added radio xfrm: validate template mode ARM: 8799/1: mm: fix pci_ioremap_io() offset check cfg80211: reg: Init wiphy_idx in regulatory_hint_core() mac80211: Always report TX status xfrm6: call kfree_skb when skb is toobig xfrm: Validate address prefix lengths in the xfrm selector. BACKPORT: xfrm: Allow Output Mark to be Updated Using UPDSA ANDROID: sdcardfs: Add option to drop unused dentries f2fs: guarantee journalled quota data by checkpoint f2fs: cleanup dirty pages if recover failed f2fs: fix data corruption issue with hardware encryption f2fs: fix to recover inode->i_flags of inode block during POR f2fs: spread f2fs_set_inode_flags() f2fs: fix to spread clear_cold_data() Revert "f2fs: fix to clear PG_checked flag in set_page_dirty()" f2fs: account read IOs and use IO counts for is_idle f2fs: fix to account IO correctly for cgroup writeback f2fs: fix to account IO correctly f2fs: remove request_list check in is_idle() f2fs: allow to mount, if quota is failed f2fs: update REQ_TIME in f2fs_cross_rename() f2fs: do not update REQ_TIME in case of error conditions f2fs: remove unneeded disable_nat_bits() f2fs: remove unused sbi->trigger_ssr_threshold f2fs: shrink sbi->sb_lock coverage in set_file_temperature() f2fs: fix to recover cold bit of inode block during POR f2fs: submit cached bio to avoid endless PageWriteback f2fs: checkpoint disabling f2fs: clear PageError on the read path f2fs: allow out-place-update for direct IO in LFS mode f2fs: refactor ->page_mkwrite() flow Revert: "f2fs: check last page index in cached bio to decide submission" f2fs: support superblock checksum f2fs: add to account skip count of background GC f2fs: add to account meta IO f2fs: keep lazytime on remount f2fs: fix missing up_read f2fs: return correct errno in f2fs_gc f2fs: avoid f2fs_bug_on if f2fs_get_meta_page_nofail got EIO f2fs: mark inode dirty explicitly in recover_inode() f2fs: fix to recover inode's crtime during POR f2fs: fix to recover inode's i_gc_failures during POR f2fs: fix to recover inode's i_flags during POR f2fs: fix to recover inode's project id during POR f2fs: update i_size after DIO completion f2fs: report ENOENT correctly in f2fs_rename f2fs: fix remount problem of option io_bits f2fs: fix to recover inode's uid/gid during POR f2fs: avoid infinite loop in f2fs_alloc_nid f2fs: add new idle interval timing for discard and gc paths f2fs: split IO error injection according to RW f2fs: add SPDX license identifiers f2fs: surround fault_injection related option parsing using CONFIG_F2FS_FAULT_INJECTION f2fs: avoid sleeping under spin_lock f2fs: plug readahead IO in readdir() f2fs: fix to do sanity check with current segment number f2fs: fix memory leak of percpu counter in fill_super() f2fs: fix memory leak of write_io in fill_super() f2fs: cache NULL when both default_acl and acl are NULL f2fs: fix to flush all dirty inodes recovered in readonly fs f2fs: report error if quota off error during umount f2fs: submit bio after shutdown f2fs: avoid wrong decrypted data from disk Revert "f2fs: use printk_ratelimited for f2fs_msg" f2fs: fix unnecessary periodic wakeup of discard thread when dev is busy f2fs: fix to avoid NULL pointer dereference on se->discard_map f2fs: add additional sanity check in f2fs_acl_from_disk() Revert "BACKPORT, FROMLIST: fscrypt: add Speck128/256 support" Build fix for 076c36fce1ea0. Revert "BACKPORT, FROMGIT: crypto: speck - add support for the Speck block cipher" Revert "FROMGIT: crypto: speck - export common helpers" Revert "BACKPORT, FROMGIT: crypto: arm/speck - add NEON-accelerated implementation of Speck-XTS" Revert "BACKPORT, FROMGIT: crypto: speck - add test vectors for Speck128-XTS" Revert "BACKPORT, FROMGIT: crypto: speck - add test vectors for Speck64-XTS" Revert "BACKPORT, FROMLIST: crypto: arm64/speck - add NEON-accelerated implementation of Speck-XTS" Revert "fscrypt: add Speck128/256 support" UPSTREAM: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl BACKPORT: block/loop: set hw_sectors UPSTREAM: loop: add ioctl for changing logical block size Conflicts: fs/ext4/crypto.c fs/ext4/ext4.h Change-Id: I8cb2f70b27906879f8e8fdd90e67f438e39701b8 Signed-off-by: Srinivasarao P <spathi@codeaurora.org>
Diffstat (limited to 'fs/f2fs/gc.c')
-rw-r--r--fs/f2fs/gc.c115
1 files changed, 83 insertions, 32 deletions
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index ada8b8056cd0..843430b55a73 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* fs/f2fs/gc.c
*
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/fs.h>
#include <linux/module.h>
@@ -43,13 +40,16 @@ static int gc_thread_func(void *data)
if (gc_th->gc_wake)
gc_th->gc_wake = 0;
- if (try_to_freeze())
+ if (try_to_freeze()) {
+ stat_other_skip_bggc_count(sbi);
continue;
+ }
if (kthread_should_stop())
break;
if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) {
increase_sleep_time(gc_th, &wait_ms);
+ stat_other_skip_bggc_count(sbi);
continue;
}
@@ -58,8 +58,10 @@ static int gc_thread_func(void *data)
f2fs_stop_checkpoint(sbi, false);
}
- if (!sb_start_write_trylock(sbi->sb))
+ if (!sb_start_write_trylock(sbi->sb)) {
+ stat_other_skip_bggc_count(sbi);
continue;
+ }
/*
* [GC triggering condition]
@@ -80,12 +82,15 @@ static int gc_thread_func(void *data)
goto do_gc;
}
- if (!mutex_trylock(&sbi->gc_mutex))
+ if (!mutex_trylock(&sbi->gc_mutex)) {
+ stat_other_skip_bggc_count(sbi);
goto next;
+ }
- if (!is_idle(sbi)) {
+ if (!is_idle(sbi, GC_TIME)) {
increase_sleep_time(gc_th, &wait_ms);
mutex_unlock(&sbi->gc_mutex);
+ stat_io_skip_bggc_count(sbi);
goto next;
}
@@ -365,6 +370,10 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
if (sec_usage_check(sbi, secno))
goto next;
+ /* Don't touch checkpointed data */
+ if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
+ get_ckpt_valid_blocks(sbi, segno)))
+ goto next;
if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
goto next;
@@ -464,7 +473,7 @@ static int check_valid_map(struct f2fs_sb_info *sbi,
* On validity, copy that node with cold status, otherwise (invalid node)
* ignore that.
*/
-static void gc_node_segment(struct f2fs_sb_info *sbi,
+static int gc_node_segment(struct f2fs_sb_info *sbi,
struct f2fs_summary *sum, unsigned int segno, int gc_type)
{
struct f2fs_summary *entry;
@@ -472,6 +481,7 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
int off;
int phase = 0;
bool fggc = (gc_type == FG_GC);
+ int submitted = 0;
start_addr = START_BLOCK(sbi, segno);
@@ -485,10 +495,11 @@ next_step:
nid_t nid = le32_to_cpu(entry->nid);
struct page *node_page;
struct node_info ni;
+ int err;
/* stop BG_GC if there is not enough free sections. */
if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0))
- return;
+ return submitted;
if (check_valid_map(sbi, segno, off) == 0)
continue;
@@ -525,7 +536,9 @@ next_step:
continue;
}
- f2fs_move_node_page(node_page, gc_type);
+ err = f2fs_move_node_page(node_page, gc_type);
+ if (!err && gc_type == FG_GC)
+ submitted++;
stat_inc_node_blk_count(sbi, 1, gc_type);
}
@@ -534,6 +547,7 @@ next_step:
if (fggc)
atomic_dec(&sbi->wb_sync_req[NODE]);
+ return submitted;
}
/*
@@ -669,7 +683,7 @@ put_page:
* Move data block via META_MAPPING while keeping locked data page.
* This can be used to move blocks, aka LBAs, directly on disk.
*/
-static void move_data_block(struct inode *inode, block_t bidx,
+static int move_data_block(struct inode *inode, block_t bidx,
int gc_type, unsigned int segno, int off)
{
struct f2fs_io_info fio = {
@@ -688,25 +702,29 @@ static void move_data_block(struct inode *inode, block_t bidx,
struct node_info ni;
struct page *page, *mpage;
block_t newaddr;
- int err;
+ int err = 0;
bool lfs_mode = test_opt(fio.sbi, LFS);
/* do not read out */
page = f2fs_grab_cache_page(inode->i_mapping, bidx, false);
if (!page)
- return;
+ return -ENOMEM;
- if (!check_valid_map(F2FS_I_SB(inode), segno, off))
+ if (!check_valid_map(F2FS_I_SB(inode), segno, off)) {
+ err = -ENOENT;
goto out;
+ }
if (f2fs_is_atomic_file(inode)) {
F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++;
F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++;
+ err = -EAGAIN;
goto out;
}
if (f2fs_is_pinned_file(inode)) {
f2fs_pin_file_control(inode, true);
+ err = -EAGAIN;
goto out;
}
@@ -717,6 +735,7 @@ static void move_data_block(struct inode *inode, block_t bidx,
if (unlikely(dn.data_blkaddr == NULL_ADDR)) {
ClearPageUptodate(page);
+ err = -ENOENT;
goto put_out;
}
@@ -799,6 +818,7 @@ write_page:
fio.new_blkaddr = newaddr;
f2fs_submit_page_write(&fio);
if (fio.retry) {
+ err = -EAGAIN;
if (PageWriteback(fio.encrypted_page))
end_page_writeback(fio.encrypted_page);
goto put_page_out;
@@ -822,34 +842,42 @@ put_out:
f2fs_put_dnode(&dn);
out:
f2fs_put_page(page, 1);
+ return err;
}
-static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
+static int move_data_page(struct inode *inode, block_t bidx, int gc_type,
unsigned int segno, int off)
{
struct page *page;
+ int err = 0;
page = f2fs_get_lock_data_page(inode, bidx, true);
if (IS_ERR(page))
- return;
+ return PTR_ERR(page);
- if (!check_valid_map(F2FS_I_SB(inode), segno, off))
+ if (!check_valid_map(F2FS_I_SB(inode), segno, off)) {
+ err = -ENOENT;
goto out;
+ }
if (f2fs_is_atomic_file(inode)) {
F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++;
F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++;
+ err = -EAGAIN;
goto out;
}
if (f2fs_is_pinned_file(inode)) {
if (gc_type == FG_GC)
f2fs_pin_file_control(inode, true);
+ err = -EAGAIN;
goto out;
}
if (gc_type == BG_GC) {
- if (PageWriteback(page))
+ if (PageWriteback(page)) {
+ err = -EAGAIN;
goto out;
+ }
set_page_dirty(page);
set_cold_data(page);
} else {
@@ -867,7 +895,6 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
.io_type = FS_GC_DATA_IO,
};
bool is_dirty = PageDirty(page);
- int err;
retry:
set_page_dirty(page);
@@ -892,6 +919,7 @@ retry:
}
out:
f2fs_put_page(page, 1);
+ return err;
}
/*
@@ -901,7 +929,7 @@ out:
* If the parent node is not valid or the data block address is different,
* the victim data block is ignored.
*/
-static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
struct gc_inode_list *gc_list, unsigned int segno, int gc_type)
{
struct super_block *sb = sbi->sb;
@@ -909,6 +937,7 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
block_t start_addr;
int off;
int phase = 0;
+ int submitted = 0;
start_addr = START_BLOCK(sbi, segno);
@@ -925,7 +954,7 @@ next_step:
/* stop BG_GC if there is not enough free sections. */
if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0))
- return;
+ return submitted;
if (check_valid_map(sbi, segno, off) == 0)
continue;
@@ -997,6 +1026,7 @@ next_step:
if (inode) {
struct f2fs_inode_info *fi = F2FS_I(inode);
bool locked = false;
+ int err;
if (S_ISREG(inode->i_mode)) {
if (!down_write_trylock(&fi->i_gc_rwsem[READ]))
@@ -1016,12 +1046,16 @@ next_step:
start_bidx = f2fs_start_bidx_of_node(nofs, inode)
+ ofs_in_node;
if (f2fs_post_read_required(inode))
- move_data_block(inode, start_bidx, gc_type,
- segno, off);
+ err = move_data_block(inode, start_bidx,
+ gc_type, segno, off);
else
- move_data_page(inode, start_bidx, gc_type,
+ err = move_data_page(inode, start_bidx, gc_type,
segno, off);
+ if (!err && (gc_type == FG_GC ||
+ f2fs_post_read_required(inode)))
+ submitted++;
+
if (locked) {
up_write(&fi->i_gc_rwsem[WRITE]);
up_write(&fi->i_gc_rwsem[READ]);
@@ -1033,6 +1067,8 @@ next_step:
if (++phase < 5)
goto next_step;
+
+ return submitted;
}
static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
@@ -1060,6 +1096,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
int seg_freed = 0;
unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ?
SUM_TYPE_DATA : SUM_TYPE_NODE;
+ int submitted = 0;
/* readahead multi ssa blocks those have contiguous address */
if (sbi->segs_per_sec > 1)
@@ -1069,6 +1106,18 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
/* reference all summary page */
while (segno < end_segno) {
sum_page = f2fs_get_sum_page(sbi, segno++);
+ if (IS_ERR(sum_page)) {
+ int err = PTR_ERR(sum_page);
+
+ end_segno = segno - 1;
+ for (segno = start_segno; segno < end_segno; segno++) {
+ sum_page = find_get_page(META_MAPPING(sbi),
+ GET_SUM_BLOCK(sbi, segno));
+ f2fs_put_page(sum_page, 0);
+ f2fs_put_page(sum_page, 0);
+ }
+ return err;
+ }
unlock_page(sum_page);
}
@@ -1103,10 +1152,11 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
* - lock_page(sum_page)
*/
if (type == SUM_TYPE_NODE)
- gc_node_segment(sbi, sum->entries, segno, gc_type);
- else
- gc_data_segment(sbi, sum->entries, gc_list, segno,
+ submitted += gc_node_segment(sbi, sum->entries, segno,
gc_type);
+ else
+ submitted += gc_data_segment(sbi, sum->entries, gc_list,
+ segno, gc_type);
stat_inc_seg_count(sbi, type, gc_type);
@@ -1117,7 +1167,7 @@ next:
f2fs_put_page(sum_page, 0);
}
- if (gc_type == FG_GC)
+ if (submitted)
f2fs_submit_merged_write(sbi,
(type == SUM_TYPE_NODE) ? NODE : DATA);
@@ -1172,7 +1222,8 @@ gc_more:
* threshold, we can make them free by checkpoint. Then, we
* secure free segments which doesn't need fggc any more.
*/
- if (prefree_segments(sbi)) {
+ if (prefree_segments(sbi) &&
+ !is_sbi_flag_set(sbi, SBI_CP_DISABLED)) {
ret = f2fs_write_checkpoint(sbi, &cpc);
if (ret)
goto stop;
@@ -1224,7 +1275,7 @@ gc_more:
segno = NULL_SEGNO;
goto gc_more;
}
- if (gc_type == FG_GC)
+ if (gc_type == FG_GC && !is_sbi_flag_set(sbi, SBI_CP_DISABLED))
ret = f2fs_write_checkpoint(sbi, &cpc);
}
stop:
@@ -1244,7 +1295,7 @@ stop:
put_gc_inode(&gc_list);
- if (sync)
+ if (sync && !ret)
ret = sec_freed ? 0 : -EAGAIN;
return ret;
}