Skip to content

Commit

Permalink
f2fs: fix iostat related lock protection
Browse files Browse the repository at this point in the history
commit 61803e9 upstream.

Made iostat related locks safe to be called from irq context again.

Cc: <stable@vger.kernel.org>
Fixes: a1e09b0 ("f2fs: use iomap for direct I/O")
Signed-off-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Stanley Chu <stanley.chu@mediatek.com>
Tested-by: Eddie Huang <eddie.huang@mediatek.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Daeho Jeong authored and gregkh committed Jun 29, 2022
1 parent 204afc1 commit 15f639f
Showing 1 changed file with 18 additions and 13 deletions.
31 changes: 18 additions & 13 deletions fs/f2fs/iostat.c
Expand Up @@ -91,8 +91,9 @@ static inline void __record_iostat_latency(struct f2fs_sb_info *sbi)
unsigned int cnt;
struct f2fs_iostat_latency iostat_lat[MAX_IO_TYPE][NR_PAGE_TYPE];
struct iostat_lat_info *io_lat = sbi->iostat_io_lat;
unsigned long flags;

spin_lock_bh(&sbi->iostat_lat_lock);
spin_lock_irqsave(&sbi->iostat_lat_lock, flags);
for (idx = 0; idx < MAX_IO_TYPE; idx++) {
for (io = 0; io < NR_PAGE_TYPE; io++) {
cnt = io_lat->bio_cnt[idx][io];
Expand All @@ -106,7 +107,7 @@ static inline void __record_iostat_latency(struct f2fs_sb_info *sbi)
io_lat->bio_cnt[idx][io] = 0;
}
}
spin_unlock_bh(&sbi->iostat_lat_lock);
spin_unlock_irqrestore(&sbi->iostat_lat_lock, flags);

trace_f2fs_iostat_latency(sbi, iostat_lat);
}
Expand All @@ -115,14 +116,15 @@ static inline void f2fs_record_iostat(struct f2fs_sb_info *sbi)
{
unsigned long long iostat_diff[NR_IO_TYPE];
int i;
unsigned long flags;

if (time_is_after_jiffies(sbi->iostat_next_period))
return;

/* Need double check under the lock */
spin_lock_bh(&sbi->iostat_lock);
spin_lock_irqsave(&sbi->iostat_lock, flags);
if (time_is_after_jiffies(sbi->iostat_next_period)) {
spin_unlock_bh(&sbi->iostat_lock);
spin_unlock_irqrestore(&sbi->iostat_lock, flags);
return;
}
sbi->iostat_next_period = jiffies +
Expand All @@ -133,7 +135,7 @@ static inline void f2fs_record_iostat(struct f2fs_sb_info *sbi)
sbi->prev_rw_iostat[i];
sbi->prev_rw_iostat[i] = sbi->rw_iostat[i];
}
spin_unlock_bh(&sbi->iostat_lock);
spin_unlock_irqrestore(&sbi->iostat_lock, flags);

trace_f2fs_iostat(sbi, iostat_diff);

Expand All @@ -145,25 +147,27 @@ void f2fs_reset_iostat(struct f2fs_sb_info *sbi)
struct iostat_lat_info *io_lat = sbi->iostat_io_lat;
int i;

spin_lock_bh(&sbi->iostat_lock);
spin_lock_irq(&sbi->iostat_lock);
for (i = 0; i < NR_IO_TYPE; i++) {
sbi->rw_iostat[i] = 0;
sbi->prev_rw_iostat[i] = 0;
}
spin_unlock_bh(&sbi->iostat_lock);
spin_unlock_irq(&sbi->iostat_lock);

spin_lock_bh(&sbi->iostat_lat_lock);
spin_lock_irq(&sbi->iostat_lat_lock);
memset(io_lat, 0, sizeof(struct iostat_lat_info));
spin_unlock_bh(&sbi->iostat_lat_lock);
spin_unlock_irq(&sbi->iostat_lat_lock);
}

void f2fs_update_iostat(struct f2fs_sb_info *sbi,
enum iostat_type type, unsigned long long io_bytes)
{
unsigned long flags;

if (!sbi->iostat_enable)
return;

spin_lock_bh(&sbi->iostat_lock);
spin_lock_irqsave(&sbi->iostat_lock, flags);
sbi->rw_iostat[type] += io_bytes;

if (type == APP_BUFFERED_IO || type == APP_DIRECT_IO)
Expand All @@ -172,7 +176,7 @@ void f2fs_update_iostat(struct f2fs_sb_info *sbi,
if (type == APP_BUFFERED_READ_IO || type == APP_DIRECT_READ_IO)
sbi->rw_iostat[APP_READ_IO] += io_bytes;

spin_unlock_bh(&sbi->iostat_lock);
spin_unlock_irqrestore(&sbi->iostat_lock, flags);

f2fs_record_iostat(sbi);
}
Expand All @@ -185,6 +189,7 @@ static inline void __update_iostat_latency(struct bio_iostat_ctx *iostat_ctx,
struct f2fs_sb_info *sbi = iostat_ctx->sbi;
struct iostat_lat_info *io_lat = sbi->iostat_io_lat;
int idx;
unsigned long flags;

if (!sbi->iostat_enable)
return;
Expand All @@ -202,12 +207,12 @@ static inline void __update_iostat_latency(struct bio_iostat_ctx *iostat_ctx,
idx = WRITE_ASYNC_IO;
}

spin_lock_bh(&sbi->iostat_lat_lock);
spin_lock_irqsave(&sbi->iostat_lat_lock, flags);
io_lat->sum_lat[idx][iotype] += ts_diff;
io_lat->bio_cnt[idx][iotype]++;
if (ts_diff > io_lat->peak_lat[idx][iotype])
io_lat->peak_lat[idx][iotype] = ts_diff;
spin_unlock_bh(&sbi->iostat_lat_lock);
spin_unlock_irqrestore(&sbi->iostat_lat_lock, flags);
}

void iostat_update_and_unbind_ctx(struct bio *bio, int rw)
Expand Down

0 comments on commit 15f639f

Please sign in to comment.