Merge lp:~colin-king/ubuntu/wily/mountall/zfs-support into lp:ubuntu/wily/mountall

Proposed by Colin Ian King
Status: Rejected
Rejected by: Martin Pitt
Proposed branch: lp:~colin-king/ubuntu/wily/mountall/zfs-support
Merge into: lp:ubuntu/wily/mountall
Diff against target: 151 lines (+102/-4)
1 file modified
src/mountall.c (+102/-4)
To merge this branch: bzr merge lp:~colin-king/ubuntu/wily/mountall/zfs-support
Reviewer Review Type Date Requested Status
Martin Pitt Needs Information
Review via email: mp+268255@code.launchpad.net

Description of the change

I am proposing the following ZFS related patches to be merged into mountall. These patches are directly from Ubuntu ZFS on Linux (https://launchpad.net/~zfs-native/+archive/ubuntu/stable) and have considerable time to mature.

To post a comment you must log in.
Revision history for this message
Martin Pitt (pitti) wrote :

Does that actually still make sense as we now have systemd? I doubt zfs is going to be used on phones (where we still use mountall and upstart). Does systemd's fstab generator need changes to generate .mount units for ZFS?

review: Needs Information
Revision history for this message
Colin Ian King (colin-king) wrote :

We indeed don't need this now. Please ignore this. Apologies.

Revision history for this message
Martin Pitt (pitti) wrote :

No need to apologize, thank you! Sorry that this was in vain.

Unmerged revisions

467. By Colin Ian King

* Handle duplicate mountpoints.
When mountall is iterating in try_mounts() on new mount point, change
is_parent() to return false when a record is tested against itself
because a mount point cannot be a root of itself.

Mountall does not preserve the behavior of `mount -a` if more than
one device shares a mountpoint in the /etc/fstab file. Suppose:

        /var/tmp/alfa /mnt/charlie ext2 loop 0 0
        /var/tmp/bravo /mnt/charlie ext2 loop 0 0

Both filesystems are mounted on /mnt/charlie by `mount -a`, but
bravo is ignored by `mountall`. This seems to be an artifact of the fix for
LP: #443035 in zfsonlinux/mountall@eca315d06ae4a2913f9b2ec994c68c45fead912f.

Furthermore, mountall hangs if such mounts are ZFS datasets or A

Closes: zfsonlinux/mountall#5
Darik Horn <email address hidden>, Fri, 27 Mar 2013 22:29:47 -0600

466. By Colin Ian King

* no filesystem should depend on mounting swap first
  mk01 <email address hidden>, Fri, 1 Feb 2013 02:06:57 +0100

465. By Colin Ian King

* readonly and atime options reflected during mount
  Matus Kral <email address hidden>, Wed, 30 Jan 2013 08:09:00 +0100

464. By Colin Ian King

* Disregard the 'mounted' dataset property.
  If `/etc/mtab` is not a symlink to `/proc/mounts`, and if it contains stale
  records, then `zfs list` returns incorrect 'mounted' values that cause
  corresponding datasets to be ignored.

  The mounted check is unnecessary (and the problem), since mountall checks if
  the mountpoints are already mounted before it spawns a mount job - but zfs list
  checks mtab before it's been written by mountall (and any stale mountpoints get
  misrepresented). Removing that check, everything seems to work fine (mounts
  correctly on startup, doesn't overmount things when run from the command line
  in a running session).
  Will Rouesnel <email address hidden>, Thu, 27 Dec 2012 05:59:37 -0600

463. By Colin Ian King

* Add ZFS support.
  Pretend that the output of `zfs list` is appended to the `/etc/fstab` file
  Darik Horn <email address hidden>, Sun, 6 Nov 2011 00:00:00 -0500

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/mountall.c'
2--- src/mountall.c 2013-10-08 02:14:58 +0000
3+++ src/mountall.c 2015-08-17 16:26:20 +0000
4@@ -147,6 +147,7 @@
5 };
6
7 #define MOUNT_NAME(_mnt) (strcmp ((_mnt)->type, "swap") \
8+ && strcmp ((_mnt)->type, "zfs") \
9 && strcmp ((_mnt)->mountpoint, "none") \
10 ? (_mnt)->mountpoint : (_mnt)->device)
11
12@@ -180,6 +181,7 @@
13 char * cut_options (const void *parent, Mount *mnt, ...);
14
15 void parse_fstab (const char *filename);
16+void parse_zfs_list (void);
17 void parse_mountinfo (void);
18
19 void parse_filesystems (void);
20@@ -759,6 +761,102 @@
21 endmntent (fstab);
22 }
23
24+/**
25+ * parse_zfs_list:
26+ *
27+ * Add the output of `/sbin/zfs list` to the internal mounts list
28+ * and pretend that these filesystems were in the /etc/fstab file.
29+ *
30+ * @TODO: Check whether Canonical agrees that libzfs, which is
31+ * subject to the CDDL, should get the GPL system library exemption
32+ * like it usually does on BSD and Solaris systems.
33+ *
34+ * @TODO: Subtitute the call to popen with a libzfs routine.
35+ *
36+ * @TODO: Double-check whether the new src parameter should be NULL
37+ * or set to a dummy fstab filename.
38+ *
39+ **/
40+void
41+parse_zfs_list (void)
42+{
43+ nih_local char *buf = NULL;
44+ size_t bufsz = 4096;
45+ FILE *zfs_stream;
46+ const char zfs_command[] =
47+ "/sbin/zfs list -H -t filesystem -o name,mountpoint,canmount,readonly,atime";
48+ int zfs_result;
49+
50+ nih_debug ("parsing ZFS list");
51+
52+ fflush (stdout);
53+ fflush (stderr);
54+ zfs_stream = popen (zfs_command, "r");
55+
56+ if (zfs_stream == NULL) {
57+ nih_debug ("popen /sbin/zfs: %s", strerror (errno));
58+ return;
59+ }
60+
61+ buf = NIH_MUST (nih_alloc (NULL, bufsz));
62+
63+ /* Read one line from the pipe into the buffer. */
64+ while (fgets (buf, bufsz, zfs_stream) != NULL) {
65+ char *saveptr;
66+ char *zfs_name, *zfs_mountpoint, *zfs_canmount, *zfs_optatime, *zfs_optronly;
67+ nih_local char *zfs_mntoptions = NULL;
68+
69+ /* If the line didn't fit, then enlarge the buffer and retry. */
70+ while ((! strchr (buf, '\n')) && (! feof (zfs_stream))) {
71+ buf = NIH_MUST (nih_realloc (buf, NULL, bufsz + 4096));
72+ if (! fgets (buf + bufsz - 1, 4097, zfs_stream)) {
73+ break;
74+ }
75+ bufsz += 4096;
76+ }
77+
78+ zfs_name = strtok_r (buf, "\t", &saveptr);
79+ if (! zfs_name) {
80+ continue;
81+ }
82+
83+ /* ASSERT: mountpoint[0] = '/' OR mountpoint = none | legacy */
84+ zfs_mountpoint = strtok_r (NULL, "\t", &saveptr);
85+ if (! zfs_mountpoint || zfs_mountpoint[0] != '/') {
86+ continue;
87+ }
88+
89+ /* ASSERT: canmount = on | off | noauto */
90+ zfs_canmount = strtok_r (NULL, "\t", &saveptr);
91+ if (! zfs_canmount || strcmp (zfs_canmount, "on")) {
92+ continue;
93+ }
94+
95+ NIH_MUST (nih_strcat (&zfs_mntoptions, NULL, "zfsutil"));
96+
97+ /* ASSERT: readonly = on | off */
98+ zfs_optronly = strtok_r (NULL, "\t", &saveptr);
99+ if ( zfs_optronly && strcmp (zfs_optronly, "off") ) {
100+ NIH_MUST (nih_strcat (&zfs_mntoptions, NULL, ",ro"));
101+ }
102+
103+ /* ASSERT: atime = on | off */
104+ zfs_optatime = strtok_r (NULL, "\t\n", &saveptr);
105+ if ( zfs_optatime && strcmp (zfs_optatime, "on") ) {
106+ NIH_MUST (nih_strcat (&zfs_mntoptions, NULL, ",noatime"));
107+ }
108+
109+ new_mount (zfs_mountpoint, zfs_name, FALSE, "zfs", zfs_mntoptions, NULL);
110+ }
111+
112+ zfs_result = pclose (zfs_stream);
113+
114+ if (zfs_result)
115+ {
116+ nih_debug ("pclose /sbin/zfs: %i %s", zfs_result, strerror (errno));
117+ }
118+}
119+
120 static int
121 needs_remount (Mount *mnt)
122 {
123@@ -1046,9 +1144,7 @@
124
125 len = strlen (root);
126 if ((! strncmp (path, root, len))
127- && ((path[len] == '\0')
128- || (path[len] == '/')
129- || (len && path[len-1] == '/')))
130+ && ((path[len] == '/') || (len && path[len-1] == '/')))
131 return TRUE;
132
133 return FALSE;
134@@ -1282,7 +1378,8 @@
135 && strcmp (mnt->device, "none")
136 && strcmp (mnt->device, mnt->type)
137 && (mnt->entry.prev != mounts)
138- && strcmp (((Mount *)mnt->entry.prev)->device, "none")) {
139+ && strcmp (((Mount *)mnt->entry.prev)->device, "none")
140+ && strcmp (((Mount *)mnt->entry.prev)->type, "swap")) {
141 NihListEntry *dep;
142 Mount * prior;
143
144@@ -4023,6 +4120,7 @@
145 */
146 parse_fstab (BUILTIN_FSTAB);
147 parse_fstab (_PATH_MNTTAB);
148+ parse_zfs_list ();
149 parse_mountinfo ();
150
151 /* Apply policy as to what waits for what, etc. */

Subscribers

People subscribed via source and target branches