diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 40ac679ec56e..e2fe95de3d71 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -258,7 +258,7 @@ static struct dentry *nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, else nilfs_transaction_abort(dir->i_sb); - return ERR_PTR(err); + return err ? ERR_PTR(err) : NULL; out_fail: drop_nlink(inode); diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 1491a4d4b1e1..9332f5ac6083 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2512,12 +2512,33 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info ti; int err; + size_t i, nfreesegs = argv[4].v_nmembs; + __u64 *segnumv = kbufs[4]; if (unlikely(!sci)) return -EROFS; nilfs_transaction_lock(sb, &ti, 1); + /* + * Validate segment numbers under ns_segctor_sem (held for write + * by nilfs_transaction_lock above) so the check is serialized + * against nilfs_ioctl_resize(), which can modify ns_nsegments. + * Rejecting bad input here, before any segment-cleaning work + * begins, avoids the per-element diagnostic path inside + * nilfs_sufile_updatev() that would otherwise run under this + * same lock and stall concurrent readers. + */ + for (i = 0; i < nfreesegs; i++) { + if (segnumv[i] >= nilfs->ns_nsegments) { + nilfs_err(sb, + "Segment number %llu to be freed is out of range", + (unsigned long long)segnumv[i]); + err = -EINVAL; + goto bail_unlock; + } + } + err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat); if (unlikely(err)) goto out_unlock; @@ -2558,6 +2579,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, sci->sc_freesegs = NULL; sci->sc_nfreesegs = 0; nilfs_mdt_clear_shadow_map(nilfs->ns_dat); + bail_unlock: nilfs_transaction_unlock(sb); return err; } diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 7aa5ef8606cd..893a504cb80c 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -1070,8 +1070,6 @@ nilfs_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_time_gran = 1; sb->s_max_links = NILFS_LINK_MAX; - sb->s_bdi = bdi_get(sb->s_bdev->bd_disk->bdi); - err = load_nilfs(nilfs, sb); if (err) goto failed_nilfs;