lib/blkdev: add support for --lock and LOCK_BLOCK_DEVICE
All simple function to parse --lock <mode> and $LOCK_BLOCK_DEVICE, and to flock the fd. The supported <mode> is: "1" or "yes" - LOCK_EX "0" or "no" - do nothing "nonblock" - LOCK_EX | LOCK_NB The function tries LOCK_NB before the solo LOCK_EX and prints inform user that it will wait, for example: session A: # sfdisk --lock /dev/sdc session B: # sfdisk --lock /dev/sdc sfdisk: /dev/sdc: device already locked, waiting to get lock ... ^C # sfdisk --lock=nonblock /dev/sdc sfdisk: /dev/sdc: device already locked Addresses: https://github.com/karelzak/util-linux/issues/921 Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
498f910eeb
commit
37b302046a
|
@ -146,5 +146,6 @@ int blkdev_get_geometry(int fd, unsigned int *h, unsigned int *s);
|
|||
/* convert scsi type code to name */
|
||||
const char *blkdev_scsi_type_to_name(int type);
|
||||
|
||||
int blkdev_lock(int fd, const char *devname, const char *lockmode);
|
||||
|
||||
#endif /* BLKDEV_H */
|
||||
|
|
52
lib/blkdev.c
52
lib/blkdev.c
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
@ -361,6 +362,57 @@ const char *blkdev_scsi_type_to_name(int type)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* return 0 on success */
|
||||
int blkdev_lock(int fd, const char *devname, const char *lockmode)
|
||||
{
|
||||
int oper, rc, msg = 0;
|
||||
|
||||
if (!lockmode)
|
||||
lockmode = getenv("LOCK_BLOCK_DEVICE");
|
||||
if (!lockmode)
|
||||
return 0;
|
||||
|
||||
if (strcasecmp(lockmode, "yes") == 0 ||
|
||||
strcmp(lockmode, "1") == 0)
|
||||
oper = LOCK_EX;
|
||||
|
||||
else if (strcasecmp(lockmode, "nonblock") == 0)
|
||||
oper = LOCK_EX | LOCK_NB;
|
||||
|
||||
else if (strcasecmp(lockmode, "no") == 0 ||
|
||||
strcmp(lockmode, "0") == 0)
|
||||
return 0;
|
||||
else {
|
||||
warnx(_("unsupported lock mode: %s"), lockmode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(oper & LOCK_NB)) {
|
||||
/* Try non-block first to provide message */
|
||||
rc = flock(fd, oper | LOCK_NB);
|
||||
if (rc == 0)
|
||||
return 0;
|
||||
if (rc != 0 && errno == EWOULDBLOCK) {
|
||||
fprintf(stderr, _("%s: %s: device already locked, waiting to get lock ... "),
|
||||
program_invocation_short_name, devname);
|
||||
msg = 1;
|
||||
}
|
||||
}
|
||||
rc = flock(fd, oper);
|
||||
if (rc != 0) {
|
||||
switch (errno) {
|
||||
case EWOULDBLOCK: /* LOCK_NB */
|
||||
warnx(_("%s: device already locked"), devname);
|
||||
break;
|
||||
default:
|
||||
warn(_("%s: failed to get lock"), devname);
|
||||
}
|
||||
} else if (msg)
|
||||
fprintf(stderr, _("OK\n"));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_PROGRAM_BLKDEV
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
Loading…
Reference in New Issue