summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/diskspace.c
diff options
context:
space:
mode:
authorDave Reisner <dreisner@archlinux.org>2012-04-29 21:00:38 +0200
committerDan McGee <dan@archlinux.org>2012-06-26 06:37:10 +0200
commite183522e3168c4a31103b3c7910fa8d29333fb5a (patch)
treeb95bd05a19eb44ffb16cdf0306a7d1579e064863 /lib/libalpm/diskspace.c
parent82c999a8bfbffab4740742b4746435f5f1657643 (diff)
downloadpacman-e183522e3168c4a31103b3c7910fa8d29333fb5a.tar.gz
pacman-e183522e3168c4a31103b3c7910fa8d29333fb5a.tar.xz
diskspace: only load filesystem info on demand
Only load filesystem details for the mount points that we're actually going to write to. This reduces our syscall count considerably. In the case of installation, we would actually stat every mountpoint twice (an extra round for download diskspace) which means (on my system) a total of 60 syscalls to write to 3 partitions when installing the kernel package. This change reduces the 60 syscalls down to the expected 3. A slight debug output change is added here to discern between a mountpoint added to our linked list versus when we actually load the fs info. Signed-off-by: Dave Reisner <dreisner@archlinux.org> Signed-off-by: Dan McGee <dan@archlinux.org>
Diffstat (limited to 'lib/libalpm/diskspace.c')
-rw-r--r--lib/libalpm/diskspace.c53
1 files changed, 40 insertions, 13 deletions
diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c
index 405bcd43..8fc4d9b0 100644
--- a/lib/libalpm/diskspace.c
+++ b/lib/libalpm/diskspace.c
@@ -69,22 +69,25 @@ static void mount_point_list_free(alpm_list_t *mount_points)
FREELIST(mount_points);
}
-#if defined(HAVE_GETMNTENT)
static int mount_point_load_fsinfo(alpm_handle_t *handle, alpm_mountpoint_t *mountpoint)
{
+#if defined(HAVE_GETMNTENT)
/* grab the filesystem usage */
if(statvfs(mountpoint->mount_dir, &(mountpoint->fsp)) != 0) {
_alpm_log(handle, ALPM_LOG_WARNING,
_("could not get filesystem information for %s: %s\n"),
mountpoint->mount_dir, strerror(errno));
+ mountpoint->fsinfo_loaded = MOUNT_FSINFO_FAIL;
return -1;
}
+ _alpm_log(handle, ALPM_LOG_DEBUG, "loading fsinfo for %s\n", mountpoint->mount_dir);
mountpoint->read_only = mountpoint->fsp.f_flag & ST_RDONLY;
+ mountpoint->fsinfo_loaded = MOUNT_FSINFO_LOADED;
+#endif
return 0;
}
-#endif
static alpm_list_t *mount_point_list(alpm_handle_t *handle)
{
@@ -106,11 +109,6 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
mp->mount_dir = strdup(mnt->mnt_dir);
mp->mount_dir_len = strlen(mp->mount_dir);
- if(mount_point_load_fsinfo(handle, mp) < 0) {
- free(mp->mount_dir);
- free(mp);
- continue;
- }
mount_points = alpm_list_add(mount_points, mp);
}
@@ -132,11 +130,6 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
mp->mount_dir = strdup(mnt->mnt_mountp);
mp->mount_dir_len = strlen(mp->mount_dir);
- if(mount_point_load_fsinfo(handle, mp) < 0) {
- free(mp->mount_dir);
- free(mp);
- continue;
- }
mount_points = alpm_list_add(mount_points, mp);
}
@@ -169,6 +162,9 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
mp->read_only = fsp->f_flags & MNT_RDONLY;
#endif
+ /* we don't support lazy loading on this platform */
+ mp->fsinfo_loaded = MOUNT_FSINFO_LOADED;
+
mount_points = alpm_list_add(mount_points, mp);
}
#endif
@@ -177,7 +173,7 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
mount_point_cmp);
for(ptr = mount_points; ptr != NULL; ptr = ptr->next) {
mp = ptr->data;
- _alpm_log(handle, ALPM_LOG_DEBUG, "mountpoint: %s\n", mp->mount_dir);
+ _alpm_log(handle, ALPM_LOG_DEBUG, "discovered mountpoint: %s\n", mp->mount_dir);
}
return mount_points;
}
@@ -245,6 +241,18 @@ static int calculate_removed_size(alpm_handle_t *handle,
continue;
}
+ /* don't check a mount that we know we can't stat */
+ if(mp && mp->fsinfo_loaded == MOUNT_FSINFO_FAIL) {
+ continue;
+ }
+
+ /* lazy load filesystem info */
+ if(mp->fsinfo_loaded == MOUNT_FSINFO_UNLOADED) {
+ if(mount_point_load_fsinfo(handle, mp) < 0) {
+ continue;
+ }
+ }
+
/* the addition of (divisor - 1) performs ceil() with integer division */
remove_size = (st.st_size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
mp->blocks_needed -= remove_size;
@@ -292,6 +300,18 @@ static int calculate_installed_size(alpm_handle_t *handle,
continue;
}
+ /* don't check a mount that we know we can't stat */
+ if(mp && mp->fsinfo_loaded == MOUNT_FSINFO_FAIL) {
+ continue;
+ }
+
+ /* lazy load filesystem info */
+ if(mp->fsinfo_loaded == MOUNT_FSINFO_UNLOADED) {
+ if(mount_point_load_fsinfo(handle, mp) < 0) {
+ continue;
+ }
+ }
+
/* the addition of (divisor - 1) performs ceil() with integer division */
install_size = (file->size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
mp->blocks_needed += install_size;
@@ -352,6 +372,13 @@ int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir,
goto finish;
}
+ if(cachedir_mp->fsinfo_loaded == MOUNT_FSINFO_UNLOADED) {
+ if(mount_point_load_fsinfo(handle, cachedir_mp)) {
+ error = 1;
+ goto finish;
+ }
+ }
+
/* there's no need to check for a R/O mounted filesystem here, as
* _alpm_filecache_setup will never give us a non-writable directory */