[LTP] [PATCH v5 1/3] Allow acquiring multiple loop devices

Martin Doucha
2020-04-14T08:59:32Z

tst_acquire_device__() currently uses a hardcoded filename so only one loop
device can be used at a time. Allow setting arbitrary temp filename so that
multiple different loop devices can be acquired.

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---

No changes in this patch since v1. Rebase only.

include/old/old_device.h | 15 ++++++++++++++-
lib/tst_device.c | 36 +++++++++++++++++++++++-------------
testcases/lib/tst_device.c | 14 +++++++++-----
3 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/include/old/old_device.h b/include/old/old_device.h
index d2f1ecde5..a6e9fea86 100644
--- a/include/old/old_device.h
+++ b/include/old/old_device.h
@@ -52,13 +52,26 @@ static inline const char *tst_acquire_device(void (cleanup_fn)(void))
return tst_acquire_device_(cleanup_fn, 0);
}

+/*
+ * Acquire a loop device with specified temp filename. This function allows
+ * you to acquire multiple devices at the same time. LTP_DEV is ignored.
+ * If you call this function directly, use tst_detach_device() to release
+ * the devices. tst_release_device() will not work correctly.
+ *
+ * The return value points to a static buffer and additional calls of
+ * tst_acquire_loop_device() or tst_acquire_device() will overwrite it.
+ */
+const char *tst_acquire_loop_device(unsigned int size, const char *filename);
+
/*
* @dev: device path returned by the tst_acquire_device()
*/
int tst_release_device(const char *dev);

/*
- * @dev: device path returned by the tst_acquire_device()
+ * Cleanup function for tst_acquire_loop_device(). If you have acquired
+ * a device using tst_acquire_device(), use tst_release_device() instead.
+ * @dev: device path returned by the tst_acquire_loop_device()
*/
int tst_detach_device(const char *dev);

diff --git a/lib/tst_device.c b/lib/tst_device.c
index a703512d2..67fe90ed6 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -228,10 +228,28 @@ int tst_dev_sync(int fd)
return syscall(__NR_syncfs, fd);
}

+const char *tst_acquire_loop_device(unsigned int size, const char *filename)
+{
+ unsigned int acq_dev_size = MAX(size, DEV_SIZE_MB);
+
+ if (tst_fill_file(filename, 0, 1024 * 1024, acq_dev_size)) {
+ tst_resm(TWARN | TERRNO, "Failed to create %s", filename);
+ return NULL;
+ }
+
+ if (tst_find_free_loopdev(dev_path, sizeof(dev_path)) == -1)
+ return NULL;
+
+ if (tst_attach_device(dev_path, filename))
+ return NULL;
+
+ return dev_path;
+}
+
const char *tst_acquire_device__(unsigned int size)
{
int fd;
- char *dev;
+ const char *dev;
struct stat st;
unsigned int acq_dev_size;
uint64_t ltp_dev_size;
@@ -282,20 +300,12 @@ const char *tst_acquire_device__(unsigned int size)
ltp_dev_size, acq_dev_size);
}

- if (tst_fill_file(DEV_FILE, 0, 1024 * 1024, acq_dev_size)) {
- tst_resm(TWARN | TERRNO, "Failed to create " DEV_FILE);
- return NULL;
- }
-
- if (tst_find_free_loopdev(dev_path, sizeof(dev_path)) == -1)
- return NULL;
+ dev = tst_acquire_loop_device(acq_dev_size, DEV_FILE);

- if (tst_attach_device(dev_path, DEV_FILE))
- return NULL;
+ if (dev)
+ device_acquired = 1;

- device_acquired = 1;
-
- return dev_path;
+ return dev;
}

const char *tst_acquire_device_(void (cleanup_fn)(void), unsigned int size)
diff --git a/testcases/lib/tst_device.c b/testcases/lib/tst_device.c
index a657db30b..2a3ab1222 100644
--- a/testcases/lib/tst_device.c
+++ b/testcases/lib/tst_device.c
@@ -18,7 +18,7 @@ static struct tst_test test = {

static void print_help(void)
{
- fprintf(stderr, "\nUsage: tst_device acquire [size]\n");
+ fprintf(stderr, "\nUsage: tst_device acquire [size [filename]]\n");
fprintf(stderr, " or: tst_device release /path/to/device\n\n");
}

@@ -27,10 +27,10 @@ static int acquire_device(int argc, char *argv[])
unsigned int size = 0;
const char *device;

- if (argc > 3)
+ if (argc > 4)
return 1;

- if (argc == 3) {
+ if (argc >= 3) {
size = atoi(argv[2]);

if (!size) {
@@ -40,7 +40,11 @@ static int acquire_device(int argc, char *argv[])
}
}

- device = tst_acquire_device__(size);
+ if (argc >= 4) {
+ device = tst_acquire_loop_device(size, argv[3]);
+ } else {
+ device = tst_acquire_device__(size);
+ }

if (!device)
return 1;
@@ -61,7 +65,7 @@ static int release_device(int argc, char *argv[])
return 1;

/*
- * tst_acquire_device() was called in a different process.
+ * tst_acquire_[loop_]device() was called in a different process.
* tst_release_device() would think that no device was acquired yet
* and do nothing. Call tst_detach_device() directly to bypass
* the check.
--
2.26.0