--- /dev/null
+#! /bin/sh
+# FS QA Test No. 177
+#
+# Test to reproduce PV#: 964316
+# Check sync reclaims and flushes unlinked inodes to their buffers.
+#-----------------------------------------------------------------------
+# Copyright (c) 2007 Silicon Graphics, Inc. All Rights Reserved.
+#-----------------------------------------------------------------------
+#
+# creator
+owner=mohamedb@sgi.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1 # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+ cd /
+ rm -f $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# real QA test starts here
+
+# Modify as appropriate.
+_supported_fs xfs
+_supported_os Linux
+
+# Setup Filesystem
+_require_scratch
+_scratch_mkfs_xfs >/dev/null 2>&1 \
+ || _fail "mkfs failed"
+
+_scratch_mount \
+ || _fail "mount failed"
+
+# run Mark Goodwin test here
+# Usage: ./bulkstat_unlink_test iterations nfiles stride dir
+# Create dir with nfiles, unlink each stride'th file, sync, bulkstat
+$here/src/bulkstat_unlink_test 50 100 1 $SCRATCH_MNT/bulkstat
+$here/src/bulkstat_unlink_test 10 1000 1 $SCRATCH_MNT/bulkstat
+$here/src/bulkstat_unlink_test 50 100 6 $SCRATCH_MNT/bulkstat
+$here/src/bulkstat_unlink_test 50 1000 3 $SCRATCH_MNT/bulkstat
+
+# success, all done
+status=0
+exit
--- /dev/null
+/*
+ * $Id: bulkstat_unlink_test.c,v 1.1 2007/07/24 16:08:02 mohamedb.longdrop.melbourne.sgi.com Exp $
+ * Test bulkstat doesn't returned unlinked inodes.
+ * Mark Goodwin <markgw@sgi.com> Fri Jul 20 09:13:57 EST 2007
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <xfs/xfs.h>
+#include <unistd.h>
+
+int
+main(int argc, char *argv[])
+{
+ int e;
+ int fd;
+ int i;
+ int j;
+ int k;
+ int nfiles;
+ int stride;
+ struct stat sbuf;
+ ino_t *inodelist;
+ xfs_fsop_bulkreq_t a;
+ xfs_bstat_t *ret;
+ int iterations;
+ char fname[MAXPATHLEN];
+ char *dirname;
+
+ if (argc != 5) {
+ fprintf(stderr, "Usage: %s iterations nfiles stride dir\n", argv[0]);
+ fprintf(stderr, "Create dir with nfiles, unlink each stride'th file, sync, bulkstat\n");
+ exit(1);
+ }
+
+ iterations = atoi(argv[1]);
+ nfiles = atoi(argv[2]);
+ stride = atoi(argv[3]);
+ dirname = argv[4];
+
+ inodelist = (ino_t *)malloc(nfiles * sizeof(ino_t));
+ ret = (xfs_bstat_t *)malloc(nfiles * sizeof(xfs_bstat_t));
+
+ for (k=0; k < iterations; k++) {
+ xfs_ino_t last_inode = 0;
+ int count = 0;
+
+ printf("Iteration %d ... ", k);
+
+ memset(&a, 0, sizeof(xfs_fsop_bulkreq_t));
+ a.lastip = &last_inode;
+ a.icount = nfiles;
+ a.ubuffer = ret;
+ a.ocount = &count;
+
+ if (mkdir(dirname, 0755) < 0) {
+ perror(dirname);
+ exit(1);
+ }
+
+ for (i=0; i < nfiles; i++) {
+ sprintf(fname, "%s/file%06d", dirname, i);
+ if ((fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
+ perror(fname);
+ exit(1);
+ }
+ write(fd, fname, sizeof(fname));
+ if (fstat(fd, &sbuf) < 0) {
+ perror(fname);
+ exit(1);
+ }
+ inodelist[i] = sbuf.st_ino;
+ close(fd);
+ }
+
+ if ((fd = open(dirname, O_RDONLY)) < 0) {
+ perror(dirname);
+ exit(1);
+ }
+
+ /*
+ * test begins here
+ */
+ for (i=0; i < nfiles; i += stride) {
+ sprintf(fname, "%s/file%06d", dirname, i);
+ if (unlink(fname) < 0) {
+ perror(fname);
+ exit(1);
+ }
+ }
+
+ sync();
+
+ for (;;) {
+ if ((e = xfsctl(dirname, fd, XFS_IOC_FSBULKSTAT, &a)) < 0) {
+ 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 %ld returned by bulkstat\n", inodelist[j]);
+ exit(1);
+ }
+ }
+ }
+ }
+
+ close(fd);
+ sprintf(fname, "rm -rf %s\n", dirname);
+ system(fname);
+
+ sync();
+ sleep(2);
+ printf("passed\n");
+ }
+
+ exit(0);
+}