~ubuntu-branches/ubuntu/precise/mountall/precise-proposed

« back to all changes in this revision

Viewing changes to src/mountall.c

  • Committer: Package Import Robot
  • Author(s): Steve Langasek, Andy Whitcroft
  • Date: 2012-11-08 00:29:40 UTC
  • mfrom: (0.1.5 karmic)
  • Revision ID: package-import@ubuntu.com-20121108002940-kw8eaeo3q9huptu2
Tags: 2.36.1
* Add options to mountall(8) manual page.  LP: #805509.
* Allow 'mounting' and 'mounted' signals from unrelated mounts to be
  processed in parallel.  Thanks to Alexander Achenbach for the initial
  patch.  LP: #643289.

[ Andy Whitcroft ]
* Add support for mounting the efivars filesystem onto
  /sys/firmware/efi/efivars.  LP: #1063061.

Show diffs side-by-side

added added

removed removed

Lines of Context:
126
126
        int                 fsck_fix;
127
127
        int                 ready;
128
128
 
 
129
        DBusPendingCall *   pending_call;
 
130
 
129
131
        Error               error;
130
132
 
131
133
        char *              type;
140
142
        int                 checked_link;
141
143
        Mount *             link_target;
142
144
        NihList             deps;
 
145
        int                 needs_mtab;
143
146
};
144
147
 
145
148
#define MOUNT_NAME(_mnt) (strcmp ((_mnt)->type, "swap")                 \
158
161
        void (*handler) (Mount *mnt, pid_t pid, int status);
159
162
} Process;
160
163
 
 
164
typedef struct event_reply_data {
 
165
        Mount *          mnt;
 
166
        void (*handler) (void *data, NihDBusMessage *message);
 
167
} EventReplyData;
161
168
 
162
169
Mount *new_mount             (const char *mountpoint, const char *device,
163
170
                              int check, const char *type, const char *opts);
185
192
 
186
193
void   try_mounts            (void);
187
194
void   try_mount             (Mount *mnt, int force);
 
195
void   mounting_event_handled(void *data, NihDBusMessage *message);
 
196
void   mounted_event_handled (void *data, NihDBusMessage *message);
188
197
 
189
198
int    find_on_path          (const char *name);
190
199
int    find_fsck             (const char *type);
209
218
void   mount_showthrough     (Mount *root);
210
219
 
211
220
void   upstart_disconnected  (DBusConnection *connection);
212
 
void   emit_event            (const char *name, Mount *mnt);
 
221
void   emit_event            (const char *name, Mount *mnt,
 
222
                              void (*cb) (void *, NihDBusMessage *message));
213
223
void   emit_event_error      (void *data, NihDBusMessage *message);
214
224
 
215
225
void   udev_monitor_watcher  (struct udev_monitor *udev_monitor,
479
489
        mnt->fsck_fix = FALSE;
480
490
        mnt->ready = FALSE;
481
491
 
 
492
        mnt->pending_call = NULL;
 
493
 
482
494
        mnt->error = ERROR_NONE;
483
495
 
484
496
        mnt->type = NULL;
495
507
        nih_alloc_set_destructor (mnt, nih_list_destroy);
496
508
        nih_list_add (mounts, &mnt->entry);
497
509
 
 
510
        mnt->needs_mtab = FALSE;
 
511
 
498
512
        update_mount (mnt, device, check, type, opts);
499
513
 
500
514
        return mnt;
859
873
                mnt = find_mount (mountpoint);
860
874
                if (mnt
861
875
                    && strcmp (type, "swap")) {
 
876
 
 
877
                        int needed_remount = needs_remount (mnt);
 
878
 
862
879
                        if (! strcmp (type, "rootfs"))
863
880
                                type = NULL;
864
881
 
871
888
                        if (mnt->mount_opts)
872
889
                                nih_unref (mnt->mount_opts, mounts);
873
890
                        mnt->mount_opts = opts;
 
891
 
 
892
                        /* If remounted, treat as newly done mount below. */
 
893
                        if (needed_remount && !needs_remount (mnt))
 
894
                                mnt->mounted = FALSE;
 
895
 
874
896
                } else {
875
897
                        mnt = new_mount (mountpoint, device, FALSE, type, opts);
876
898
                        mnt->mount_opts = opts;
879
901
                if (sscanf (dev, "%d:%d", &maj, &min) == 2)
880
902
                        mnt->mounted_dev = makedev (maj, min);
881
903
 
882
 
                if (reparsed && (! mnt->mounted)) {
 
904
                if (mnt->mounted)
 
905
                        continue;
 
906
 
 
907
                /* Fully update mounted state if reparsed.
 
908
                 * If invoked first time, just set the flag and leave complete
 
909
                 * state update (including event trigger) to mark_mounted ().
 
910
                 */
 
911
                if (reparsed && ! mnt->pending_call) {
883
912
                        mounted (mnt);
884
913
                } else {
885
914
                        mnt->mounted = TRUE;
1433
1462
 
1434
1463
        nih_debug ("%s", MOUNT_NAME (mnt));
1435
1464
 
1436
 
        mnt->mounted = TRUE;
1437
 
        newly_mounted = TRUE;
1438
 
        nih_main_loop_interrupt ();
1439
 
 
1440
1465
        mnt->error = ERROR_NONE;
1441
1466
        plymouth_update (FALSE);
1442
1467
 
1476
1501
                }
1477
1502
        }
1478
1503
 
1479
 
        emit_event ("mounted", mnt);
1480
 
 
1481
 
        /* Any previous mount options no longer apply
1482
 
         * (ie. we're not read-only anymore)
1483
 
         */
1484
 
        if (mnt->mount_opts)
1485
 
                nih_unref (mnt->mount_opts, mounts);
1486
 
        mnt->mount_opts = NULL;
1487
 
 
1488
 
        if ((! written_mtab))
1489
 
                write_mtab ();
1490
 
 
1491
 
        switch (mnt->tag) {
1492
 
        case TAG_LOCAL:
1493
 
                num_local_mounted++;
1494
 
                break;
1495
 
        case TAG_TIMEOUT:
1496
 
                num_local_mounted++;
1497
 
                num_timeout_mounted++;
1498
 
                if (num_timeout_mounted == num_timeout) {
1499
 
                        nih_message (_("\n %s finished! "), "local_timeout");
1500
 
                        /* Stop the timeout waiting for device to get ready"
1501
 
                         */
1502
 
                        if (device_ready_timer) {
1503
 
                                nih_free (device_ready_timer);
1504
 
                                device_ready_timer = NULL;
1505
 
                        }
1506
 
                }
1507
 
                break;
1508
 
        case TAG_REMOTE:
1509
 
                num_remote_mounted++;
1510
 
                break;
1511
 
        case TAG_VIRTUAL:
1512
 
                num_virtual_mounted++;
1513
 
                break;
1514
 
        case TAG_SWAP:
1515
 
                num_swap_mounted++;
1516
 
                break;
1517
 
        case TAG_NOWAIT:
1518
 
                break;
1519
 
        case TAG_SKIPPED:
1520
 
                break;
1521
 
        case TAG_UNKNOWN:
1522
 
                break;
1523
 
        default:
1524
 
                nih_assert_not_reached ();
1525
 
        }
1526
 
 
1527
 
        trigger_events ();
 
1504
        if (!mnt->pending_call)
 
1505
                emit_event ("mounted", mnt, mounted_event_handled);
1528
1506
 
1529
1507
        fsck_update ();
1530
1508
}
1597
1575
        if ((! virtual_triggered)
1598
1576
            && (num_virtual_mounted == num_virtual)) {
1599
1577
                nih_info (_("%s finished"), "virtual");
1600
 
                emit_event ("virtual-filesystems", NULL);
 
1578
                emit_event ("virtual-filesystems", NULL, NULL);
1601
1579
                virtual_triggered = TRUE;
1602
1580
        }
1603
1581
 
1606
1584
            && virtual_triggered
1607
1585
            && (num_local_mounted == num_local)) {
1608
1586
                nih_info (_("%s finished"), "local");
1609
 
                emit_event ("local-filesystems", NULL);
 
1587
                emit_event ("local-filesystems", NULL, NULL);
1610
1588
                local_triggered = TRUE;
1611
1589
        }
1612
1590
 
1615
1593
            && virtual_triggered
1616
1594
            && (num_remote_mounted == num_remote)) {
1617
1595
                nih_info (_("%s finished"), "remote");
1618
 
                emit_event ("remote-filesystems", NULL);
 
1596
                emit_event ("remote-filesystems", NULL, NULL);
1619
1597
                remote_triggered = TRUE;
1620
1598
        }
1621
1599
 
1625
1603
            && local_triggered
1626
1604
            && remote_triggered) {
1627
1605
                nih_info (_("All filesystems mounted"));
1628
 
                emit_event ("filesystem", NULL);
 
1606
                emit_event ("filesystem", NULL, NULL);
1629
1607
                filesystem_triggered = TRUE;
1630
1608
        }
1631
1609
 
1633
1611
        if ((! swap_triggered)
1634
1612
            && (num_swap_mounted == num_swap)) {
1635
1613
                nih_info (_("%s finished"), "swap");
1636
 
                emit_event ("all-swaps", NULL);
 
1614
                emit_event ("all-swaps", NULL, NULL);
1637
1615
                swap_triggered = TRUE;
1638
1616
        }
1639
1617
 
1679
1657
                        || (! strncmp (mnt->device, "LABEL=", 6))))
1680
1658
                {
1681
1659
                        nih_message ("%s device not ready in ROOTDELAY sec", MOUNT_NAME (mnt));
1682
 
                        emit_event ("device-not-ready", mnt);
 
1660
                        emit_event ("device-not-ready", mnt, NULL);
1683
1661
                }
1684
1662
        }
1685
1663
}
1747
1725
                }
1748
1726
 
1749
1727
                if (all) {
 
1728
                        /* All mounts have been attempted, so wait for
 
1729
                         * pending events.
 
1730
                         */
 
1731
                        NIH_LIST_FOREACH (mounts, iter) {
 
1732
                                Mount           *mnt = (Mount *)iter;
 
1733
                                DBusPendingCall *pending_call = mnt->pending_call;
 
1734
 
 
1735
                                if (!pending_call)
 
1736
                                        continue;
 
1737
 
 
1738
                                dbus_pending_call_block (pending_call);
 
1739
                                dbus_pending_call_unref (pending_call);
 
1740
                                mnt->pending_call = NULL;
 
1741
                        }
 
1742
 
1750
1743
                        if (control_server) {
1751
1744
                                dbus_server_disconnect (control_server);
1752
1745
                                dbus_server_unref (control_server);
1764
1757
 
1765
1758
        nih_assert (mnt != NULL);
1766
1759
 
 
1760
        if (mnt->pending_call)
 
1761
                return;
 
1762
 
1767
1763
        NIH_LIST_FOREACH (&mnt->deps, dep_iter) {
1768
1764
                NihListEntry *dep_entry = (NihListEntry *)dep_iter;
1769
1765
                Mount *       dep = (Mount *)dep_entry->data;
1852
1848
                return;
1853
1849
        }
1854
1850
 
1855
 
        /* Queue a filesystem check if not yet ready, otherwise run
1856
 
         * swapon or mount as appropriate.
 
1851
        /* Queue a filesystem check if not yet ready, otherwise emit mounting
 
1852
         * event (callback will run swapon or mount as appropriate).
1857
1853
         */
1858
1854
        if ((! mnt->ready)
1859
1855
            && (! is_remote (mnt))) {
1860
1856
                run_fsck (mnt);
1861
1857
        } else if (! strcmp (mnt->type, "swap")) {
1862
 
                emit_event ("mounting", mnt);
 
1858
                nih_info ("mounting event sent for swap %s", mnt->device);
 
1859
                emit_event ("mounting", mnt, mounting_event_handled);
 
1860
        } else {
 
1861
                nih_info ("mounting event sent for %s", mnt->mountpoint);
 
1862
                emit_event ("mounting", mnt, mounting_event_handled);
 
1863
        }
 
1864
}
 
1865
 
 
1866
 
 
1867
void
 
1868
mounting_event_handled (void *data,
 
1869
                        NihDBusMessage *message)
 
1870
{
 
1871
        Mount *mnt = ((EventReplyData *)data)->mnt;
 
1872
 
 
1873
        nih_free (data);
 
1874
 
 
1875
        /* We may generate new pending events below; make sure to clear
 
1876
         * the current one before we do. */
 
1877
        mnt->pending_call = NULL;
 
1878
 
 
1879
        if (!strcmp(mnt->type, "swap")) {
 
1880
                nih_info ("mounting event handled for swap %s", mnt->device);
1863
1881
                run_swapon (mnt);
1864
1882
        } else {
1865
 
                emit_event ("mounting", mnt);
 
1883
                nih_info ("mounting event handled for %s", mnt->mountpoint);
1866
1884
                run_mount (mnt, FALSE);
1867
1885
        }
1868
1886
}
1869
1887
 
1870
1888
 
 
1889
void
 
1890
mounted_event_handled (void *data,
 
1891
                       NihDBusMessage *message)
 
1892
{
 
1893
        Mount *mnt = ((EventReplyData *)data)->mnt;
 
1894
 
 
1895
        nih_free (data);
 
1896
 
 
1897
        /* We may generate new pending events below; make sure to clear
 
1898
         * the current one before we do. */
 
1899
        mnt->pending_call = NULL;
 
1900
 
 
1901
        mnt->mounted = TRUE;
 
1902
        newly_mounted = TRUE;
 
1903
        nih_main_loop_interrupt ();
 
1904
 
 
1905
        if (!strcmp(mnt->type, "swap")) {
 
1906
                nih_info ("mounted event handled for swap %s", mnt->device);
 
1907
        } else {
 
1908
                nih_info ("mounted event handled for %s", mnt->mountpoint);
 
1909
        }
 
1910
 
 
1911
        /* Any previous mount options no longer apply
 
1912
         * (ie. we're not read-only anymore)
 
1913
         */
 
1914
        if (mnt->mount_opts)
 
1915
                nih_unref (mnt->mount_opts, mounts);
 
1916
        mnt->mount_opts = NULL;
 
1917
 
 
1918
        if ((! written_mtab))
 
1919
                write_mtab ();
 
1920
        if (written_mtab && mnt->needs_mtab)
 
1921
                run_mount (mnt, TRUE);
 
1922
 
 
1923
        switch (mnt->tag) {
 
1924
        case TAG_LOCAL:
 
1925
                num_local_mounted++;
 
1926
                break;
 
1927
        case TAG_TIMEOUT:
 
1928
                num_local_mounted++;
 
1929
                num_timeout_mounted++;
 
1930
                if (num_timeout_mounted == num_timeout) {
 
1931
                        nih_message (_("\n %s finished! "), "local_timeout");
 
1932
                        /* Stop the timeout waiting for device to get ready"
 
1933
                         */
 
1934
                        if (device_ready_timer) {
 
1935
                                nih_free (device_ready_timer);
 
1936
                                device_ready_timer = NULL;
 
1937
                        }
 
1938
                }
 
1939
                break;
 
1940
        case TAG_REMOTE:
 
1941
                num_remote_mounted++;
 
1942
                break;
 
1943
        case TAG_VIRTUAL:
 
1944
                num_virtual_mounted++;
 
1945
                break;
 
1946
        case TAG_SWAP:
 
1947
                num_swap_mounted++;
 
1948
                break;
 
1949
        case TAG_NOWAIT:
 
1950
                break;
 
1951
        case TAG_SKIPPED:
 
1952
                break;
 
1953
        case TAG_UNKNOWN:
 
1954
                break;
 
1955
        default:
 
1956
                nih_assert_not_reached ();
 
1957
        }
 
1958
 
 
1959
        trigger_events ();
 
1960
 
 
1961
        fsck_update ();
 
1962
}
 
1963
 
 
1964
 
1871
1965
/**
1872
1966
 * find_on_path:
1873
1967
 *
2127
2221
                   && strcmp (mnt->type, "ntfs")
2128
2222
                   && strcmp (mnt->type, "ntfs-3g")) {
2129
2223
                NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-n"));
 
2224
                mnt->needs_mtab = TRUE;
2130
2225
        } else if (mnt->has_showthrough) {
2131
2226
                NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-n"));
2132
2227
        }
2201
2296
         */
2202
2297
        if (! mnt->mounted) {
2203
2298
                parse_mountinfo ();
2204
 
                if (! mnt->mounted)
 
2299
                /* If the canonical path of the mount point doesn't match
 
2300
                 * what's in the fstab, reparsing /proc/mounts won't change
 
2301
                 * this mount but instead create a new record.  So handle
 
2302
                 * this case directly here.
 
2303
                 */
 
2304
                if (! mnt->mounted && ! mnt->pending_call)
2205
2305
                        mounted (mnt);
2206
2306
        } else {
2207
2307
                mounted (mnt);
2483
2583
                        continue;
2484
2584
 
2485
2585
                run_mount (mnt, TRUE);
 
2586
                mnt->needs_mtab = FALSE;
2486
2587
        }
2487
2588
 
2488
2589
        written_mtab = TRUE;
2566
2667
 
2567
2668
void
2568
2669
emit_event (const char *name,
2569
 
            Mount *     mnt)
 
2670
            Mount *     mnt,
 
2671
            void (*cb) (void *, NihDBusMessage *message))
2570
2672
{
2571
2673
        DBusPendingCall *pending_call;
2572
2674
        nih_local char **env = NULL;
2573
2675
        size_t           env_len = 0;
 
2676
        EventReplyData  *reply_data = NULL;
2574
2677
 
2575
2678
        nih_assert (name != NULL);
2576
2679
 
2609
2712
                nih_discard (var);
2610
2713
        }
2611
2714
 
 
2715
        if (mnt && cb)
 
2716
                reply_data = NIH_MUST (nih_alloc (NULL, sizeof (EventReplyData)));
 
2717
        
2612
2718
        pending_call = NIH_SHOULD (upstart_emit_event (upstart,
2613
 
                                                       name, env, mnt ? TRUE : FALSE,
2614
 
                                                       NULL, emit_event_error, NULL,
 
2719
                                                       name, env, reply_data ? TRUE : FALSE,
 
2720
                                                       reply_data ? cb : NULL,
 
2721
                                                       emit_event_error, reply_data,
2615
2722
                                                       NIH_DBUS_TIMEOUT_NEVER));
2616
 
        if (! pending_call) {
 
2723
 
 
2724
        if (pending_call) {
 
2725
        
 
2726
                if (reply_data) {
 
2727
 
 
2728
                        reply_data->mnt = mnt;
 
2729
                        reply_data->handler = cb;
 
2730
 
 
2731
                        /* If previous event is still pending, wait for it. */
 
2732
                        if (mnt->pending_call) {
 
2733
                                DBusPendingCall *pending = mnt->pending_call;
 
2734
                                dbus_pending_call_block (pending);
 
2735
                                dbus_pending_call_unref (pending);
 
2736
                        }
 
2737
 
 
2738
                        mnt->pending_call = pending_call;
 
2739
 
 
2740
                } else {
 
2741
 
 
2742
                        /* Immediate return from upstart, wait for it. */
 
2743
                        dbus_pending_call_block (pending_call);
 
2744
                        dbus_pending_call_unref (pending_call);
 
2745
                }
 
2746
                
 
2747
        } else {
 
2748
        
2617
2749
                NihError *err;
2618
2750
 
2619
2751
                err = nih_error_get ();
2620
2752
                nih_warn ("%s", err->message);
2621
2753
                nih_free (err);
2622
2754
 
2623
 
                return;
 
2755
                nih_free (reply_data);
2624
2756
        }
2625
 
 
2626
 
        dbus_pending_call_block (pending_call);
2627
 
 
2628
 
        dbus_pending_call_unref (pending_call);
2629
2757
}
2630
2758
 
2631
2759
void
2632
2760
emit_event_error (void *          data,
2633
2761
                  NihDBusMessage *message)
2634
2762
{
 
2763
        EventReplyData *reply_data = (EventReplyData *)data;
2635
2764
        NihError *err;
2636
2765
 
2637
2766
        err = nih_error_get ();
2638
2767
        nih_warn ("%s", err->message);
2639
2768
        nih_free (err);
 
2769
 
 
2770
        /* Even if the event returned an error, we still want to do the mount */
 
2771
        if (reply_data)
 
2772
                reply_data->handler (data, message);
2640
2773
}
2641
2774
 
2642
2775
 
3714
3847
                                        else {
3715
3848
                                                nih_free (mnt->device);
3716
3849
                                                mnt->device = newdev;
3717
 
                                                emit_event ("changed-device", mnt);
 
3850
                                                emit_event ("changed-device", mnt, NULL);
3718
3851
                                        }
3719
3852
                                }
3720
3853
                                break;
3937
4070
                nih_free (err);
3938
4071
        }
3939
4072
        if (!ret)
3940
 
                emit_event("mountallServer", NULL);
 
4073
                emit_event("mountallServer", NULL, NULL);
3941
4074
        /* Activate the timer for a fs that is local, unmounted and waits for
3942
4075
         * a device to be ready, before it can be mounted onto it. Timer on
3943
4076
         * only for fs not marked with a "nobootwait=1" */