static int prop_compression_validate(const struct btrfs_inode *inode,
const char *value, size_t len)
{
+ size_t type_len;
+ int type;
+
if (!value)
return 0;
+ if (memchr(value, '\0', len))
+ return -EINVAL;
- if (btrfs_compress_is_valid_type(value, len)) {
- if (!btrfs_inode_can_compress(inode))
- return -EINVAL;
+ if ((len == 2 && strncmp("no", value, 2) == 0) ||
+ (len == 4 && strncmp("none", value, 4) == 0))
return 0;
+
+ if (len >= 3 && strncmp("lzo", value, 3) == 0) {
+ type = BTRFS_COMPRESS_LZO;
+ type_len = 3;
+ } else if (len >= 4 && strncmp("zlib", value, 4) == 0) {
+ type = BTRFS_COMPRESS_ZLIB;
+ type_len = 4;
+ } else if (len >= 4 && strncmp("zstd", value, 4) == 0) {
+ type = BTRFS_COMPRESS_ZSTD;
+ type_len = 4;
+ } else {
+ return -EINVAL;
}
- if ((len == 2 && strncmp("no", value, 2) == 0) ||
- (len == 4 && strncmp("none", value, 4) == 0))
+ if (!btrfs_inode_can_compress(inode))
+ return -EINVAL;
+
+ if (len == type_len)
return 0;
+ /* Only a valid ":level" suffix may follow the algorithm name. */
+ if (value[type_len] == ':') {
+ char str[16];
+ size_t suffix_len = len - type_len;
+ int level;
+
+ if (suffix_len >= sizeof(str))
+ return -EINVAL;
+ memcpy(str, value + type_len, suffix_len);
+ str[suffix_len] = 0;
+ if (btrfs_compress_str2level(type, str, &level) == 0)
+ return 0;
+ }
+
return -EINVAL;
}