diff options
| author | Junxiao Bi <junxiao.bi@oracle.com> | 2023-10-25 13:36:03 -0700 |
|---|---|---|
| committer | Karel Zak <kzak@redhat.com> | 2023-11-01 12:39:16 +0100 |
| commit | a6ca0456cc6d704a786f6b66d8bb2d89ff18eba7 (patch) | |
| tree | 21f565cb6b94d589f05f0f57eecaa9cc24a1c5f6 /lib/loopdev.c | |
| parent | d8379563fe5c8a4adba12804abbe20e43a8e1cde (diff) | |
| download | util-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.c | 36 |
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! * |
