// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2021 Oracle. All Rights Reserved. * Author: Darrick J. Wong * * Regression test for failing to undo delalloc quota reservations when * changing project id and we fail some other FSSETXATTR validation. */ #include #include #include #include #include #include #include #include #include #include "global.h" static char zerobuf[65536]; int main( int argc, char *argv[]) { struct fsxattr fa; ssize_t sz; int fd, ret; if (argc < 2) { printf("Usage: %s filename\n", argv[0]); return 1; } fd = open(argv[1], O_CREAT | O_TRUNC | O_RDWR, 0600); if (fd < 0) { perror(argv[1]); return 2; } /* Zero the project id and the extent size hint. */ ret = ioctl(fd, FS_IOC_FSGETXATTR, &fa); if (ret) { perror("FSGETXATTR check file"); return 2; } if (fa.fsx_projid != 0 || fa.fsx_extsize != 0) { fa.fsx_projid = 0; fa.fsx_extsize = 0; ret = ioctl(fd, FS_IOC_FSSETXATTR, &fa); if (ret) { perror("FSSETXATTR zeroing"); return 2; } } /* Dirty a few kb of a file to create delalloc extents. */ sz = write(fd, zerobuf, sizeof(zerobuf)); if (sz != sizeof(zerobuf)) { perror("delalloc write"); return 2; } /* * The regression we're trying to test happens when the fsxattr input * validation decides to bail out after the chown quota reservation has * been made on a file containing delalloc extents. Extent size hints * can't be set on non-empty files and we can't check the value until * we've reserved resources and taken the file's ILOCK, so this is a * perfect vector for triggering this condition. In this way we set up * a FSSETXATTR call that will fail. */ ret = ioctl(fd, FS_IOC_FSGETXATTR, &fa); if (ret) { perror("FSGETXATTR"); return 2; } fa.fsx_projid = 23652; fa.fsx_extsize = 2; fa.fsx_xflags |= FS_XFLAG_EXTSIZE; ret = ioctl(fd, FS_IOC_FSSETXATTR, &fa); if (ret) { printf("FSSETXATTRR should fail: %s\n", strerror(errno)); return 0; } /* Uhoh, that FSSETXATTR call should have failed! */ return 3; }