On 09/18/2015 05:30 AM, adavies42 wrote: > somewhere between 8.12 and 8.20, du seems to have acquired the behavior of > stat'ing all mountpoints during its startup > > why does it do this? it seems to have no connection to what's being du'd, and > if stat blocks on one of the mountpoints (e.g. in some FUSE failure > scenarios), it means the entire du run blocks, even if the broken mount has > no connection to what i'm actually trying to do >
Thanks for the report. Indeed, the stat()ing of all mount points can easily be avoided by doing it only when needed, i.e., when FTS has detected a directory cycle (FTS_DC). The attached does this. Would you mind giving us your name so that I can mention it as "Reported by: ..."? Have a nice day, Berny
>From 1891ae62a2843aa23ff5e8b05826aa524d27c7d5 Mon Sep 17 00:00:00 2001 From: Bernhard Voelker <[email protected]> Date: Fri, 18 Sep 2015 09:20:38 +0200 Subject: [PATCH] du: avoid to stat all mount points if possible du makes stat calls for every mount point at startup. This would block or even make du fail if stat for an unrelated mount point hangs. The result is not needed in the normal case anyway and therefore should be avoided. Regression introduced in commit v8.19-2-gcf7e1b5. * src/du.c (fill_mount_table): Move function up as it's not used ... (mount_point_in_fts_cycle): ... here, i.e., the DI_MNT set is initialized and filled only iff FTS has detected a directory cycle. (main): Remove the initialization and filling of the DI_MNT set here, and free the DI_MNT set only if it was used. --- NEWS | 6 ++++++ src/du.c | 74 ++++++++++++++++++++++++++++++++++------------------------------ 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/NEWS b/NEWS index 33414c4..9829582 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,12 @@ GNU coreutils NEWS -*- outline -*- base64 no longer supports hex or oct --wrap parameters, thus better supporting decimals with leading zeros. +** Improvements + + do now avoids to stat all mount points at startup, and only does it + when needed, i.e., when FTS has detected a directory cycle. + [bug introduced in coreutils-8.20] + * Noteworthy changes in release 8.24 (2015-07-03) [stable] diff --git a/src/du.c b/src/du.c index 86827f8..30378e5 100644 --- a/src/du.c +++ b/src/du.c @@ -419,6 +419,33 @@ print_size (const struct duinfo *pdui, const char *string) fflush (stdout); } +/* Fill the di_mnt set with local mount point dev/ino pairs. */ + +static void +fill_mount_table (void) +{ + struct mount_entry *mnt_ent = read_file_system_list (false); + while (mnt_ent) + { + struct mount_entry *mnt_free; + if (!mnt_ent->me_remote && !mnt_ent->me_dummy) + { + struct stat buf; + if (!stat (mnt_ent->me_mountdir, &buf)) + hash_ins (di_mnt, buf.st_ino, buf.st_dev); + else + { + /* Ignore stat failure. False positives are too common. + E.g., "Permission denied" on /run/user/<name>/gvfs. */ + } + } + + mnt_free = mnt_ent; + mnt_ent = mnt_ent->me_next; + free_mount_entry (mnt_free); + } +} + /* This function checks whether any of the directories in the cycle that fts detected is a mount point. */ @@ -427,6 +454,16 @@ mount_point_in_fts_cycle (FTSENT const *ent) { FTSENT const *cycle_ent = ent->fts_cycle; + if (!di_mnt) + { + /* Initialize the set of dev,inode pairs. */ + di_mnt = di_set_alloc (); + if (!di_mnt) + xalloc_die (); + + fill_mount_table (); + } + while (ent && ent != cycle_ent) { if (di_set_lookup (di_mnt, ent->fts_statp->st_dev, @@ -680,33 +717,6 @@ du_files (char **files, int bit_flags) return ok; } -/* Fill the di_mnt set with local mount point dev/ino pairs. */ - -static void -fill_mount_table (void) -{ - struct mount_entry *mnt_ent = read_file_system_list (false); - while (mnt_ent) - { - struct mount_entry *mnt_free; - if (!mnt_ent->me_remote && !mnt_ent->me_dummy) - { - struct stat buf; - if (!stat (mnt_ent->me_mountdir, &buf)) - hash_ins (di_mnt, buf.st_ino, buf.st_dev); - else - { - /* Ignore stat failure. False positives are too common. - E.g., "Permission denied" on /run/user/<name>/gvfs. */ - } - } - - mnt_free = mnt_ent; - mnt_ent = mnt_ent->me_next; - free_mount_entry (mnt_free); - } -} - int main (int argc, char **argv) { @@ -1034,13 +1044,6 @@ main (int argc, char **argv) xalloc_die (); /* Initialize the set of dev,inode pairs. */ - - di_mnt = di_set_alloc (); - if (!di_mnt) - xalloc_die (); - - fill_mount_table (); - di_files = di_set_alloc (); if (!di_files) xalloc_die (); @@ -1121,7 +1124,8 @@ main (int argc, char **argv) argv_iter_free (ai); di_set_free (di_files); - di_set_free (di_mnt); + if (di_mnt) + di_set_free (di_mnt); if (files_from && (ferror (stdin) || fclose (stdin) != 0) && ok) error (EXIT_FAILURE, 0, _("error reading %s"), quote (files_from)); -- 2.1.4
