@@ -57,11 +57,22 @@ int tst_find_free_loopdev(const char *path, size_t path_len);
*/
int tst_attach_device(const char *dev_path, const char *file_path);
+/*
+ * Detaches a file from a loop device fd.
+ *
+ * @dev_path Path to the loop device e.g. /dev/loop0
+ * @dev_fd a open fd for the loop device
+ * @return Zero on succes, non-zero otherwise.
+ * */
+
+int tst_detach_device_by_fd(const char *dev_path, int dev_fd);
+
/*
* Detaches a file from a loop device.
*
* @dev_path Path to the loop device e.g. /dev/loop0
* @return Zero on succes, non-zero otherwise.
+ * In internal, call tst_detach_device_by_fd api.
*/
int tst_detach_device(const char *dev_path);
@@ -187,43 +187,48 @@ int tst_attach_device(const char *dev, const char *file)
return 0;
}
-int tst_detach_device(const char *dev)
+int tst_detach_device_by_fd(const char *dev, int dev_fd)
{
- int dev_fd, ret, i;
-
- dev_fd = open(dev, O_RDONLY);
- if (dev_fd < 0) {
- tst_resm(TWARN | TERRNO, "open(%s) failed", dev);
- return 1;
- }
+ int ret, i;
/* keep trying to clear LOOPDEV until we get ENXIO, a quick succession
* of attach/detach might not give udev enough time to complete */
for (i = 0; i < 40; i++) {
ret = ioctl(dev_fd, LOOP_CLR_FD, 0);
- if (ret && (errno == ENXIO)) {
- close(dev_fd);
+ if (ret && (errno == ENXIO))
return 0;
- }
if (ret && (errno != EBUSY)) {
tst_resm(TWARN,
"ioctl(%s, LOOP_CLR_FD, 0) unexpectedly failed with: %s",
dev, tst_strerrno(errno));
- close(dev_fd);
return 1;
}
usleep(50000);
}
- close(dev_fd);
tst_resm(TWARN,
"ioctl(%s, LOOP_CLR_FD, 0) no ENXIO for too long", dev);
return 1;
}
+int tst_detach_device(const char *dev)
+{
+ int dev_fd, ret;
+
+ dev_fd = open(dev, O_RDONLY);
+ if (dev_fd < 0) {
+ tst_resm(TWARN | TERRNO, "open(%s) failed", dev);
+ return 1;
+ }
+
+ ret = tst_detach_device_by_fd(dev, dev_fd);
+ close(dev_fd);
+ return ret;
+}
+
int tst_dev_sync(int fd)
{
return syscall(__NR_syncfs, fd);