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 */
|
/* convert scsi type code to name */
|
||||||
const char *blkdev_scsi_type_to_name(int type);
|
const char *blkdev_scsi_type_to_name(int type);
|
||||||
|
|
||||||
|
int blkdev_lock(int fd, const char *devname, const char *lockmode);
|
||||||
|
|
||||||
#endif /* BLKDEV_H */
|
#endif /* BLKDEV_H */
|
||||||
|
|
52
lib/blkdev.c
52
lib/blkdev.c
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/file.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -361,6 +362,57 @@ const char *blkdev_scsi_type_to_name(int type)
|
||||||
return NULL;
|
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
|
#ifdef TEST_PROGRAM_BLKDEV
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
Loading…
Reference in New Issue