mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
nilfs2: do not propagate ENOENT error from sufile during GC
nilfs_sufile_freev(), which is used to free segments in GC, aborts with -ENOENT if the target segment usage is on a hole block. This error only occurs if one of the segment numbers to be freed passed by the GC ioctl is invalid, so return -EINVAL instead. To avoid impairing readability, introduce a wrapper function that encapsulates error handling including the error code conversion (and error message output). Link: https://lkml.kernel.org/r/20240821154627.11848-5-konishi.ryusuke@gmail.com Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
5b527d3864
commit
0b9aad46c1
@ -1102,12 +1102,64 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci,
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* nilfs_free_segments - free the segments given by an array of segment numbers
|
||||
* @nilfs: nilfs object
|
||||
* @segnumv: array of segment numbers to be freed
|
||||
* @nsegs: number of segments to be freed in @segnumv
|
||||
*
|
||||
* nilfs_free_segments() wraps nilfs_sufile_freev() and
|
||||
* nilfs_sufile_cancel_freev(), and edits the segment usage metadata file
|
||||
* (sufile) to free all segments given by @segnumv and @nsegs at once. If
|
||||
* it fails midway, it cancels the changes so that none of the segments are
|
||||
* freed. If @nsegs is 0, this function does nothing.
|
||||
*
|
||||
* The freeing of segments is not finalized until the writing of a log with
|
||||
* a super root block containing this sufile change is complete, and it can
|
||||
* be canceled with nilfs_sufile_cancel_freev() until then.
|
||||
*
|
||||
* Return: 0 on success, or the following negative error code on failure.
|
||||
* * %-EINVAL - Invalid segment number.
|
||||
* * %-EIO - I/O error (including metadata corruption).
|
||||
* * %-ENOMEM - Insufficient memory available.
|
||||
*/
|
||||
static int nilfs_free_segments(struct the_nilfs *nilfs, __u64 *segnumv,
|
||||
size_t nsegs)
|
||||
{
|
||||
size_t ndone;
|
||||
int ret;
|
||||
|
||||
if (!nsegs)
|
||||
return 0;
|
||||
|
||||
ret = nilfs_sufile_freev(nilfs->ns_sufile, segnumv, nsegs, &ndone);
|
||||
if (unlikely(ret)) {
|
||||
nilfs_sufile_cancel_freev(nilfs->ns_sufile, segnumv, ndone,
|
||||
NULL);
|
||||
/*
|
||||
* If a segment usage of the segments to be freed is in a
|
||||
* hole block, nilfs_sufile_freev() will return -ENOENT.
|
||||
* In this case, -EINVAL should be returned to the caller
|
||||
* since there is something wrong with the given segment
|
||||
* number array. This error can only occur during GC, so
|
||||
* there is no need to worry about it propagating to other
|
||||
* callers (such as fsync).
|
||||
*/
|
||||
if (ret == -ENOENT) {
|
||||
nilfs_err(nilfs->ns_sb,
|
||||
"The segment usage entry %llu to be freed is invalid (in a hole)",
|
||||
(unsigned long long)segnumv[ndone]);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
|
||||
{
|
||||
struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
|
||||
struct list_head *head;
|
||||
struct nilfs_inode_info *ii;
|
||||
size_t ndone;
|
||||
int err = 0;
|
||||
|
||||
switch (nilfs_sc_cstage_get(sci)) {
|
||||
@ -1201,14 +1253,10 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
|
||||
nilfs_sc_cstage_inc(sci);
|
||||
fallthrough;
|
||||
case NILFS_ST_SUFILE:
|
||||
err = nilfs_sufile_freev(nilfs->ns_sufile, sci->sc_freesegs,
|
||||
sci->sc_nfreesegs, &ndone);
|
||||
if (unlikely(err)) {
|
||||
nilfs_sufile_cancel_freev(nilfs->ns_sufile,
|
||||
sci->sc_freesegs, ndone,
|
||||
NULL);
|
||||
err = nilfs_free_segments(nilfs, sci->sc_freesegs,
|
||||
sci->sc_nfreesegs);
|
||||
if (unlikely(err))
|
||||
break;
|
||||
}
|
||||
sci->sc_stage.flags |= NILFS_CF_SUFREED;
|
||||
|
||||
err = nilfs_segctor_scan_file(sci, nilfs->ns_sufile,
|
||||
|
Loading…
Reference in New Issue
Block a user