Skip to content

Commit 1c41a6a

Browse files
adilgerOleg Drokin
authored andcommitted
LU-12368 obdclass: don't send multiple statfs RPCs
If multiple threads are racing to send a non-cached OST_STATFS or MDS_STATFS RPC, this can cause a significant RPC storm for systems with many-core clients and many OSTs due to amplification of the requests, and the fact that STATFS RPCs are sent asynchronously. Some logs have shown few 96-core clients have 20k+ OST_STATFS RPCs in flight concurrently, which can overload the network if many OSTs are on the same OSS nodes (osc.*.max_rpcs_in_flight is per OST). This was not previously a significant issue when core counts were smaller on the clients, or with fewer OSTs per OSS. If a thread can't use the cached statfs values, limit statfs to one thread at a time, since the thread(s) would be blocked waiting for the RPC replies anyway, which can't finish faster if many are sent. Also add a llite.*.statfs_max_age parameter that can be tuned on to control the maximum age (in seconds) of the statfs cache. This can avoid overhead for workloads that are statfs heavy, given that the filesystem is _probably_ not running out of space this second, and even so "statfs" does not guarantee space in parallel workloads. Signed-off-by: Andreas Dilger <[email protected]> Change-Id: I95690e37aecbac08ac5768a5e5c6c70ca258a832 Reviewed-on: https://review.whamcloud.com/35380 Tested-by: jenkins <[email protected]> Reviewed-by: Patrick Farrell <[email protected]> Tested-by: Maloo <[email protected]> Reviewed-by: Alex Zhuravlev <[email protected]> Reviewed-by: Li Xi <[email protected]> Reviewed-by: Oleg Drokin <[email protected]>
1 parent da05018 commit 1c41a6a

File tree

5 files changed

+59
-4
lines changed

5 files changed

+59
-4
lines changed

lustre/include/obd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ struct echo_client_obd {
380380

381381
/* allow statfs data caching for 1 second */
382382
#define OBD_STATFS_CACHE_SECONDS 1
383+
/* arbitrary maximum. larger would be useless, allows catching bogus input */
384+
#define OBD_STATFS_CACHE_MAX_AGE 3600 /* seconds */
383385

384386
#define lov_tgt_desc lu_tgt_desc
385387

lustre/include/obd_class.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,13 +1058,31 @@ static inline int obd_statfs(const struct lu_env *env, struct obd_export *exp,
10581058
if (obd->obd_osfs_age < max_age ||
10591059
((obd->obd_osfs.os_state & OS_STATE_SUM) &&
10601060
!(flags & OBD_STATFS_SUM))) {
1061-
rc = OBP(obd, statfs)(env, exp, osfs, max_age, flags);
1061+
bool update_age = false;
1062+
/* the RPC will block anyway, so avoid sending many at once */
1063+
rc = mutex_lock_interruptible(&obd->obd_dev_mutex);
1064+
if (rc)
1065+
RETURN(rc);
1066+
if (obd->obd_osfs_age < max_age ||
1067+
((obd->obd_osfs.os_state & OS_STATE_SUM) &&
1068+
!(flags & OBD_STATFS_SUM))) {
1069+
rc = OBP(obd, statfs)(env, exp, osfs, max_age, flags);
1070+
update_age = true;
1071+
} else {
1072+
CDEBUG(D_SUPER,
1073+
"%s: new %p cache blocks %llu/%llu objects %llu/%llu\n",
1074+
obd->obd_name, &obd->obd_osfs,
1075+
obd->obd_osfs.os_bavail, obd->obd_osfs.os_blocks,
1076+
obd->obd_osfs.os_ffree, obd->obd_osfs.os_files);
1077+
}
10621078
if (rc == 0) {
10631079
spin_lock(&obd->obd_osfs_lock);
10641080
memcpy(&obd->obd_osfs, osfs, sizeof(obd->obd_osfs));
1065-
obd->obd_osfs_age = ktime_get_seconds();
1081+
if (update_age)
1082+
obd->obd_osfs_age = ktime_get_seconds();
10661083
spin_unlock(&obd->obd_osfs_lock);
10671084
}
1085+
mutex_unlock(&obd->obd_dev_mutex);
10681086
} else {
10691087
CDEBUG(D_SUPER,
10701088
"%s: use %p cache blocks %llu/%llu objects %llu/%llu\n",

lustre/llite/llite_internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,9 @@ struct ll_sb_info {
595595
/* st_blksize returned by stat(2), when non-zero */
596596
unsigned int ll_stat_blksize;
597597

598+
/* maximum relative age of cached statfs results */
599+
unsigned int ll_statfs_max_age;
600+
598601
struct kset ll_kset; /* sysfs object */
599602
struct completion ll_kobj_unregister;
600603

lustre/llite/llite_lib.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static struct ll_sb_info *ll_init_sbi(void)
9191
spin_lock_init(&sbi->ll_pp_extent_lock);
9292
spin_lock_init(&sbi->ll_process_lock);
9393
sbi->ll_rw_stats_on = 0;
94+
sbi->ll_statfs_max_age = OBD_STATFS_CACHE_SECONDS;
9495

9596
si_meminfo(&si);
9697
pages = si.totalram - si.totalhigh;
@@ -331,7 +332,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
331332
* can make sure the client can be mounted as long as MDT0 is
332333
* avaible */
333334
err = obd_statfs(NULL, sbi->ll_md_exp, osfs,
334-
ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
335+
ktime_get_seconds() - sbi->ll_statfs_max_age,
335336
OBD_STATFS_FOR_MDT0);
336337
if (err)
337338
GOTO(out_md_fid, err);
@@ -1938,7 +1939,7 @@ int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs,
19381939
int rc;
19391940

19401941
ENTRY;
1941-
max_age = ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS;
1942+
max_age = ktime_get_seconds() - sbi->ll_statfs_max_age;
19421943

19431944
rc = obd_statfs(NULL, sbi->ll_md_exp, osfs, max_age, flags);
19441945
if (rc)

lustre/llite/lproc_llite.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,36 @@ static ssize_t lazystatfs_store(struct kobject *kobj,
875875
}
876876
LUSTRE_RW_ATTR(lazystatfs);
877877

878+
static ssize_t statfs_max_age_show(struct kobject *kobj, struct attribute *attr,
879+
char *buf)
880+
{
881+
struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
882+
ll_kset.kobj);
883+
884+
return snprintf(buf, PAGE_SIZE, "%u\n", sbi->ll_statfs_max_age);
885+
}
886+
887+
static ssize_t statfs_max_age_store(struct kobject *kobj,
888+
struct attribute *attr, const char *buffer,
889+
size_t count)
890+
{
891+
struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
892+
ll_kset.kobj);
893+
unsigned int val;
894+
int rc;
895+
896+
rc = kstrtouint(buffer, 10, &val);
897+
if (rc)
898+
return rc;
899+
if (val > OBD_STATFS_CACHE_MAX_AGE)
900+
return -EINVAL;
901+
902+
sbi->ll_statfs_max_age = val;
903+
904+
return count;
905+
}
906+
LUSTRE_RW_ATTR(statfs_max_age);
907+
878908
static ssize_t max_easize_show(struct kobject *kobj,
879909
struct attribute *attr,
880910
char *buf)
@@ -1477,6 +1507,7 @@ static struct attribute *llite_attrs[] = {
14771507
&lustre_attr_statahead_max.attr,
14781508
&lustre_attr_statahead_agl.attr,
14791509
&lustre_attr_lazystatfs.attr,
1510+
&lustre_attr_statfs_max_age.attr,
14801511
&lustre_attr_max_easize.attr,
14811512
&lustre_attr_default_easize.attr,
14821513
&lustre_attr_xattr_cache.attr,

0 commit comments

Comments
 (0)