Skip to content

Commit 29e4402

Browse files
committed
lklfuse: add lock parameter to avoid duplicate mounts
This lock-while-mounted behaviour is similar to what QEMU does, and can help avoid duplicate mounts. Allowing for an explicit lock path that differs from the filesystem image / block device path was intentional, to ensure non-flock supporting filesystems can still be used. Also, there are cases where a block device and partition (e.g. sda and sda1) can both provide access to the same filesystem image, in which case an FS-ID based lock would make sense. Signed-off-by: David Disseldorp <ddiss@suse.de>
1 parent 46f599b commit 29e4402

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

Documentation/lkl/lklfuse.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ OPTIONS
3939

4040
-o part=parition mount <partition>.
4141

42-
-o ro open file read-only.
42+
-o ro open block-device read-only.
43+
44+
-o lock=<file> only mount after taking an exclusive lock on <file>.
4345

4446
-o opts=options Linux kernel mount <options> (use \\ to escape , and =).
4547

tools/lkl/lklfuse.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <stdio.h>
77
#include <string.h>
88
#include <stdlib.h>
9+
#include <sys/file.h>
910
#include <sys/stat.h>
1011
#include <string.h>
1112
#include <errno.h>
@@ -24,6 +25,7 @@ struct lklfuse {
2425
const char *log;
2526
const char *type;
2627
const char *opts;
28+
const char *lock;
2729
struct lkl_disk disk;
2830
int disk_id;
2931
int part;
@@ -46,6 +48,7 @@ static struct fuse_opt lklfuse_opts[] = {
4648
LKLFUSE_OPT("mb=%d", mb, 0),
4749
LKLFUSE_OPT("opts=%s", opts, 0),
4850
LKLFUSE_OPT("part=%d", part, 0),
51+
LKLFUSE_OPT("lock=%s", lock, 0),
4952
FUSE_OPT_KEY("-h", KEY_HELP),
5053
FUSE_OPT_KEY("--help", KEY_HELP),
5154
FUSE_OPT_KEY("-V", KEY_VERSION),
@@ -58,7 +61,7 @@ static struct fuse_opt lklfuse_opts[] = {
5861
static void usage(void)
5962
{
6063
printf(
61-
"usage: lklfuse file mountpoint [options]\n"
64+
"usage: lklfuse block-device mountpoint [options]\n"
6265
"\n"
6366
"general options:\n"
6467
" -o opt,[opt...] mount options\n"
@@ -70,7 +73,8 @@ static void usage(void)
7073
" -o type=fstype filesystem type\n"
7174
" -o mb=memory amount of memory to allocate in MB (default: 64)\n"
7275
" -o part=parition partition to mount\n"
73-
" -o ro open file read-only\n"
76+
" -o ro open block-device read-only\n"
77+
" -o lock=FILE only mount after taking an exclusive lock on FILE\n"
7478
" -o opts=options mount options (use \\ to escape , and =)\n"
7579
);
7680
}
@@ -791,7 +795,7 @@ int main(int argc, char **argv)
791795
struct fuse_cmdline_opts cli_opts;
792796
struct fuse *fuse;
793797
struct stat st;
794-
int ret;
798+
int ret, lockfd = -1;
795799

796800
if (fuse_opt_parse(&args, &lklfuse, lklfuse_opts, lklfuse_opt_proc))
797801
return 1;
@@ -801,6 +805,23 @@ int main(int argc, char **argv)
801805
return 1;
802806
}
803807

808+
if (lklfuse.lock) {
809+
lockfd = open(lklfuse.lock, O_RDWR | O_CREAT, 0644);
810+
if (lockfd < 0) {
811+
fprintf(stderr, "failed to open %s: %s\n",
812+
lklfuse.lock, strerror(errno));
813+
return 1;
814+
}
815+
816+
ret = flock(lockfd, LOCK_EX | LOCK_NB);
817+
if (ret < 0) {
818+
fprintf(stderr, "unable to exclusively lock %s: %s\n",
819+
lklfuse.lock, strerror(errno));
820+
return 2;
821+
}
822+
/* lock dropped when lockfd is closed on program exit */
823+
}
824+
804825
if (fuse_parse_cmdline(&args, &cli_opts))
805826
return 1;
806827

0 commit comments

Comments
 (0)