summaryrefslogtreecommitdiff
path: root/src/du.c
diff options
context:
space:
mode:
authorBernhard Voelker <mail@bernhard-voelker.de>2015-09-18 13:29:17 +0200
committerBernhard Voelker <mail@bernhard-voelker.de>2015-09-18 13:29:17 +0200
commitd4a22dff9b4cd8b05cb01e654fa84b189d3b5721 (patch)
treef9af93dd8a618a70c85b4baf2f7e3e52145de076 /src/du.c
parente4d8c99436587b5186b145b6654edaa00eb5a8b8 (diff)
downloadcoreutils-d4a22dff9b4cd8b05cb01e654fa84b189d3b5721.tar.gz
du: avoid to stat all mount points if possible
du calls stat for each 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. Issue 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.
Diffstat (limited to 'src/du.c')
-rw-r--r--src/du.c74
1 files changed, 39 insertions, 35 deletions
diff --git a/src/du.c b/src/du.c
index 86827f808..30378e552 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));