Commit
f37c563bab42 ("btrfs: add missing check for nocow and compression
inode flags") added conflict checks for certain inode flag combinations,
and commit
0e852ab8974c ("btrfs: do not allow compression on nodatacow
files") extended the same logic to xattrs.
Both commits also forbade the combination of FS_NOCOW_FL (NODATACOW)
and FS_NOCOMP_FL (NOCOMPRESS). This restriction is undocumented, has
no technical basis, and provides no benefit. NODATACOW files cannot be
compressed in any case, so the NOCOMPRESS bit is a no-op: behavior is
the same whether the flag is present or not.
Forcing an unnecessary conflict makes inode flags harder to use.
Portable applications may inherit COMPRESS, NOCOMPRESS, or NODATACOW bits
from parent directories and combine them with unrelated flags such as
IMMUTABLE or NOATIME. Rejecting otherwise valid flag sets with EINVAL
creates surprises for applications that do not know about btrfs-specific
interactions and only touch the flags they care about.
Fix by permitting the combination of NODATACOW and NOCOMPRESS, both via
FS_IOC_SETFLAGS and by setting btrfs.compression to "no"/"none" through
xattrs.
Fixes: f37c563bab42 ("btrfs: add missing check for nocow and compression inode flags")
Fixes: 0e852ab8974c ("btrfs: do not allow compression on nodatacow files")
Signed-off-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
* are not changed.
*/
if ((inode_flags & BTRFS_INODE_NODATACOW) &&
- (fsflags & (FS_COMPR_FL | FS_NOCOMP_FL))) {
+ (fsflags & FS_COMPR_FL)) {
old_fsflags = btrfs_inode_flags_to_fsflags(inode);
- if ((old_fsflags & (FS_NOCOW_FL | FS_COMPR_FL | FS_NOCOMP_FL)) !=
- (fsflags & (FS_NOCOW_FL | FS_COMPR_FL | FS_NOCOMP_FL)))
+ if ((old_fsflags & (FS_NOCOW_FL | FS_COMPR_FL)) !=
+ (fsflags & (FS_NOCOW_FL | FS_COMPR_FL)))
return -EINVAL;
}
} else {
static int prop_compression_validate(const struct btrfs_inode *inode,
const char *value, size_t len)
{
- if (!btrfs_inode_can_compress(inode))
- return -EINVAL;
-
if (!value)
return 0;
- if (btrfs_compress_is_valid_type(value, len))
+ if (btrfs_compress_is_valid_type(value, len)) {
+ if (!btrfs_inode_can_compress(inode))
+ return -EINVAL;
return 0;
+ }
if ((len == 2 && strncmp("no", value, 2) == 0) ||
(len == 4 && strncmp("none", value, 4) == 0))