+void
+do_zero_range(unsigned int offset, unsigned int length)
+{
+ unsigned int end_offset;
+ int mode = FALLOC_FL_ZERO_RANGE;
+ int keep_size;
+ int fd;
+
+ tf = get_tf();
+ fd = tf->fd;
+ if (length == 0) {
+ if (!quiet && testcalls > simulatedopcount) {
+ prt("skipping zero length zero range\n");
+ log4(OP_SKIPPED, OP_ZERO_RANGE, offset, length);
+ }
+ return;
+ }
+
+ keep_size = random() % 2;
+
+ end_offset = keep_size ? 0 : offset + length;
+
+ if (end_offset > biggest) {
+ biggest = end_offset;
+ if (!quiet && testcalls > simulatedopcount)
+ prt("zero_range to largest ever: 0x%x\n", end_offset);
+ }
+
+ /*
+ * last arg matches fallocate string array index in logdump:
+ * 0: allocate past EOF
+ * 1: extending prealloc
+ * 2: interior prealloc
+ */
+ log4(OP_ZERO_RANGE, offset, length,
+ (end_offset > file_size) ? (keep_size ? 0 : 1) : 2);
+
+ if (testcalls <= simulatedopcount)
+ return;
+
+ output_line(tf, OP_TRUNCATE, offset, length);
+
+ if (fallocate(fd, mode, (loff_t)offset, (loff_t)length) == -1) {
+ prt("pzero range: %x to %x\n", offset, length);
+ prterr("fallocate");
+ report_failure(161);
+ }
+ output_debug(offset, length, "zero_range done");
+
+ memset(good_buf + offset, '\0', length);
+}
+
+/*
+ * fallocate is basically a no-op unless extending,
+ * then a lot like a truncate
+ */
+void
+do_preallocate(unsigned int offset, unsigned int length)
+{
+ off_t end_offset;
+ off_t new_offset;
+ int keep_size;
+ int fd;
+ struct stat statbufs;
+
+ tf = get_tf();
+ fd = tf->fd;
+ if (length == 0) {
+ if (!quiet && testcalls > simulatedopcount)
+ prt("skipping zero length fallocate\n");
+ log4(OP_SKIPPED, OP_FALLOCATE, offset, length);
+ return;
+ }
+
+ keep_size = fl_keep_size && (random() % 2);
+
+ end_offset = keep_size ? 0 : offset + length;
+
+ if (end_offset > biggest) {
+ biggest = end_offset;
+ if (!quiet && testcalls > simulatedopcount)
+ prt("fallocating to largest ever: 0x%jx\n", end_offset);
+ }
+
+ /*
+ * last arg matches fallocate string array index in logdump:
+ * 0: allocate past EOF
+ * 1: extending prealloc
+ * 2: interior prealloc
+ */
+ log4(OP_FALLOCATE, offset, length, (end_offset > file_size) ?
+ (keep_size ? 0 : 1) : 2);
+
+ if (end_offset > file_size) {
+ memset(good_buf + file_size, '\0', end_offset - file_size);
+ file_size = end_offset;
+ } else {
+ new_offset = file_size - (offset + length);
+ length = length + new_offset;
+ }
+
+ if (testcalls <= simulatedopcount)
+ return;
+
+ fstat(fd, &statbufs);
+ if (fallocate(fd, keep_size ? FALLOC_FL_KEEP_SIZE : 0, (loff_t)offset,
+ (loff_t)length) == -1) {
+ prt("fallocate: %x to %x\n", offset, length);
+ prterr("fallocate");
+ report_failure(161);
+ }
+ output_line(tf, OP_FALLOCATE, offset, length);
+ output_debug(offset, length, "fallocate done");
+}