]> www.infradead.org Git - users/sagi/blktests.git/commitdiff
loop: test LO_FLAGS_BLOCKSIZE
authorOmar Sandoval <osandov@fb.com>
Fri, 18 Aug 2017 06:22:22 +0000 (23:22 -0700)
committerOmar Sandoval <osandov@fb.com>
Fri, 18 Aug 2017 06:22:22 +0000 (23:22 -0700)
Signed-off-by: Omar Sandoval <osandov@fb.com>
src/.gitignore
src/Makefile
src/loblksize.c [new file with mode: 0644]
tests/loop/002 [new file with mode: 0755]
tests/loop/002.out [new file with mode: 0644]

index 0fca08a74fb1f4e7c94a6893be94f7be4c106e19..216094576851b283f8ab5d98c525bd58bc2c7b2c 100644 (file)
@@ -1,2 +1,3 @@
+/loblksize
 /sg/syzkaller1
 /sg/dxfer-from-dev
index c0d7fd3a7e305fafd5dd93856be13d00460711f8..9415baedabfbb10f675a429a8eef608abf2a7c32 100644 (file)
@@ -1,4 +1,4 @@
-TARGETS := sg/dxfer-from-dev sg/syzkaller1
+TARGETS := sg/dxfer-from-dev sg/syzkaller1 loblksize
 
 CFLAGS := -O2
 
diff --git a/src/loblksize.c b/src/loblksize.c
new file mode 100644 (file)
index 0000000..45d9939
--- /dev/null
@@ -0,0 +1,73 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <linux/loop.h>
+
+/* LO_FLAGS_BLOCKSIZE is an enum so we can't ifdef. */
+#define LO_FLAGS_BLOCKSIZE_ 32
+
+#ifndef LO_INFO_BLOCKSIZE
+#define LO_INFO_BLOCKSIZE(l) (l)->lo_init[0]
+#endif
+
+int main(int argc, char **argv)
+{
+       struct loop_info64 lo;
+       unsigned long long blksize;
+       char *end;
+       int fd = -1;
+       bool set = argc >= 3;
+       int status = EXIT_FAILURE;
+
+       if (argc != 2 && argc != 3) {
+               fprintf(stderr, "usage: %s DEV [BLKSIZE]\n", argv[0]);
+               return EXIT_FAILURE;
+       }
+
+       if (set) {
+               errno = 0;
+               blksize = strtoull(argv[2], &end, 0);
+               if (errno || *end) {
+                       fprintf(stderr, "invalid block size\n");
+                       return EXIT_FAILURE;
+               }
+       }
+
+       fd = open(argv[1], O_RDONLY);
+       if (fd == -1) {
+               perror("open");
+               return EXIT_FAILURE;
+       }
+
+       if (ioctl(fd, LOOP_GET_STATUS64, &lo) == -1) {
+               perror("LOOP_GET_STATUS64");
+               goto out;
+       }
+
+       if (!(lo.lo_flags & LO_FLAGS_BLOCKSIZE_)) {
+               fprintf(stderr, "LO_FLAGS_BLOCKSIZE not supported");
+               goto out;
+       }
+
+       if (set) {
+               lo.lo_flags |= LO_FLAGS_BLOCKSIZE_;
+               LO_INFO_BLOCKSIZE(&lo) = blksize;
+               if (ioctl(fd, LOOP_SET_STATUS64, &lo) == -1) {
+                       perror("LOOP_SET_STATUS64");
+                       goto out;
+               }
+       } else {
+               printf("%llu\n", LO_INFO_BLOCKSIZE(&lo));
+       }
+
+       status = EXIT_SUCCESS;
+out:
+       close(fd);
+       return status;
+}
diff --git a/tests/loop/002 b/tests/loop/002
new file mode 100755 (executable)
index 0000000..be9965c
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# Tests the LO_FLAGS_BLOCKSIZE flag for LOOP_{GET,SET}_STATUS, introduced in
+# commit f2c6df7dbf9a ("loop: support 4k physical blocksize"). Also a
+# regression test for patches "loop: always return block size in
+# LOOP_GET_STATUS" and "loop: fix hang if LOOP_SET_STATUS gets invalid
+# blocksize or encrypt type".
+#
+# Copyright (C) 2017 Omar Sandoval
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+DESCRIPTION="try various loop device block sizes"
+QUICK=1
+
+requires() {
+       local tmpfile loop_dev
+
+       if ! _have_src_program loblksize; then
+               return 1
+       fi
+
+       # XXX: $TMPDIR isn't set up for requires(), should it be?
+       if ! tmpfile="$(mktemp "blktests.${TEST_NAME//\//.}.XXX")" ||
+          ! truncate -s 1M "$tmpfile"; then
+               SKIP_REASON="could not create temporary file"
+               return 1
+       fi
+
+       if ! loop_dev="$(losetup -f --show "$tmpfile" 2>/dev/null)"; then
+               SKIP_REASON="could not get loop device"
+               rm -f "$tmpfile"
+               return 1
+       fi
+
+       if ! src/loblksize "$loop_dev" >/dev/null 2>&1; then
+               SKIP_REASON="kernel does not support LO_FLAGS_BLOCKSIZE"
+               losetup -d "$loop_dev"
+               rm -f "$tmpfile"
+               return 1
+       fi
+
+       losetup -d "$loop_dev"
+       rm -f "$tmpfile"
+       return 0
+}
+
+test() {
+       local loop_dev
+       echo "Running ${TEST_NAME}"
+
+       truncate -s 1M "$TMPDIR/file"
+       if ! loop_dev="$(losetup -f --show "$TMPDIR/file")"; then
+               return 1
+       fi
+
+       for blksize in "" 4096 2048 1234 1024 512; do
+               if [[ -z $blksize ]]; then
+                       echo "Checking default block size"
+               else
+                       echo "Setting block size to $blksize"
+                       if src/loblksize "$loop_dev" "$blksize"; then
+                               dd if=/dev/zero of="$loop_dev" oflag=direct bs="$blksize" count=1 status=none
+                       fi
+               fi
+               echo "LOOP_GET_STATUS says" "$(src/loblksize "$loop_dev")"
+               echo "sysfs says" "$(cat "/sys/block/${loop_dev#/dev/}/queue/logical_block_size")"
+       done
+
+       losetup -d "$loop_dev"
+
+       echo "Test complete"
+}
diff --git a/tests/loop/002.out b/tests/loop/002.out
new file mode 100644 (file)
index 0000000..f7f9605
--- /dev/null
@@ -0,0 +1,21 @@
+Running loop/002
+Checking default block size
+LOOP_GET_STATUS says 512
+sysfs says 512
+Setting block size to 4096
+LOOP_GET_STATUS says 4096
+sysfs says 4096
+Setting block size to 2048
+LOOP_GET_STATUS says 2048
+sysfs says 2048
+Setting block size to 1234
+LOOP_SET_STATUS64: Invalid argument
+LOOP_GET_STATUS says 2048
+sysfs says 2048
+Setting block size to 1024
+LOOP_GET_STATUS says 1024
+sysfs says 1024
+Setting block size to 512
+LOOP_GET_STATUS says 512
+sysfs says 512
+Test complete