Discussion:
[systemd-devel] systemd-fstab-generator and multiple mounts to same mount point
John Lane
2013-01-02 12:01:41 UTC
Permalink
Hello,

I have a configuration where a filesystem is mounted on /images.

Then a subdirectory of that filesystem, say /images/1, is bind mounted
on top as /images.

Prior to moving to systemd, this kind of thing has always worked fine
with /etc/fstab containing something like this:

# images uuid 8847d358-c4f6-4405-a65c-e0c514151f8e is on /dev/sda1
UUID=8847d358-c4f6-4405-a65c-e0c514151f8e /images ext3 defaults 0 1

# Bind mount current images on /images
#/images/1354 /images none rw,bind 0 0

With systemd, systemd-fstab-generator complains about the second use of
the /images mount point:

Jan 02 08:31:58 neon systemd-fstab-generator[79]: Failed to create unit
file /run/systemd/generator/images.mount: File exists
Jan 02 08:31:58 neon systemd[1]:
/usr/lib/systemd/system-generators/systemd-fstab-generator exited with
exit status 1.

How should this situation be handled with systemd ?

Thanks,
John
Andrey Borzenkov
2013-01-02 12:15:04 UTC
Permalink
В Wed, 02 Jan 2013 12:01:41 +0000
Post by John Lane
Hello,
I have a configuration where a filesystem is mounted on /images.
Then a subdirectory of that filesystem, say /images/1, is bind mounted
on top as /images.
Prior to moving to systemd, this kind of thing has always worked fine
# images uuid 8847d358-c4f6-4405-a65c-e0c514151f8e is on /dev/sda1
UUID=8847d358-c4f6-4405-a65c-e0c514151f8e /images ext3 defaults 0 1
# Bind mount current images on /images
#/images/1354 /images none rw,bind 0 0
With systemd, systemd-fstab-generator complains about the second use of
Jan 02 08:31:58 neon systemd-fstab-generator[79]: Failed to create unit
file /run/systemd/generator/images.mount: File exists
/usr/lib/systemd/system-generators/systemd-fstab-generator exited with
exit status 1.
How should this situation be handled with systemd ?
Mount first time somewhere else? Like /image_archive? And bind
mount /image_archive/1354 to /images?
John Lane
2013-01-02 12:44:10 UTC
Permalink
Post by Andrey Borzenkov
В Wed, 02 Jan 2013 12:01:41 +0000
Post by John Lane
Hello,
I have a configuration where a filesystem is mounted on /images.
Then a subdirectory of that filesystem, say /images/1, is bind mounted
on top as /images.
Prior to moving to systemd, this kind of thing has always worked fine
# images uuid 8847d358-c4f6-4405-a65c-e0c514151f8e is on /dev/sda1
UUID=8847d358-c4f6-4405-a65c-e0c514151f8e /images ext3 defaults 0 1
# Bind mount current images on /images
#/images/1354 /images none rw,bind 0 0
With systemd, systemd-fstab-generator complains about the second use of
Jan 02 08:31:58 neon systemd-fstab-generator[79]: Failed to create unit
file /run/systemd/generator/images.mount: File exists
/usr/lib/systemd/system-generators/systemd-fstab-generator exited with
exit status 1.
How should this situation be handled with systemd ?
Mount first time somewhere else? Like /image_archive? And bind
mount /image_archive/1354 to /images?
I realise I can work around the problem (that's what I am doing right
now) but I want the mounts to be done in that way (one over the other).

As such an /etc/fstab worked fine before systemd it would be good if it
continued to work with systemd.

I think the problem is how systemd names the generated mount units. If
there is a clash, could it not
use a modified name for the unit (e.g if
/run/systemd/generator/images.mount exists it would create
/run/systemd/generator/images-1.mount or something like that) ?
Zbigniew Jędrzejewski-Szmek
2013-01-02 14:25:19 UTC
Permalink
Post by John Lane
Post by Andrey Borzenkov
В Wed, 02 Jan 2013 12:01:41 +0000
Post by John Lane
Hello,
I have a configuration where a filesystem is mounted on /images.
Then a subdirectory of that filesystem, say /images/1, is bind mounted
on top as /images.
I think the problem is how systemd names the generated mount units.
If there is a clash, could it not
use a modified name for the unit (e.g if
/run/systemd/generator/images.mount exists it would create
/run/systemd/generator/images-1.mount or something like that) ?
Hi,

it's on the TODO list ("* properly handle .mount unit state tracking
when two mount points are stacked one on top of another on the exact
same mount point.") Patches welcome :)

Zbyszek
John Lane
2013-01-02 20:21:39 UTC
Permalink
Post by Zbigniew Jędrzejewski-Szmek
Post by John Lane
Post by Andrey Borzenkov
В Wed, 02 Jan 2013 12:01:41 +0000
Post by John Lane
Hello,
I have a configuration where a filesystem is mounted on /images.
Then a subdirectory of that filesystem, say /images/1, is bind mounted
on top as /images.
I think the problem is how systemd names the generated mount units.
If there is a clash, could it not
use a modified name for the unit (e.g if
/run/systemd/generator/images.mount exists it would create
/run/systemd/generator/images-1.mount or something like that) ?
Hi,
it's on the TODO list ("* properly handle .mount unit state tracking
when two mount points are stacked one on top of another on the exact
same mount point.") Patches welcome :)
Zbyszek
Good to know, thanks. I'll take a look and see if I'll provide a patch
if I can.
But I have never looked inside systemd so I may need some pointers to
find my way around it.

@tom: good point about not including a "-" in any variant filename.
John Lane
2013-01-03 16:16:06 UTC
Permalink
Post by John Lane
Post by Zbigniew Jędrzejewski-Szmek
Post by John Lane
Post by Andrey Borzenkov
В Wed, 02 Jan 2013 12:01:41 +0000
Post by John Lane
Hello,
I have a configuration where a filesystem is mounted on /images.
Then a subdirectory of that filesystem, say /images/1, is bind mounted
on top as /images.
I think the problem is how systemd names the generated mount units.
If there is a clash, could it not
use a modified name for the unit (e.g if
/run/systemd/generator/images.mount exists it would create
/run/systemd/generator/images-1.mount or something like that) ?
Hi,
it's on the TODO list ("* properly handle .mount unit state tracking
when two mount points are stacked one on top of another on the exact
same mount point.") Patches welcome :)
Zbyszek
Good to know, thanks. I'll take a look and see if I'll provide a patch
if I can.
But I have never looked inside systemd so I may need some pointers to
find my way around it.
@tom: good point about not including a "-" in any variant filename.
Hello. Here is a patch to allow systemd to handle overmounts defined in
/etc/fstab.

https://raw.github.com/johnlane/archlinux-systemd/master/fstab-overmount.patch

It works against the latest git version. It amends two files :

* src/fstab-generator/fstab-generator.c
* src/core/mount.c

It appends a suffix (an underscore followed by a number) to a mount unit
file name when one already
exists. This allows the mount unit file to be generated. The mount
routine is modified to consider the
suffix when checking that the mount point and unit file names match.

Tested on Arch Linux. I have a pkgbuild for it:
https://github.com/johnlane/archlinux-systemd

If I should submit this in some other way please let me know. Sorry I am
not more familiar with your process.

I hope this is useful.

Kind regards,
John
Tom Gundersen
2013-01-03 16:40:54 UTC
Permalink
Post by John Lane
Hello. Here is a patch to allow systemd to handle overmounts defined in
/etc/fstab.
https://raw.github.com/johnlane/archlinux-systemd/master/fstab-overmount.patch
Please use spaces rather than tabs ;-)
Post by John Lane
It appends a suffix (an underscore followed by a number) to a mount unit
file name when one already exists.
Hm, I didn't look carefully, but won't this break if you have a folder
named, say, "/mnt_1"? I suppose you could use some unused escape code
similarly to how '/' is encoded?
Post by John Lane
This allows the mount unit file to be generated. The mount routine
is modified to consider the
suffix when checking that the mount point and unit file names match.
How are you making sure that the mounts are stacked in the right
order? You'd want to order mounts that are 'higher' in the stack
After= the mounts that are lower down (in the same way as home.mount
is now ordered After=-.mount).
Post by John Lane
If I should submit this in some other way please let me know. Sorry I am not
more familiar with your process.
Use 'git send-email', that way people can comment inline (and you
avoid linke-break problems that usually results from pasting the patch
into your email client).

Cheers,

Tom
John Lane
2013-01-03 17:18:27 UTC
Permalink
Post by Tom Gundersen
Post by John Lane
Hello. Here is a patch to allow systemd to handle overmounts defined in
/etc/fstab.
https://raw.github.com/johnlane/archlinux-systemd/master/fstab-overmount.patch
Please use spaces rather than tabs ;-)
I thought I did. I hate tabs too :)
Post by Tom Gundersen
Post by John Lane
It appends a suffix (an underscore followed by a number) to a mount unit
file name when one already exists.
Hm, I didn't look carefully, but won't this break if you have a folder
named, say, "/mnt_1"? I suppose you could use some unused escape code
similarly to how '/' is encoded?
No, it's fine. I just tested it to make sure. It looks for the _
delimiter from the right-hand end of the name so it's ok (because all
that can come to the right of it is a number and '.mount'.
Post by Tom Gundersen
Post by John Lane
This allows the mount unit file to be generated. The mount routine
is modified to consider the
suffix when checking that the mount point and unit file names match.
How are you making sure that the mounts are stacked in the right
order? You'd want to order mounts that are 'higher' in the stack
After= the mounts that are lower down (in the same way as home.mount
is now ordered After=-.mount).
I haven't considered that (I haven't modified the code to put in an
"after") but I've been using it
all day and it seems to get them in the right order. If I have time I'll
see if I can work out how to
stick in an "After" to point at the previous mount.
Post by Tom Gundersen
Post by John Lane
If I should submit this in some other way please let me know. Sorry I am not
more familiar with your process.
Use 'git send-email', that way people can comment inline (and you
avoid linke-break problems that usually results from pasting the patch
into your email client).
Cheers,
Tom
Lennart Poettering
2013-01-03 19:39:43 UTC
Permalink
Post by Zbigniew Jędrzejewski-Szmek
Post by John Lane
Post by Andrey Borzenkov
В Wed, 02 Jan 2013 12:01:41 +0000
Post by John Lane
Hello,
I have a configuration where a filesystem is mounted on /images.
Then a subdirectory of that filesystem, say /images/1, is bind mounted
on top as /images.
I think the problem is how systemd names the generated mount units.
If there is a clash, could it not
use a modified name for the unit (e.g if
/run/systemd/generator/images.mount exists it would create
/run/systemd/generator/images-1.mount or something like that) ?
Hi,
it's on the TODO list ("* properly handle .mount unit state tracking
when two mount points are stacked one on top of another on the exact
same mount point.") Patches welcome :)
This is actually about something different. I don't think we really
should support stackable .mount units. However, we should handle it
properly if somebody does that with external tools, and if then the
mount unit is stopped we should unmount all mounts on the same mount
point. This TODO list item is hence mostly about looping around
/bin/umount when we stop a mount unit, rather than actually allowing
multiple parallel mount units for the same mount path...

Lennart
--
Lennart Poettering - Red Hat, Inc.
Tom Gundersen
2013-01-02 17:21:36 UTC
Permalink
I think the problem is how systemd names the generated mount units. If there
is a clash, could it not
use a modified name for the unit (e.g if /run/systemd/generator/images.mount
exists it would create /run/systemd/generator/images-1.mount or something
like that) ?
Note that that particular naming scheme would not work. Check out the
escaping logic in systemd.unit(5).

-t
Lennart Poettering
2013-01-03 19:50:41 UTC
Permalink
Post by John Lane
I realise I can work around the problem (that's what I am doing
right now) but I want the mounts to be done in that way (one over
the other).
As such an /etc/fstab worked fine before systemd it would be good if
it continued to work with systemd.
I think the problem is how systemd names the generated mount units.
If there is a clash, could it not
use a modified name for the unit (e.g if
/run/systemd/generator/images.mount exists it would create
/run/systemd/generator/images-1.mount or something like that) ?
Humm, I am very conservative about this I must say.

In general we have the rule that the mount unit for a path is named
after the path (while replacing "/" by "-" and appending ".mount" to
it), and this is enforced in the code. Allowing multiple .mount units
for the same path would really complicate the whole system, and I am not
convinced that that would be worth it.

systemd automatically determines a multitude of dependencies between the
units. For example if a mount point lies beneath another mount point
they gain implicit ordering deps. Similar, if a socket unit refers to a
file system socket on a specific mount point they gain ordering deps
implicitly too, and so on. In fact, much of what is nice in systemd is
based on implicit dependencies.

Now, if you allow multiple separate mount units for the same path this
all becomes really complicated. Because how do you handle the ordering
deps for those? How do you handle the ordering deps *between* the two?
Sure you can say "whatever comes first in fstab is mounted first", but
that only gets you so far, as fstab is just one way to configure mount
units, and they can come from other sources too. Also, native units are
loaded only when referenced, in order to optimize the footprint of
systemd. That basically means the "first mention" rule becomes very much
chaotic, since whatever unit is referenced first wins, and that
recursively.

Also, I have my doubts that other software would be fine with these
clashes, either. I am pretty sure most folks would assume that mount
point names are unique, and this will be coded into many projects, not
just systemd.

Just changing the generator to output alternate .mount units if a clash
happens won't solve your issue btw, because the mount path will still
have to be in sync with the mount unit name. And since you cannot have
two files with the same name in a directory you can't have two units for
the same mount point either...

So, before we spend time on implementing this, we really should figure
out if this is a desirable feature, or if there are better ways to solve
this usecase. I guess the first question needs to be: what's the usecase
anyway? if we know that, maybe we can find a nicer way?

Lennart
--
Lennart Poettering - Red Hat, Inc.
John Lane
2013-01-04 01:22:41 UTC
Permalink
Post by Lennart Poettering
Post by John Lane
I realise I can work around the problem (that's what I am doing
right now) but I want the mounts to be done in that way (one over
the other).
As such an /etc/fstab worked fine before systemd it would be good if
it continued to work with systemd.
I think the problem is how systemd names the generated mount units.
If there is a clash, could it not
use a modified name for the unit (e.g if
/run/systemd/generator/images.mount exists it would create
/run/systemd/generator/images-1.mount or something like that) ?
Humm, I am very conservative about this I must say.
In general we have the rule that the mount unit for a path is named
after the path (while replacing "/" by "-" and appending ".mount" to
it), and this is enforced in the code. Allowing multiple .mount units
for the same path would really complicate the whole system, and I am not
convinced that that would be worth it.
systemd automatically determines a multitude of dependencies between the
units. For example if a mount point lies beneath another mount point
they gain implicit ordering deps. Similar, if a socket unit refers to a
file system socket on a specific mount point they gain ordering deps
implicitly too, and so on. In fact, much of what is nice in systemd is
based on implicit dependencies.
Now, if you allow multiple separate mount units for the same path this
all becomes really complicated. Because how do you handle the ordering
deps for those? How do you handle the ordering deps *between* the two?
Sure you can say "whatever comes first in fstab is mounted first", but
that only gets you so far, as fstab is just one way to configure mount
units, and they can come from other sources too. Also, native units are
loaded only when referenced, in order to optimize the footprint of
systemd. That basically means the "first mention" rule becomes very much
chaotic, since whatever unit is referenced first wins, and that
recursively.
Could we consider the units generated from /etc/fstab as a special and
straightforward case, where the generator can base the unit dependencies
on the ordering that the mount definitions are listed in /etc/fstab?
Like you say "whatever comes first in fstab is mounted first". There may
be other ways to configure mount units but we are only talking here
about those generated from /etc/fstab.

if /etc/fstab is not going away then the possibility of arranging mounts
in that file which break in systemd will remain.
Post by Lennart Poettering
Also, I have my doubts that other software would be fine with these
clashes, either. I am pretty sure most folks would assume that mount
point names are unique, and this will be coded into many projects, not
just systemd.
Just changing the generator to output alternate .mount units if a clash
happens won't solve your issue btw, because the mount path will still
have to be in sync with the mount unit name. And since you cannot have
two files with the same name in a directory you can't have two units for
the same mount point either...
The patch I supplied attempts to address this also (unless there is more
to it than what seemed to be the case when I looked at it).
Post by Lennart Poettering
So, before we spend time on implementing this, we really should figure
out if this is a desirable feature, or if there are better ways to solve
this usecase. I guess the first question needs to be: what's the usecase
anyway? if we know that, maybe we can find a nicer way?
I didn't want to muddy the waters by discussing the pros and cons of my
use-case but I'll explain in case it helps.

A custom configuration here allows a system to have multiple system
images to help support upgrade and rollback: a 'live' one that is
running and others that are not. Each has their own partitions except
there needed to be a single /boot partition. Each system writes their
own boot files to the same /boot partition but each has its own
subdirectory on it. It is this subdirectory that is overmounted so the
running system sees its own boot files at /boot where it expects them to
be. It's been running like that smoothly for a very long time and has
only become an issue with the transition to systemd.

I have updated my patch so it writes an "After=" dependency as per Tom's
comment. It's here:

https://raw.github.com/johnlane/archlinux-systemd/master/fstab-overmount.patch

(I'll do a git-send-email tomorrow once I sort out smtp access for the
box I was testing this on)

With that patch, I have systemd working well for the above use-case.

I'm going to leave it at that until there's more of a discussion by
people more knowledgeable than me but, If I can help in any way, do let
me know. I would obviously like to see this supported as I have a
genuine use-case for over-mounting that I have been able to do for as
long as I can remember.

Regards,
John
Post by Lennart Poettering
Lennart
John Lane
2013-01-04 14:09:10 UTC
Permalink
From: John Lane <***@lane.uk.net>

---
src/core/mount.c | 13 +++++++-
src/fstab-generator/fstab-generator.c | 58 +++++++++++++++++++++++------------
2 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/src/core/mount.c b/src/core/mount.c
index f263d9b..b0a06e9 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -507,6 +507,9 @@ static int mount_fix_timeouts(Mount *m) {
static int mount_verify(Mount *m) {
bool b;
char *e;
+ char *ext, *suf;
+ int name_len;
+ char cm[strlen(UNIT(m)->id)];
assert(m);

if (UNIT(m)->load_state != UNIT_LOADED)
@@ -518,7 +521,15 @@ static int mount_verify(Mount *m) {
if (!(e = unit_name_from_path(m->where, ".mount")))
return -ENOMEM;

- b = unit_has_name(UNIT(m), e);
+ /* clean mount file name with any overmount suffix removed */
+ ext = strrchr(UNIT(m)->id,'.');
+ suf = strrchr(UNIT(m)->id,'_');
+ name_len = (suf ? suf : ext ) - UNIT(m)->id;
+ strncpy(cm,UNIT(m)->id, name_len);
+ strcpy(cm + name_len, ext);
+ log_debug("clean mount file name (with any overmount suffix removed): %s", cm);
+
+ b = unit_has_name(UNIT(m), e) || !strcmp(e,cm);
free(e);

if (!b) {
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index a0173d8..1f693fe 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -214,6 +214,9 @@ static int add_mount(const char *what, const char *where, const char *type, cons
int passno, bool wait, bool noauto, bool nofail, bool automount, bool isbind, bool isnetwork,
const char *source) {
char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL, *automount_name = NULL, *automount_unit = NULL;
+ char uniq_suffix[10] = ".mount";
+ int uniq_num = 0;
+ char *prior_unit = NULL;
FILE *f = NULL;
int r;
const char *post, *pre;
@@ -244,27 +247,37 @@ static int add_mount(const char *what, const char *where, const char *type, cons
pre = SPECIAL_LOCAL_FS_PRE_TARGET;
}

- name = unit_name_from_path(where, ".mount");
- if (!name) {
- r = log_oom();
- goto finish;
- }
+ do {

- unit = strjoin(arg_dest, "/", name, NULL);
- if (!unit) {
- r = log_oom();
- goto finish;
- }
+ name = unit_name_from_path(where, uniq_suffix);
+ if (!name) {
+ r = log_oom();
+ goto finish;
+ }

- f = fopen(unit, "wxe");
- if (!f) {
- r = -errno;
- if (errno == EEXIST)
- log_error("Failed to create mount unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit);
- else
- log_error("Failed to create unit file %s: %m", unit);
- goto finish;
- }
+ unit = strjoin(arg_dest, "/", name, NULL);
+ if (!unit) {
+ r = log_oom();
+ goto finish;
+ }
+
+ f = fopen(unit, "wxe");
+ if (!f) {
+ r = -errno;
+ if (errno == EEXIST)
+ {
+ free(prior_unit);
+ prior_unit = strdup(name);
+ snprintf(uniq_suffix, 10, "_%d.mount", uniq_num++);
+ log_warning("Failed to create mount unit file %s because it already exists (overmount entry in /etc/fstab?). Will retry with suffix %s", unit, uniq_suffix);
+ }
+ else
+ {
+ log_error("Failed to create unit file %s: %m", unit);
+ goto finish;
+ }
+ }
+ } while (!f);

fprintf(f,
"# Automatically generated by systemd-fstab-generator\n\n"
@@ -288,6 +301,13 @@ static int add_mount(const char *what, const char *where, const char *type, cons
"Before=%s\n",
post);

+ if (prior_unit) {
+ fprintf(f,
+ "After=%s\n",
+ prior_unit);
+ free(prior_unit);
+ }
+
fprintf(f,
"\n"
"[Mount]\n"
--
1.8.0
Peeters Simon
2013-01-04 02:56:20 UTC
Permalink
Post by Lennart Poettering
...
Just changing the generator to output alternate .mount units if a clash
happens won't solve your issue btw, because the mount path will still
have to be in sync with the mount unit name. And since you cannot have
two files with the same name in a directory you can't have two units for
the same mount point either...
So, before we spend time on implementing this, we really should figure
out if this is a desirable feature, or if there are better ways to solve
this usecase. I guess the first question needs to be: what's the usecase
anyway? if we know that, maybe we can find a nicer way?
I think one of the only usecase for this kind of overmounting is to bind mount
a subdir of a mountpoint on top of that mountpoint: (as in Johns original post)
mount /dev/somedev /images
mount --bind /images/1354 /images

so it might be a solution to add a BindSubdir= option to the unit file
like this:
[Mount]
What=/dev/somedev
Where=/images
BindSubdir=1354

So that multiple mount units for the same mount point are not needed.
I think this is a quiet clean solution, but anyhow just my 2c.


Simon
John Lane
2013-01-15 15:41:15 UTC
Permalink
Post by Peeters Simon
I think one of the only usecase for this kind of overmounting is to bind mount
a subdir of a mountpoint on top of that mountpoint: (as in Johns original post)
mount /dev/somedev /images
mount --bind /images/1354 /images
so it might be a solution to add a BindSubdir= option to the unit file
[Mount]
What=/dev/somedev
Where=/images
BindSubdir=1354
So that multiple mount units for the same mount point are not needed.
I think this is a quiet clean solution, but anyhow just my 2c.
Simon
I would agree with Simon's suggestion. Such a 'BindSubdir' option would
satisfy my use case. I can try and write a patch to implement a Bind
option if this solution would be acceptable ?

(meanwhile, I've updated my original patch for the current source tree
to keep it up to date).

Are there any further thoughts on this?

Thanks,
John
John Lane
2013-01-15 15:47:04 UTC
Permalink
---
src/core/mount.c | 13 +++++++++-
src/fstab-generator/fstab-generator.c | 49 +++++++++++++++++++++++++----------
2 files changed, 47 insertions(+), 15 deletions(-)

diff --git a/src/core/mount.c b/src/core/mount.c
index 25bc7e1..8f35f68 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -518,6 +518,9 @@ static int mount_fix_timeouts(Mount *m) {
static int mount_verify(Mount *m) {
bool b;
char *e;
+ char *ext, *suf;
+ int name_len;
+ char cm[strlen(UNIT(m)->id)];
assert(m);

if (UNIT(m)->load_state != UNIT_LOADED)
@@ -529,7 +532,15 @@ static int mount_verify(Mount *m) {
if (!(e = unit_name_from_path(m->where, ".mount")))
return -ENOMEM;

- b = unit_has_name(UNIT(m), e);
+ /* clean mount file name with any overmount suffix removed */
+ ext = strrchr(UNIT(m)->id,'.');
+ suf = strrchr(UNIT(m)->id,'_');
+ name_len = (suf ? suf : ext ) - UNIT(m)->id;
+ strncpy(cm,UNIT(m)->id, name_len);
+ strcpy(cm + name_len, ext);
+ log_debug("clean mount file name (with any overmount suffix removed): %s", cm);
+
+ b = unit_has_name(UNIT(m), e) || !strcmp(e,cm);
free(e);

if (!b) {
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 2b67bb6..aad2d49 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -198,6 +198,10 @@ static int add_mount(const char *what, const char *where, const char *type, cons
int r;
const char *post, *pre;

+ char uniq_suffix[10] = ".mount";
+ int uniq_num = 0;
+ char *prior_unit = NULL;
+
assert(what);
assert(where);
assert(type);
@@ -224,22 +228,33 @@ static int add_mount(const char *what, const char *where, const char *type, cons
pre = SPECIAL_LOCAL_FS_PRE_TARGET;
}

- name = unit_name_from_path(where, ".mount");
- if (!name)
- return log_oom();
+ do {

- unit = strjoin(arg_dest, "/", name, NULL);
- if (!unit)
- return log_oom();
+ name = unit_name_from_path(where, uniq_suffix);
+ if (!name)
+ return log_oom();

- f = fopen(unit, "wxe");
- if (!f) {
- if (errno == EEXIST)
- log_error("Failed to create mount unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit);
- else
- log_error("Failed to create unit file %s: %m", unit);
- return -errno;
- }
+ unit = strjoin(arg_dest, "/", name, NULL);
+ if (!unit)
+ return log_oom();
+
+ f = fopen(unit, "wxe");
+ if (!f) {
+ if (errno == EEXIST)
+ {
+ free(prior_unit);
+ prior_unit = strdup(name);
+ snprintf(uniq_suffix, 10, "_%d.mount", uniq_num++);
+ log_warning("Failed to create mount unit file %s because it already exists (overmount entry in /etc/fstab?). Will retry with suffix %s", unit, uniq_suffix);
+ }
+ else
+ {
+ log_error("Failed to create unit file %s: %m", unit);
+ return -errno;
+ }
+ }
+
+ } while (!f);

fprintf(f,
"# Automatically generated by systemd-fstab-generator\n\n"
@@ -257,6 +272,12 @@ static int add_mount(const char *what, const char *where, const char *type, cons
pre,
pre);

+ if (prior_unit) {
+ fprintf(f,
+ "After=%s\n",
+ prior_unit);
+ free(prior_unit);
+ }

if (!noauto && !nofail && !automount)
fprintf(f,
--
1.8.0
Lennart Poettering
2013-01-15 15:48:04 UTC
Permalink
Post by John Lane
Post by Peeters Simon
I think one of the only usecase for this kind of overmounting is to bind mount
a subdir of a mountpoint on top of that mountpoint: (as in Johns original post)
mount /dev/somedev /images
mount --bind /images/1354 /images
so it might be a solution to add a BindSubdir= option to the unit file
[Mount]
What=/dev/somedev
Where=/images
BindSubdir=1354
So that multiple mount units for the same mount point are not needed.
I think this is a quiet clean solution, but anyhow just my 2c.
Simon
I would agree with Simon's suggestion. Such a 'BindSubdir' option
would satisfy my use case. I can try and write a patch to implement
a Bind option if this solution would be acceptable ?
I am a bit afraid of the atomicity implications this have. If you do two
mounts to set up a specific mount point, then apps listening for that
will get two events, and if they end up being too quick they might see
the mount point at an "invalid" time. That's a real problem actually, as
gvfs/nautilus actively watch all mounts as they are created. And
gvfs/nautilus are hardly the only ones.

Creating mount points should be atomic, there should be no time window
where a mount point contains stuff that is not supposed to be visible,
and there should be a single notification event be generated for it.

Ultimately this means this should be fixed in the kernel, i.e. the
kernel should provide a mount option or so how one can mount a file
system's subdirectory only instead of the file system itself. It's the
only clean way...

Also, I am pretty sure systemd should not expose more here than mount(8)
does, so if we work around a missing feature of the kernel in userspace,
then this should at least live in mount(8) so that it is available from
all mount commands, not just those configured via systemd.

This all is very similar actually to the discussion of read-only bind
mounts. Right now you need two mount commands to set them up, and they
can hence not be created atomically either. THis really is something to
fix in the kernel, as it creates and will continue to create all kinds
of weird userspace problems.

Sorry if that's disappointing...

Lennart
--
Lennart Poettering - Red Hat, Inc.
Jan Engelhardt
2013-01-06 18:57:08 UTC
Permalink
Post by Lennart Poettering
systemd automatically determines a multitude of dependencies between the
units. For example if a mount point lies beneath another mount point
they gain implicit ordering deps.[...]
Now, if you allow multiple separate mount units for the same path this
all becomes really complicated. Because how do you handle the ordering
deps for those? How do you handle the ordering deps *between* the two?
Sure you can say "whatever comes first in fstab is mounted first", but
that only gets you so far, as fstab is just one way to configure mount
units, and they can come from other sources too.
/proc/self/mountinfo should have all the vfsmounts that are interdependent
ordered.
Loading...