From: Darrick J. Wong All current users of the iomap swapfile activation mechanism are block device filesystems. This means that claim_swapfile will set swap_info_struct::bdev to inode->i_sb->s_bdev of the swap file. However, in the future there could be fuse+iomap filesystems that are block device based but don't set s_bdev. In this case, sis::bdev will be set to NULL when we enter iomap_swapfile_activate, and we can pick up a bdev from the first iomap mapping that the filesystem provides. To make this work robustly, we must explicitly check that each mapping provides a bdev and that there's no way we can succeed at collecting swapfile pages without a block device. Signed-off-by: "Darrick J. Wong" --- fs/iomap/swapfile.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fs/iomap/swapfile.c b/fs/iomap/swapfile.c index 0db77c449467a7..9d9f4e84437df5 100644 --- a/fs/iomap/swapfile.c +++ b/fs/iomap/swapfile.c @@ -112,6 +112,13 @@ static int iomap_swapfile_iter(struct iomap_iter *iter, if (iomap->flags & IOMAP_F_SHARED) return iomap_swapfile_fail(isi, "has shared extents"); + /* Swapfiles must be backed by a block device */ + if (!iomap->bdev) + return iomap_swapfile_fail(isi, "is not on a block device"); + + if (iter->pos == 0 && !isi->sis->bdev) + isi->sis->bdev = iomap->bdev; + /* Only one bdev per swap file. */ if (iomap->bdev != isi->sis->bdev) return iomap_swapfile_fail(isi, "outside the main device"); @@ -184,6 +191,16 @@ int iomap_swapfile_activate(struct swap_info_struct *sis, return -EINVAL; } + /* + * If this swapfile doesn't have a block device, reject this useless + * swapfile to prevent confusion later on. + */ + if (sis->bdev == NULL) { + pr_warn( + "swapon: No block device for swap file but usage pages?!\n"); + return -EINVAL; + } + *pagespan = 1 + isi.highest_ppage - isi.lowest_ppage; sis->max = isi.nr_pages; sis->pages = isi.nr_pages - 1;