Commit 7c3ca183 authored by Gao Xiang's avatar Gao Xiang
Browse files

erofs: restrict pcluster size limitations



Error out if {en,de}encoded size of a pcluster is unsupported:
  Maximum supported encoded size (of a pcluster):  1 MiB
  Maximum supported decoded size (of a pcluster): 12 MiB

Users can still choose to use supported large configurations (e.g.,
for archival purposes), but there may be performance penalties in
low-memory scenarios compared to smaller pclusters.

Reviewed-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20240912074156.2925394-1-hsiangkao@linux.alibaba.com
parent 79f504a2
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -288,9 +288,12 @@ struct erofs_dirent {

#define EROFS_NAME_LEN      255

/* maximum supported size of a physical compression cluster */
/* maximum supported encoded size of a physical compressed cluster */
#define Z_EROFS_PCLUSTER_MAX_SIZE	(1024 * 1024)

/* maximum supported decoded size of a physical compressed cluster */
#define Z_EROFS_PCLUSTER_MAX_DSIZE	(12 * 1024 * 1024)

/* available compression algorithm types (for h_algorithmtype) */
enum {
	Z_EROFS_COMPRESSION_LZ4		= 0,
+20 −22
Original line number Diff line number Diff line
@@ -687,32 +687,30 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,
	int err = 0;

	trace_erofs_map_blocks_enter(inode, map, flags);

	/* when trying to read beyond EOF, leave it unmapped */
	if (map->m_la >= inode->i_size) {
	if (map->m_la >= inode->i_size) {	/* post-EOF unmapped extent */
		map->m_llen = map->m_la + 1 - inode->i_size;
		map->m_la = inode->i_size;
		map->m_flags = 0;
		goto out;
	}

	} else {
		err = z_erofs_fill_inode_lazy(inode);
	if (err)
		goto out;

		if (!err) {
			if ((vi->z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER) &&
			    !vi->z_tailextent_headlcn) {
				map->m_la = 0;
				map->m_llen = inode->i_size;
		map->m_flags = EROFS_MAP_MAPPED | EROFS_MAP_FULL_MAPPED |
				EROFS_MAP_FRAGMENT;
		goto out;
	}

				map->m_flags = EROFS_MAP_MAPPED |
					EROFS_MAP_FULL_MAPPED | EROFS_MAP_FRAGMENT;
			} else {
				err = z_erofs_do_map_blocks(inode, map, flags);
out:
			}
		}
		if (!err && (map->m_flags & EROFS_MAP_ENCODED) &&
		    unlikely(map->m_plen > Z_EROFS_PCLUSTER_MAX_SIZE ||
			     map->m_llen > Z_EROFS_PCLUSTER_MAX_DSIZE))
			err = -EOPNOTSUPP;
		if (err)
			map->m_llen = 0;
	}
	trace_erofs_map_blocks_exit(inode, map, flags, err);
	return err;
}