>From 21d983eac2cb2b955fae7cda3c723a18736ba3d8 Mon Sep 17 00:00:00 2001 From: Fridolin Pokorny Date: Wed, 27 Aug 2014 15:00:14 +0200 Subject: [PATCH] df: avoid stat()s when using /proc//mountinfo * src/df.c (filter_mount_list, get_dev): Use stat() only if device ID is not known. It could be propagated from gnulib when /proc//mountinfo is used. There was added new argument for get_dev() to enable device ID propagation. --- src/df.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/df.c b/src/df.c index e907b94..156c7c1 100644 --- a/src/df.c +++ b/src/df.c @@ -622,11 +622,11 @@ filter_mount_list (bool devices_only) struct devlist *devlist; struct mount_entry *discard_me = NULL; - /* TODO: On Linux we might avoid this stat() and another in get_dev() - by using the device IDs available from /proc/self/mountinfo. - read_file_system_list() could populate me_dev from those - for efficiency and accuracy. */ +#ifdef _linux_ + if (me->me_dev == (dev_t) -1 && stat (me->me_mountdir, &buf) == -1) +#else if (-1 == stat (me->me_mountdir, &buf)) +#endif { /* Stat failed - add ME to be able to complain about it later. */ buf.st_dev = me->me_dev; @@ -870,13 +870,14 @@ add_to_grand_total (struct field_values_t *bv, struct field_values_t *iv) If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may not be able to produce statistics in this case. ME_DUMMY and ME_REMOTE are the mount entry flags. + ME_DEV is mount entry device id or -1. Caller must set PROCESS_ALL to true when iterating over all entries, as when df is invoked with no non-option argument. See below for details. */ static void get_dev (char const *disk, char const *mount_point, char const* file, char const *stat_file, char const *fstype, - bool me_dummy, bool me_remote, + bool me_dummy, bool me_remote, dev_t me_dev, const struct fs_usage *force_fsu, bool process_all) { @@ -930,9 +931,15 @@ get_dev (char const *disk, char const *mount_point, char const* file, /* Ensure we don't output incorrect stats for over-mounted directories. Discard stats when the device name doesn't match. */ struct stat sb; +#ifdef _linux_ + if (me_dev != (dev_t) -1 || stat (stat_file, &sb) == 0) + { +#else if (stat (stat_file, &sb) == 0) { - char const * devname = devname_for_dev (sb.st_dev); + me_dev = sb.st_dev; +#endif + char const * devname = devname_for_dev (me_dev); if (devname && ! STREQ (devname, disk)) { fstype = "-"; @@ -1212,7 +1219,7 @@ get_disk (char const *disk) { get_dev (best_match->me_devname, best_match->me_mountdir, file, NULL, best_match->me_type, best_match->me_dummy, - best_match->me_remote, NULL, false); + best_match->me_remote, best_match->me_dev, NULL, false); return true; } else if (eclipsed_device) @@ -1307,7 +1314,7 @@ get_point (const char *point, const struct stat *statp) if (best_match) get_dev (best_match->me_devname, best_match->me_mountdir, point, point, best_match->me_type, best_match->me_dummy, best_match->me_remote, - NULL, false); + best_match->me_dev, NULL, false); else { /* We couldn't find the mount entry corresponding to POINT. Go ahead and @@ -1318,7 +1325,8 @@ get_point (const char *point, const struct stat *statp) char *mp = find_mount_point (point, statp); if (mp) { - get_dev (NULL, mp, point, NULL, NULL, false, false, NULL, false); + get_dev (NULL, mp, point, NULL, NULL, false, false, + (dev_t) -1, NULL, false); free (mp); } } @@ -1349,7 +1357,7 @@ get_all_entries (void) for (me = mount_list; me; me = me->me_next) get_dev (me->me_devname, me->me_mountdir, NULL, NULL, me->me_type, - me->me_dummy, me->me_remote, NULL, true); + me->me_dummy, me->me_remote, me->me_dev, NULL, true); } /* Add FSTYPE to the list of file system types to display. */ @@ -1699,8 +1707,8 @@ main (int argc, char **argv) { if (print_grand_total) get_dev ("total", - (field_data[SOURCE_FIELD].used ? "-" : "total"), - NULL, NULL, NULL, false, false, &grand_fsu, false); + (field_data[SOURCE_FIELD].used ? "-" : "total"), NULL, + NULL, NULL, false, false, (dev_t) -1, &grand_fsu, false); print_table (); } -- 1.9.3