@@ -379,6 +379,8 @@ struct echo_client_obd {
/* allow statfs data caching for 1 second */
#define OBD_STATFS_CACHE_SECONDS 1
+/* arbitrary maximum. larger would be useless, allows catching bogus input */
+#define OBD_STATFS_CACHE_MAX_AGE 3600 /* seconds */
#define lov_tgt_desc lu_tgt_desc
@@ -952,13 +952,31 @@ static inline int obd_statfs(const struct lu_env *env, struct obd_export *exp,
if (obd->obd_osfs_age < max_age ||
((obd->obd_osfs.os_state & OS_STATE_SUM) &&
!(flags & OBD_STATFS_SUM))) {
- rc = OBP(obd, statfs)(env, exp, osfs, max_age, flags);
+ bool update_age = false;
+ /* the RPC will block anyway, so avoid sending many at once */
+ rc = mutex_lock_interruptible(&obd->obd_dev_mutex);
+ if (rc)
+ return rc;
+ if (obd->obd_osfs_age < max_age ||
+ ((obd->obd_osfs.os_state & OS_STATE_SUM) &&
+ !(flags & OBD_STATFS_SUM))) {
+ rc = OBP(obd, statfs)(env, exp, osfs, max_age, flags);
+ update_age = true;
+ } else {
+ CDEBUG(D_SUPER,
+ "%s: new %p cache blocks %llu/%llu objects %llu/%llu\n",
+ obd->obd_name, &obd->obd_osfs,
+ obd->obd_osfs.os_bavail, obd->obd_osfs.os_blocks,
+ obd->obd_osfs.os_ffree, obd->obd_osfs.os_files);
+ }
if (rc == 0) {
spin_lock(&obd->obd_osfs_lock);
memcpy(&obd->obd_osfs, osfs, sizeof(obd->obd_osfs));
- obd->obd_osfs_age = ktime_get_seconds();
+ if (update_age)
+ obd->obd_osfs_age = ktime_get_seconds();
spin_unlock(&obd->obd_osfs_lock);
}
+ mutex_unlock(&obd->obd_dev_mutex);
} else {
CDEBUG(D_SUPER,
"%s: use %p cache blocks %llu/%llu objects %llu/%llu\n",
@@ -568,6 +568,9 @@ struct ll_sb_info {
/* st_blksize returned by stat(2), when non-zero */
unsigned int ll_stat_blksize;
+ /* maximum relative age of cached statfs results */
+ unsigned int ll_statfs_max_age;
+
struct kset ll_kset; /* sysfs object */
struct completion ll_kobj_unregister;
@@ -87,6 +87,7 @@ static struct ll_sb_info *ll_init_sbi(void)
spin_lock_init(&sbi->ll_pp_extent_lock);
spin_lock_init(&sbi->ll_process_lock);
sbi->ll_rw_stats_on = 0;
+ sbi->ll_statfs_max_age = OBD_STATFS_CACHE_SECONDS;
si_meminfo(&si);
pages = si.totalram - si.totalhigh;
@@ -330,7 +331,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
* available
*/
err = obd_statfs(NULL, sbi->ll_md_exp, osfs,
- ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ ktime_get_seconds() - sbi->ll_statfs_max_age,
OBD_STATFS_FOR_MDT0);
if (err)
goto out_md_fid;
@@ -1860,7 +1861,7 @@ int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs,
time64_t max_age;
int rc;
- max_age = ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS;
+ max_age = ktime_get_seconds() - sbi->ll_statfs_max_age;
rc = obd_statfs(NULL, sbi->ll_md_exp, osfs, max_age, flags);
if (rc)
@@ -882,6 +882,36 @@ static ssize_t lazystatfs_store(struct kobject *kobj,
}
LUSTRE_RW_ATTR(lazystatfs);
+static ssize_t statfs_max_age_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
+ ll_kset.kobj);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", sbi->ll_statfs_max_age);
+}
+
+static ssize_t statfs_max_age_store(struct kobject *kobj,
+ struct attribute *attr, const char *buffer,
+ size_t count)
+{
+ struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
+ ll_kset.kobj);
+ unsigned int val;
+ int rc;
+
+ rc = kstrtouint(buffer, 10, &val);
+ if (rc)
+ return rc;
+ if (val > OBD_STATFS_CACHE_MAX_AGE)
+ return -EINVAL;
+
+ sbi->ll_statfs_max_age = val;
+
+ return count;
+}
+LUSTRE_RW_ATTR(statfs_max_age);
+
static ssize_t max_easize_show(struct kobject *kobj,
struct attribute *attr,
char *buf)
@@ -1480,6 +1510,7 @@ struct lprocfs_vars lprocfs_llite_obd_vars[] = {
&lustre_attr_statahead_max.attr,
&lustre_attr_statahead_agl.attr,
&lustre_attr_lazystatfs.attr,
+ &lustre_attr_statfs_max_age.attr,
&lustre_attr_max_easize.attr,
&lustre_attr_default_easize.attr,
&lustre_attr_xattr_cache.attr,