aboutsummaryrefslogtreecommitdiffstats
path: root/lib/loopdev.c
diff options
context:
space:
mode:
authorJunxiao Bi <junxiao.bi@oracle.com>2023-10-25 13:36:03 -0700
committerKarel Zak <kzak@redhat.com>2023-11-01 12:39:16 +0100
commita6ca0456cc6d704a786f6b66d8bb2d89ff18eba7 (patch)
tree21f565cb6b94d589f05f0f57eecaa9cc24a1c5f6 /lib/loopdev.c
parentd8379563fe5c8a4adba12804abbe20e43a8e1cde (diff)
downloadutil-linux-a6ca0456cc6d704a786f6b66d8bb2d89ff18eba7.tar.gz
loopdev: report lost loop devices
If a /dev/loopX is lost because someone might have removed it by mistake, future losetup operations on that loop device will fail and losetup --all and --list will not report the devices (although kernel still uses it). Since /sysfs still have the loop device intact, detect that and report it. Changes: * --list and --all add "(lost)" after device node path # losetup NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC /dev/loop0 (lost) 0 0 0 0 /root/l0.img 0 512 # losetup -a /dev/loop0 (lost): []: (/root/l0.img) * use /sys to get devno rather than stat() * report warning after failed operation # losetup -d /dev/loop0 losetup: /dev/loop0: detach failed: No such file or directory losetup: device node /dev/loop0 (7:0) is lost. You may use mknod(1) to recover it. * fix copy & past bugs in some API comments Co-Author: Karel Zak <kzak@redhat.com> Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib/loopdev.c')
-rw-r--r--lib/loopdev.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/lib/loopdev.c b/lib/loopdev.c
index dae499f256..c72fb2c404 100644
--- a/lib/loopdev.c
+++ b/lib/loopdev.c
@@ -116,6 +116,8 @@ int loopcxt_set_device(struct loopdev_cxt *lc, const char *device)
DBG(CXT, ul_debugobj(lc, "closing old open fd"));
}
lc->fd = -1;
+ lc->is_lost = 0;
+ lc->devno = 0;
lc->mode = O_RDONLY;
lc->blocksize = 0;
lc->has_info = 0;
@@ -153,6 +155,28 @@ int loopcxt_has_device(struct loopdev_cxt *lc)
return lc && *lc->device;
}
+dev_t loopcxt_get_devno(struct loopdev_cxt *lc)
+{
+ if (!lc || !loopcxt_has_device(lc))
+ return 0;
+ if (!lc->devno)
+ lc->devno = sysfs_devname_to_devno(lc->device);
+ return lc->devno;
+}
+
+int loopcxt_is_lost(struct loopdev_cxt *lc)
+{
+ if (!lc || !loopcxt_has_device(lc))
+ return 0;
+ if (lc->is_lost)
+ return 1;
+
+ lc->is_lost = access(lc->device, F_OK) != 0
+ && loopcxt_get_devno(lc) != 0;
+
+ return lc->is_lost;
+}
+
/*
* @lc: context
* @flags: LOOPDEV_FL_* flags
@@ -265,7 +289,7 @@ static struct path_cxt *loopcxt_get_sysfs(struct loopdev_cxt *lc)
return NULL;
if (!lc->sysfs) {
- dev_t devno = sysfs_devname_to_devno(lc->device);
+ dev_t devno = loopcxt_get_devno(lc);
if (!devno) {
DBG(CXT, ul_debugobj(lc, "sysfs: failed devname to devno"));
return NULL;
@@ -416,13 +440,6 @@ static int loopiter_set_device(struct loopdev_cxt *lc, const char *device)
!(lc->iter.flags & LOOPITER_FL_FREE))
return 0; /* caller does not care about device status */
- if (!is_loopdev(lc->device)) {
- DBG(ITER, ul_debugobj(&lc->iter, "%s does not exist", lc->device));
- return -errno;
- }
-
- DBG(ITER, ul_debugobj(&lc->iter, "%s exist", lc->device));
-
used = loopcxt_get_offset(lc, NULL) == 0;
if ((lc->iter.flags & LOOPITER_FL_USED) && used)
@@ -876,7 +893,7 @@ int loopcxt_get_sizelimit(struct loopdev_cxt *lc, uint64_t *size)
/*
* @lc: context
- * @devno: returns encryption type
+ * @type: returns encryption type
*
* Cryptoloop is DEPRECATED!
*
@@ -901,7 +918,6 @@ int loopcxt_get_encrypt_type(struct loopdev_cxt *lc, uint32_t *type)
/*
* @lc: context
- * @devno: returns crypt name
*
* Cryptoloop is DEPRECATED!
*