Skip to contentSkip to conversation

lib: make the loop device size can be increased

PATCH New Li Wang 2 participants 2 messages Sep 27, 2016 Library code

lore
Share & tools
lore

Li Wang

author
#0 lore raw

PATCH v6 1/1 lib: make the loop device size can be increased

For the purpose of satisfying specific requirements, here rename function tst_acqurire_device() to tst_acqurie_device_(), then add parameter '@size' to tst_acquire_device_() to make the test device can be increased according to real need.

This change gives a flexibility to ltp test device, you can customize its size by passing 'tst_test->device_min_size' to your cases. But it's limited that at least 150MB for the device generation.

Also, add tst_device.c tests, updating test-writing-guidelines.txt documents.

---
 doc/test-writing-guidelines.txt | 12 ++++++----
 include/old/old_device.h        |  7 +++++-
 include/tst_test.h              |  2 ++
 lib/newlib_tests/.gitignore     |  1 +
 lib/newlib_tests/tst_device.c   | 49 +++++++++++++++++++++++++++++++++++++++++
 lib/tst_device.c                | 27 ++++++++++++++++++-----
 lib/tst_test.c                  |  2 +-
 testcases/lib/test.sh           |  8 +++++--
 8 files changed, 94 insertions(+), 14 deletions(-)
 create mode 100644 lib/newlib_tests/tst_device.c
doc/test-writing-guidelines.txt +8 -4
index f927fc6..9c412be 100644
@@ -1323,12 +1323,16 @@ Following functions similar to the LTP C interface are available.
 * tst_rmdir()
 * tst_fs_has_free()
 * tst_mkfs()
-* tst_acquire_device()
 * tst_release_device()
 
-There is one more function called 'tst_check_cmds()' that gets unspecified
-number of parameters and asserts that each parameter is a name of an
-executable in '$PATH' and exits the test with 'TCONF' on first missing.
+One more function called 'tst_check_cmds()' that gets unspecified number
+of parameters and asserts that each parameter is a name of an executable
+in '$PATH' and exits the test with 'TCONF' on first missing.
+
+Another one is 'tst_acquire_device()' that looks for LTP_DEV env variable
+first (which may be passed by the test driver or by a user) and returns while
+it's value greater than 150MB. It also does clear first sectors of $LTP_DEV
+and makes the block device size can be increased according to real need.
 
 tst_sleep
 +++++++++
include/old/old_device.h +6 -1
index 4dae05e..aabc617 100644
@@ -42,7 +42,12 @@ const char *tst_dev_fs_type(void);
  *
  * Returns path to the device or NULL if it cannot be created.
  */
-const char *tst_acquire_device(void (cleanup_fn)(void));
+const char *tst_acquire_device_(void (cleanup_fn)(void), unsigned int size);
+
+static inline const char *tst_acquire_device(void (cleanup_fn)(void))
+{
+	return tst_acquire_device_(cleanup_fn, 0);
+}
 
 /*
  * @dev: device path returned by the tst_acquire_device()
include/tst_test.h +2 -0
index 4c30134..3f7123e 100644
@@ -106,6 +106,8 @@ struct tst_test {
 	int needs_device:1;
 	int needs_checkpoints:1;
 
+	unsigned int device_min_size;
+
 	/* override default timeout per test run */
 	unsigned int timeout;
 
lib/newlib_tests/.gitignore +1 -0
index c5b643f..1b83738 100644
@@ -12,3 +12,4 @@ test11
 test12
 test13
 tst_safe_fileops
+tst_device
lib/newlib_tests/tst_device.c new file +49 -0

49 lines not on this page · raw message

lib/tst_device.c +21 -6
index 30b1be2..f02d1c6 100644
@@ -182,10 +182,15 @@ static void detach_device(const char *dev)
 		"ioctl(%s, LOOP_CLR_FD, 0) no ENXIO for too long", dev);
 }
 
-const char *tst_acquire_device(void (cleanup_fn)(void))
+const char *tst_acquire_device_(void (cleanup_fn)(void), unsigned int size)
 {
+	int fd;
 	char *dev;
 	struct stat st;
+	unsigned int acq_dev_size;
+	unsigned int ltp_dev_size;
+
+	acq_dev_size = size > 150 ? size : 150;
 
 	if (device_acquired)
 		tst_brkm(TBROK, cleanup_fn, "Device allready acquired");
@@ -207,15 +212,25 @@ const char *tst_acquire_device(void (cleanup_fn)(void))
 			         "%s is not a block device", dev);
 		}
 
-		if (tst_fill_file(dev, 0, 1024, 512)) {
-			tst_brkm(TBROK | TERRNO, cleanup_fn,
-				 "Failed to clear the first 512k of %s", dev);
+		fd = SAFE_OPEN(cleanup_fn, dev, O_RDONLY);
+		SAFE_IOCTL(cleanup_fn, fd, BLKGETSIZE64, &ltp_dev_size);
+		SAFE_CLOSE(cleanup_fn, fd);
+		ltp_dev_size = ltp_dev_size/1024/1024;
+
+		if (acq_dev_size <= ltp_dev_size) {
+			if (tst_fill_file(dev, 0, 1024, 512)) {
+				tst_brkm(TBROK | TERRNO, cleanup_fn,
+					"Failed to clear the first 512k of %s", dev);
+			}
+
+			return dev;
 		}
 
-		return dev;
+		tst_resm(TINFO, "Skipping $LTP_DEV size %luMB, requested size %luMB",
+				ltp_dev_size, acq_dev_size);
 	}
 
-	if (tst_fill_file(DEV_FILE, 0, 1024, 153600)) {
+	if (tst_fill_file(DEV_FILE, 0, 1024, 1024 * acq_dev_size)) {
 		tst_brkm(TBROK | TERRNO, cleanup_fn,
 		         "Failed to create " DEV_FILE);
 
lib/tst_test.c +1 -1
index 12ca051..06f0339 100644
@@ -596,7 +596,7 @@ static void do_setup(int argc, char *argv[])
 	}
 
 	if (tst_test->needs_device) {
-		tdev.dev = tst_acquire_device(NULL);
+		tdev.dev = tst_acquire_device_(NULL, tst_test->device_min_size);
 		tdev.fs_type = tst_dev_fs_type();
 
 		if (!tdev.dev)
testcases/lib/test.sh +6 -2
index a1fa2d9..76b7062 100644
@@ -283,11 +283,15 @@ EXPECT_FAIL()
 
 tst_acquire_device()
 {
+	local acq_dev_size=${1:-150}
+
 	if [ -z ${TST_TMPDIR} ]; then
 		tst_brkm "Use 'tst_tmpdir' before 'tst_acquire_device'"
 	fi
 
-	if [ -n "${LTP_DEV}" ]; then
+	ltp_dev_size=$((`blockdev --getsize64 $LTP_DEV`/1024/1024))
+
+	if [ -n "${LTP_DEV}" ] && [ ${acq_dev_size} -le ${ltp_dev_size} ]; then
 		tst_resm TINFO "Using test device LTP_DEV='${LTP_DEV}'"
 		if [ ! -b ${LTP_DEV} ]; then
 			tst_brkm TBROK "${LTP_DEV} is not a block device"
@@ -300,7 +304,7 @@ tst_acquire_device()
 		return
 	fi
 
-	ROD_SILENT dd if=/dev/zero of=test_dev.img bs=1024 count=153600
+	ROD_SILENT dd if=/dev/zero of=test_dev.img bs=1024 count=$((1024*$acq_dev_size))
 
 	TST_DEVICE=$(losetup -f)
 	if [ $? -ne 0 ]; then
Signature · 1 line
1.8.3.1
#1 lore raw

PATCH v6 1/1 lib: make the loop device size can be increased

Hi!
Pushed with a few changes, thanks.

* I've changed the parameter passed to the ioctl() it has to be 64 bit unsigned integer otherwise the stack would get corrupted since the kernel writes 64 bit value to the pointer.

* Tweaked the documentation. Added documentation for the .device_min_size and cleared up the tst_acquire_device one.

The full diff is:

doc/test-writing-guidelines.txt +25 -9
index a27f24f..384ff09 100644
@@ -904,6 +904,10 @@ If '.needs_device' flag in the 'struct tst_test' is set the the 'tst_device'
 structure is initialized with a path to a test device and default filesystem
 to be used.
 
+You can also request minimal device size in megabytes by setting
+'.device_min_size' in the 'struct tst_test' structure. The device is
+guaranteed to have at least the requested size then.
+
 [source,c]
 -------------------------------------------------------------------------------
 #include "tst_test.h"
@@ -919,8 +923,10 @@ int tst_umount(const char *path);
 -------------------------------------------------------------------------------
 
 In case that 'LTP_DEV' is passed to the test in an environment, the library
-checks that the file exists and that it's a block device. Otherwise a
-temporary file is created and attached to a free loop device.
+checks that the file exists and that it's a block device, if
+'.device_min_size' is set the device size is checked as well. If 'LTP_DEV'
+wasn't set or if size requirements were not met a temporary file is created
+and attached to a free loop device.
 
 If there is no usable device and loop device couldn't be initialized the test
 exits with 'TCONF'.
@@ -1330,14 +1336,24 @@ Following functions similar to the LTP C interface are available.
 * tst_mkfs()
 * tst_release_device()
 
-One more function called 'tst_check_cmds()' that gets unspecified number
-of parameters and asserts that each parameter is a name of an executable
-in '$PATH' and exits the test with 'TCONF' on first missing.
+tst_check_cmds
+++++++++++++++
+
+The 'tst_check_cmds()' function that gets unspecified number of parameters and
+asserts that each parameter is a name of an executable in '$PATH' and exits
+the test with 'TCONF' on first missing.
+
+tst_acquire_device
+++++++++++++++++++
+
+The 'tst_acquire_device()' can be used to obtain a block device for testing,
+the function takes optional parameter which can be used to request device
+minimal size in megabytes.
 
-Another one is 'tst_acquire_device()' that looks for LTP_DEV env variable
-first (which may be passed by the test driver or by a user) and returns while
-it's value greater than 150MB. It also does clear first sectors of $LTP_DEV
-and makes the block device size can be increased according to real need.
+The function returns device passed in 'LTP_DEV' environment variable if it's
+set, points to a block device, and if size requirements are met. If 'LTP_DEV'
+is not set or found suitable a temporary file is created and attached to a
+free loop device.
 
 tst_sleep
 +++++++++
lib/newlib_tests/tst_device.c +5 -2
index d656904..72c2033 100644
@@ -17,6 +17,7 @@
 
 #include <stdlib.h>
 #include <sys/mount.h>
+#include <stdint.h>
 
 #include "tst_test.h"
 
@@ -24,7 +25,7 @@ static void do_test(void)
 {
 	int fd;
 	const char *dev;
-	unsigned int ltp_dev_size;
+	uint64_t ltp_dev_size;
 
 	dev = tst_device->dev;
 	if (!dev)
@@ -37,7 +38,9 @@ static void do_test(void)
 	SAFE_CLOSE(fd);
 
 	if (ltp_dev_size/1024/1024 == 160)
-		tst_res(TPASS, "PASSED LTP Device Test");
+		tst_res(TPASS, "Got expected device size");
+	else
+		tst_res(TFAIL, "Got unexpected device size");
 }
 
 static struct tst_test test = {
lib/tst_device.c +4 -2
index f02d1c6..3c62df0 100644
@@ -29,6 +29,8 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <linux/loop.h>
+#include <stdint.h>
+#include <inttypes.h>
 #include "test.h"
 #include "safe_macros.h"
 
@@ -188,7 +190,7 @@ const char *tst_acquire_device_(void (cleanup_fn)(void), unsigned int size)
 	char *dev;
 	struct stat st;
 	unsigned int acq_dev_size;
-	unsigned int ltp_dev_size;
+	uint64_t ltp_dev_size;
 
 	acq_dev_size = size > 150 ? size : 150;
 
@@ -226,7 +228,7 @@ const char *tst_acquire_device_(void (cleanup_fn)(void), unsigned int size)
 			return dev;
 		}
 
-		tst_resm(TINFO, "Skipping $LTP_DEV size %luMB, requested size %luMB",
+		tst_resm(TINFO, "Skipping $LTP_DEV size %"PRIu64"MB, requested size %uMB",
 				ltp_dev_size, acq_dev_size);
 	}
 
Signature · 2 lines
Cyril Hrubis
[email protected]