/* * $Id: bulkstat_unlink_test.c,v 1.3 2007/10/30 03:07:42 mohamedb.longdrop.melbourne.sgi.com Exp $ * Test bulkstat doesn't returned unlinked inodes. * Mark Goodwin Fri Jul 20 09:13:57 EST 2007 */ #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { int e; int i; int j; int k; int nfiles; int stride; int c; struct stat sbuf; ino_t *inodelist; struct xfs_fsop_bulkreq a; struct xfs_bstat *ret; int iterations; char fname[MAXPATHLEN]; char *dirname; int chknb = 0; while ((c = getopt(argc, argv, "r")) != -1) { switch(c) { case 'r': chknb = 1; break; default: break; } } if ((argc - optind) != 4) { fprintf(stderr, "Usage: %s iterations nfiles stride dir [options]\n", argv[0]); fprintf(stderr, "Create dir with nfiles, unlink each stride'th file, sync, bulkstat\n"); exit(1); } iterations = atoi(argv[optind++]); nfiles = atoi(argv[optind++]); stride = atoi(argv[optind++]); dirname = argv[optind++]; if (chknb) printf("Runing extended checks.\n"); inodelist = (ino_t *)malloc(nfiles * sizeof(ino_t)); ret = (struct xfs_bstat *)malloc(nfiles * sizeof(struct xfs_bstat)); for (k=0; k < iterations; k++) { int fd[nfiles + 1]; xfs_ino_t last_inode = 0; int count = 0, scount = -1; printf("Iteration %d ... (%d files)", k, nfiles); memset(&a, 0, sizeof(struct xfs_fsop_bulkreq)); a.lastip = (__u64 *)&last_inode; a.icount = nfiles; a.ubuffer = ret; a.ocount = &count; if (mkdir(dirname, 0755) < 0) { printf("Warning (%s,%d), mkdir(%s) failed.\n", __FILE__, __LINE__, dirname); perror(dirname); exit(1); } if ((fd[nfiles] = open(dirname, O_RDONLY)) < 0) { printf("Warning (%s,%d), open(%s) failed.\n", __FILE__, __LINE__, dirname); perror(dirname); exit(1); } if (chknb) { /* Get the original number of inodes (lazy) */ sync(); if (xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a) != 0) { printf("Warning (%s:%d), xfsctl(XFS_IOC_FSBULKSTAT) FAILED.\n", __FILE__, __LINE__); } scount = count; } for (i=0; i < nfiles; i++) { /* Open the files */ sprintf(fname, "%s/file%06d", dirname, i); if ((fd[i] = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) { printf("Warning (%s,%d), open(%s) failed.\n", __FILE__, __LINE__, fname); perror(fname); exit(1); } write(fd[i], fname, sizeof(fname)); if (fstat(fd[i], &sbuf) < 0) { printf("Warning (%s,%d), fstat failed.\n", __FILE__, __LINE__); perror(fname); exit(1); } inodelist[i] = sbuf.st_ino; unlink(fname); } if (chknb) { /* *The files are still opened (but unlink()ed) , * we should have more inodes than before */ sync(); last_inode = 0; if (xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a) != 0) { printf("Warning (%s:%d), xfsctl(XFS_IOC_FSBULKSTAT) FAILED.\n", __FILE__, __LINE__); } if (count < scount) { printf("ERROR, count(%d) < scount(%d).\n", count, scount); return -1; } } /* Close all the files */ for (i = 0; i < nfiles; i++) { close(fd[i]); } if (chknb) { /* * The files are now closed, we should be back to our, * previous inode count */ sync(); last_inode = 0; if (xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a) != 0) { printf("Warning (%s:%d), xfsctl(XFS_IOC_FSBULKSTAT) FAILED.\n", __FILE__, __LINE__); } if (count != scount) { printf("ERROR, count(%d) != scount(%d).\n", count, scount); return -1; } } sync(); last_inode = 0; for (;;) { if ((e = xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a)) < 0) { printf("Warning (%s,%d), xfsctl failed.\n", __FILE__, __LINE__); perror("XFS_IOC_FSBULKSTAT:"); exit(1); } if (count == 0) break; for (i=0; i < count; i++) { for (j=0; j < nfiles; j += stride) { if (ret[i].bs_ino == inodelist[j]) { /* oops ... */ printf("failed. Unlinked inode %llu returned by bulkstat\n", (unsigned long long)inodelist[j]); exit(1); } } } } close(fd[nfiles]); sprintf(fname, "rm -rf %s\n", dirname); system(fname); sync(); sleep(2); printf("passed\n"); } exit(0); }