// SPDX-License-Identifier: GPL-2.0+ /* * stale_handle.c - attempt to create a stale handle and open it * Copyright (C) 2010 Red Hat, Inc. All Rights reserved. */ #define TEST_UTIME #include #include #include #include #include #include #include #include #include #include #define NUMFILES 1024 int main(int argc, char **argv) { int i; int fd; int ret; int failed = 0; char fname[MAXPATHLEN]; char *test_dir; void *handle[NUMFILES]; size_t hlen[NUMFILES]; char fshandle[256]; size_t fshlen; struct stat st; if (argc != 2) { fprintf(stderr, "usage: stale_handle test_dir\n"); return EXIT_FAILURE; } test_dir = argv[1]; if (stat(test_dir, &st) != 0) { perror("stat"); return EXIT_FAILURE; } ret = path_to_fshandle(test_dir, (void **)fshandle, &fshlen); if (ret < 0) { perror("path_to_fshandle"); return EXIT_FAILURE; } /* * create a large number of files to force allocation of new inode * chunks on disk. */ for (i=0; i < NUMFILES; i++) { sprintf(fname, "%s/file%06d", test_dir, i); fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644); if (fd < 0) { printf("Warning (%s,%d), open(%s) failed.\n", __FILE__, __LINE__, fname); perror(fname); return EXIT_FAILURE; } close(fd); } /* sync to get the new inodes to hit the disk */ sync(); /* create the handles */ for (i=0; i < NUMFILES; i++) { sprintf(fname, "%s/file%06d", test_dir, i); ret = path_to_handle(fname, &handle[i], &hlen[i]); if (ret < 0) { perror("path_to_handle"); return EXIT_FAILURE; } } /* unlink the files */ for (i=0; i < NUMFILES; i++) { sprintf(fname, "%s/file%06d", test_dir, i); ret = unlink(fname); if (ret < 0) { perror("unlink"); return EXIT_FAILURE; } } /* sync to get log forced for unlink transactions to hit the disk */ sync(); /* sync once more FTW */ sync(); /* * now drop the caches so that unlinked inodes are reclaimed and * buftarg page cache is emptied so that the inode cluster has to be * fetched from disk again for the open_by_handle() call. */ system("echo 3 > /proc/sys/vm/drop_caches"); /* * now try to open the files by the stored handles. Expecting ENOENT * for all of them. */ for (i=0; i < NUMFILES; i++) { errno = 0; fd = open_by_handle(handle[i], hlen[i], O_RDWR); if (fd < 0 && (errno == ENOENT || errno == ESTALE)) { free_handle(handle[i], hlen[i]); continue; } if (fd >= 0) { printf("open_by_handle(%d) opened an unlinked file!\n", i); close(fd); } else printf("open_by_handle(%d) returned %d incorrectly on an unlinked file!\n", i, errno); free_handle(handle[i], hlen[i]); failed++; } if (failed) return EXIT_FAILURE; return EXIT_SUCCESS; }