From 5a980196ab7a8a4291c18effc5054fa6198a24a2 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 3 Dec 2021 11:07:02 +0100 Subject: [PATCH] basic: Make sure we're extra paranoid in chattr_full On btrfs, trying to disable FS_NOCOW_FL on a file that has data already written will fail silently without reporting an error. To catch such cases, let's query the flags again if the IOC_SETFLAGS ioctl() succeeds to make sure the flags we tried to configure we're actually accepted by the kernel. --- src/basic/chattr-util.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c index 59707a79c0..807288a649 100644 --- a/src/basic/chattr-util.c +++ b/src/basic/chattr-util.c @@ -59,11 +59,25 @@ int chattr_full(const char *path, } if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) >= 0) { - if (ret_previous) - *ret_previous = old_attr; - if (ret_final) - *ret_final = new_attr; - return 1; + unsigned attr; + + /* Some filesystems (BTRFS) silently fail when a flag cannot be set. Let's make sure our + * changes actually went through by querying the flags again and verifying they're equal to + * the flags we tried to configure. */ + + if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0) + return -errno; + + if (new_attr == attr) { + if (ret_previous) + *ret_previous = old_attr; + if (ret_final) + *ret_final = new_attr; + return 1; + } + + /* Trigger the fallback logic. */ + errno = EINVAL; } if ((errno != EINVAL && !ERRNO_IS_NOT_SUPPORTED(errno)) || -- 2.25.1