From 9490fd9bb84dc277bd103bf16286fc26882e5b5e Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Mon, 7 Dec 2020 23:54:58 -0700 Subject: [PATCH] LU-13601 llite: avoid needless large stats alloc Allocate the ll_rw_extents_info (5896 bytes), ll_rw_offset_info (6400 bytes), and ll_rw_process_info (640 bytes) structs only when these stats are enabled, which is very rarely. Signed-off-by: Andreas Dilger Change-Id: I59bbfce8d7f2422d810617d5fa712a67333ebbe5 Signed-off-by: Alexander Zarochentsev Reviewed-on: https://review.whamcloud.com/40901 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin --- lustre/llite/llite_internal.h | 9 +- lustre/llite/llite_lib.c | 9 +- lustre/llite/lproc_llite.c | 364 +++++++++++++++++++++++++++--------------- 3 files changed, 243 insertions(+), 139 deletions(-) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 7d27214..3f06e46 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -703,15 +703,15 @@ struct ll_sb_info { struct cl_device *ll_cl; /* Statistics */ - struct ll_rw_extents_info ll_rw_extents_info; + struct ll_rw_extents_info *ll_rw_extents_info; int ll_extent_process_count; unsigned int ll_offset_process_count; + struct ll_rw_process_info *ll_rw_process_info; + struct ll_rw_process_info *ll_rw_offset_info; ktime_t ll_process_stats_init; - struct ll_rw_process_info ll_rw_process_info[LL_PROCESS_HIST_MAX]; - struct ll_rw_process_info ll_rw_offset_info[LL_OFFSET_HIST_MAX]; unsigned int ll_rw_offset_entry_count; int ll_stats_track_id; - enum stats_track_type ll_stats_track_type; + enum stats_track_type ll_stats_track_type; int ll_rw_stats_on; /* metadata stat-ahead */ @@ -984,6 +984,7 @@ void cl_put_grouplock(struct ll_grouplock *lg); int ll_debugfs_register_super(struct super_block *sb, const char *name); void ll_debugfs_unregister_super(struct super_block *sb); void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, long count); +void ll_free_rw_stats_info(struct ll_sb_info *sbi); enum { LPROC_LL_READ_BYTES, diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 87ccf1b..a60739e 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -92,7 +92,6 @@ static struct ll_sb_info *ll_init_sbi(void) unsigned long lru_page_max; struct sysinfo si; int rc; - int i; ENTRY; @@ -171,13 +170,6 @@ static struct ll_sb_info *ll_init_sbi(void) #endif set_bit(LL_SBI_LAZYSTATFS, sbi->ll_flags); - for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) { - spin_lock_init(&sbi->ll_rw_extents_info.pp_extents[i]. - pp_r_hist.oh_lock); - spin_lock_init(&sbi->ll_rw_extents_info.pp_extents[i]. - pp_w_hist.oh_lock); - } - /* metadata statahead is enabled by default */ sbi->ll_sa_running_max = LL_SA_RUNNING_DEF; sbi->ll_sa_max = LL_SA_RPC_DEF; @@ -261,6 +253,7 @@ static void ll_free_sbi(struct super_block *sb) sizeof(struct ll_foreign_symlink_upcall_item)); sbi->ll_foreign_symlink_upcall_items = NULL; } + ll_free_rw_stats_info(sbi); pcc_super_fini(&sbi->ll_pcc_super); OBD_FREE(sbi, sizeof(*sbi)); } diff --git a/lustre/llite/lproc_llite.c b/lustre/llite/lproc_llite.c index 4b4d270..29493ab 100644 --- a/lustre/llite/lproc_llite.c +++ b/lustre/llite/lproc_llite.c @@ -1912,25 +1912,26 @@ void ll_debugfs_unregister_super(struct super_block *sb) } #undef MAX_STRING_SIZE -static void ll_display_extents_info(struct ll_rw_extents_info *io_extents, - struct seq_file *seq, int which) -{ - unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum; - unsigned long start, end, r, w; - char *unitp = "KMGTPEZY"; - int i, units = 10; - struct per_process_info *pp_info = &io_extents->pp_extents[which]; - - read_cum = 0; - write_cum = 0; - start = 0; - - for(i = 0; i < LL_HIST_MAX; i++) { - read_tot += pp_info->pp_r_hist.oh_buckets[i]; - write_tot += pp_info->pp_w_hist.oh_buckets[i]; - } +static void ll_display_extents_info(struct ll_rw_extents_info *rw_extents, + struct seq_file *seq, int which) +{ + unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum; + unsigned long start, end, r, w; + char *unitp = "KMGTPEZY"; + int i, units = 10; + struct per_process_info *pp_info; + + pp_info = &rw_extents->pp_extents[which]; + read_cum = 0; + write_cum = 0; + start = 0; + + for (i = 0; i < LL_HIST_MAX; i++) { + read_tot += pp_info->pp_r_hist.oh_buckets[i]; + write_tot += pp_info->pp_w_hist.oh_buckets[i]; + } - for(i = 0; i < LL_HIST_MAX; i++) { + for (i = 0; i < LL_HIST_MAX; i++) { r = pp_info->pp_r_hist.oh_buckets[i]; w = pp_info->pp_w_hist.oh_buckets[i]; read_cum += r; @@ -1955,38 +1956,107 @@ static void ll_display_extents_info(struct ll_rw_extents_info *io_extents, static int ll_rw_extents_stats_pp_seq_show(struct seq_file *seq, void *v) { struct ll_sb_info *sbi = seq->private; - struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info; + struct ll_rw_extents_info *rw_extents = sbi->ll_rw_extents_info; int k; - if (!sbi->ll_rw_stats_on) { + if (!sbi->ll_rw_stats_on || !rw_extents) { seq_puts(seq, "disabled\n write anything to this file to activate, then '0' or 'disable' to deactivate\n"); return 0; } - lprocfs_stats_header(seq, ktime_get(), io_extents->pp_init, 25, ":", 1); + + spin_lock(&sbi->ll_pp_extent_lock); + lprocfs_stats_header(seq, ktime_get(), rw_extents->pp_init, 25, ":", 1); seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write"); seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n", - "extents", "calls", "%", "cum%", - "calls", "%", "cum%"); - spin_lock(&sbi->ll_pp_extent_lock); + "extents", "calls", "%", "cum%", "calls", "%", "cum%"); + for (k = 0; k < LL_PROCESS_HIST_MAX; k++) { - if (io_extents->pp_extents[k].pid != 0) { + if (rw_extents->pp_extents[k].pid != 0) { seq_printf(seq, "\nPID: %d\n", - io_extents->pp_extents[k].pid); - ll_display_extents_info(io_extents, seq, k); + rw_extents->pp_extents[k].pid); + ll_display_extents_info(rw_extents, seq, k); } } spin_unlock(&sbi->ll_pp_extent_lock); return 0; } +static int alloc_rw_stats_info(struct ll_sb_info *sbi) +{ + struct ll_rw_extents_info *rw_extents; + struct ll_rw_process_info *offset; + struct ll_rw_process_info *process; + int i, rc = 0; + + OBD_ALLOC(rw_extents, sizeof(*rw_extents)); + if (!rw_extents) + return -ENOMEM; + + for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) { + spin_lock_init(&rw_extents->pp_extents[i].pp_r_hist.oh_lock); + spin_lock_init(&rw_extents->pp_extents[i].pp_w_hist.oh_lock); + } + + spin_lock(&sbi->ll_pp_extent_lock); + if (!sbi->ll_rw_extents_info) + sbi->ll_rw_extents_info = rw_extents; + spin_unlock(&sbi->ll_pp_extent_lock); + /* another writer allocated the struct before we got the lock */ + if (sbi->ll_rw_extents_info != rw_extents) + OBD_FREE(rw_extents, sizeof(*rw_extents)); + + OBD_ALLOC(process, sizeof(*process) * LL_PROCESS_HIST_MAX); + if (!process) + GOTO(out, rc = -ENOMEM); + OBD_ALLOC(offset, sizeof(*offset) * LL_OFFSET_HIST_MAX); + if (!offset) + GOTO(out_free, rc = -ENOMEM); + + spin_lock(&sbi->ll_process_lock); + if (!sbi->ll_rw_process_info) + sbi->ll_rw_process_info = process; + if (!sbi->ll_rw_offset_info) + sbi->ll_rw_offset_info = offset; + spin_unlock(&sbi->ll_process_lock); + + /* another writer allocated the structs before we got the lock */ + if (sbi->ll_rw_offset_info != offset) + OBD_FREE(offset, sizeof(*offset) * LL_OFFSET_HIST_MAX); + if (sbi->ll_rw_process_info != process) { +out_free: + OBD_FREE(process, sizeof(*process) * LL_PROCESS_HIST_MAX); + } + +out: + return rc; +} + +void ll_free_rw_stats_info(struct ll_sb_info *sbi) +{ + if (sbi->ll_rw_extents_info) { + OBD_FREE(sbi->ll_rw_extents_info, + sizeof(*sbi->ll_rw_extents_info)); + sbi->ll_rw_extents_info = NULL; + } + if (sbi->ll_rw_offset_info) { + OBD_FREE(sbi->ll_rw_offset_info, + sizeof(*sbi->ll_rw_offset_info) * LL_OFFSET_HIST_MAX); + sbi->ll_rw_offset_info = NULL; + } + if (sbi->ll_rw_process_info) { + OBD_FREE(sbi->ll_rw_process_info, + sizeof(*sbi->ll_rw_process_info) * LL_PROCESS_HIST_MAX); + sbi->ll_rw_process_info = NULL; + } +} + static ssize_t ll_rw_extents_stats_pp_seq_write(struct file *file, const char __user *buf, - size_t len, - loff_t *off) + size_t len, loff_t *off) { struct seq_file *seq = file->private_data; struct ll_sb_info *sbi = seq->private; - struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info; + struct ll_rw_extents_info *rw_extents; int i; __s64 value; @@ -1995,19 +2065,31 @@ static ssize_t ll_rw_extents_stats_pp_seq_write(struct file *file, value = ll_stats_pid_write(buf, len); - if (value == 0) + if (value == 0) { sbi->ll_rw_stats_on = 0; - else + } else { + if (!sbi->ll_rw_extents_info) { + int rc = alloc_rw_stats_info(sbi); + + if (rc) + return rc; + } sbi->ll_rw_stats_on = 1; + } + spin_lock(&sbi->ll_pp_extent_lock); - io_extents->pp_init = ktime_get(); - for (i = 0; i < LL_PROCESS_HIST_MAX; i++) { - io_extents->pp_extents[i].pid = 0; - lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist); - lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist); + rw_extents = sbi->ll_rw_extents_info; + if (rw_extents) { + rw_extents->pp_init = ktime_get(); + for (i = 0; i < LL_PROCESS_HIST_MAX; i++) { + rw_extents->pp_extents[i].pid = 0; + lprocfs_oh_clear(&rw_extents->pp_extents[i].pp_r_hist); + lprocfs_oh_clear(&rw_extents->pp_extents[i].pp_w_hist); + } } spin_unlock(&sbi->ll_pp_extent_lock); + return len; } @@ -2016,21 +2098,22 @@ LDEBUGFS_SEQ_FOPS(ll_rw_extents_stats_pp); static int ll_rw_extents_stats_seq_show(struct seq_file *seq, void *v) { struct ll_sb_info *sbi = seq->private; - struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info; + struct ll_rw_extents_info *rw_extents = sbi->ll_rw_extents_info; - if (!sbi->ll_rw_stats_on) { + if (!sbi->ll_rw_stats_on || !rw_extents) { seq_puts(seq, "disabled\n write anything to this file to activate, then '0' or 'disable' to deactivate\n"); return 0; } - lprocfs_stats_header(seq, ktime_get(), io_extents->pp_init, 25, ":", 1); + spin_lock(&sbi->ll_lock); + lprocfs_stats_header(seq, ktime_get(), rw_extents->pp_init, 25, ":", 1); seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write"); seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n", "extents", "calls", "%", "cum%", "calls", "%", "cum%"); - spin_lock(&sbi->ll_lock); - ll_display_extents_info(io_extents, seq, LL_PROCESS_HIST_MAX); + + ll_display_extents_info(rw_extents, seq, LL_PROCESS_HIST_MAX); spin_unlock(&sbi->ll_lock); return 0; @@ -2042,7 +2125,7 @@ static ssize_t ll_rw_extents_stats_seq_write(struct file *file, { struct seq_file *seq = file->private_data; struct ll_sb_info *sbi = seq->private; - struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info; + struct ll_rw_extents_info *rw_extents; int i; __s64 value; @@ -2051,17 +2134,27 @@ static ssize_t ll_rw_extents_stats_seq_write(struct file *file, value = ll_stats_pid_write(buf, len); - if (value == 0) + if (value == 0) { sbi->ll_rw_stats_on = 0; - else + } else { + if (!sbi->ll_rw_extents_info) { + int rc = alloc_rw_stats_info(sbi); + + if (rc) + return rc; + } sbi->ll_rw_stats_on = 1; + } spin_lock(&sbi->ll_pp_extent_lock); - io_extents->pp_init = ktime_get(); - for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) { - io_extents->pp_extents[i].pid = 0; - lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist); - lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist); + rw_extents = sbi->ll_rw_extents_info; + if (rw_extents) { + rw_extents->pp_init = ktime_get(); + for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) { + rw_extents->pp_extents[i].pid = 0; + lprocfs_oh_clear(&rw_extents->pp_extents[i].pp_r_hist); + lprocfs_oh_clear(&rw_extents->pp_extents[i].pp_w_hist); + } } spin_unlock(&sbi->ll_pp_extent_lock); @@ -2071,65 +2164,73 @@ static ssize_t ll_rw_extents_stats_seq_write(struct file *file, LDEBUGFS_SEQ_FOPS(ll_rw_extents_stats); void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid, - struct ll_file_data *file, loff_t pos, - size_t count, int rw) + struct ll_file_data *file, loff_t pos, + size_t count, int rw) { - int i, cur = -1; - struct ll_rw_process_info *process; - struct ll_rw_process_info *offset; - int *off_count = &sbi->ll_rw_offset_entry_count; - int *process_count = &sbi->ll_offset_process_count; - struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info; + int i, cur = -1; + struct ll_rw_process_info *process; + struct ll_rw_process_info *offset; + int *off_count = &sbi->ll_rw_offset_entry_count; + int *process_count = &sbi->ll_offset_process_count; + struct ll_rw_extents_info *rw_extents; - if(!sbi->ll_rw_stats_on) - return; - process = sbi->ll_rw_process_info; - offset = sbi->ll_rw_offset_info; + if (!sbi->ll_rw_stats_on) + return; spin_lock(&sbi->ll_pp_extent_lock); - /* Extent statistics */ - for(i = 0; i < LL_PROCESS_HIST_MAX; i++) { - if(io_extents->pp_extents[i].pid == pid) { - cur = i; - break; - } - } - - if (cur == -1) { - /* new process */ - sbi->ll_extent_process_count = - (sbi->ll_extent_process_count + 1) % LL_PROCESS_HIST_MAX; - cur = sbi->ll_extent_process_count; - io_extents->pp_extents[cur].pid = pid; - lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_r_hist); - lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_w_hist); - } + rw_extents = sbi->ll_rw_extents_info; + if (!rw_extents) { + spin_unlock(&sbi->ll_pp_extent_lock); + return; + } + + /* Extent statistics */ + for (i = 0; i < LL_PROCESS_HIST_MAX; i++) { + if (rw_extents->pp_extents[i].pid == pid) { + cur = i; + break; + } + } + + if (cur == -1) { + /* new process */ + sbi->ll_extent_process_count = + (sbi->ll_extent_process_count + 1) % LL_PROCESS_HIST_MAX; + cur = sbi->ll_extent_process_count; + rw_extents->pp_extents[cur].pid = pid; + lprocfs_oh_clear(&rw_extents->pp_extents[cur].pp_r_hist); + lprocfs_oh_clear(&rw_extents->pp_extents[cur].pp_w_hist); + } for (i = 0; (count >= 1 << (LL_HIST_START + i)) && (i < (LL_HIST_MAX - 1)); i++); if (rw == 0) { - io_extents->pp_extents[cur].pp_r_hist.oh_buckets[i]++; - io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_r_hist.oh_buckets[i]++; + rw_extents->pp_extents[cur].pp_r_hist.oh_buckets[i]++; + rw_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_r_hist.oh_buckets[i]++; } else { - io_extents->pp_extents[cur].pp_w_hist.oh_buckets[i]++; - io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_w_hist.oh_buckets[i]++; + rw_extents->pp_extents[cur].pp_w_hist.oh_buckets[i]++; + rw_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_w_hist.oh_buckets[i]++; } spin_unlock(&sbi->ll_pp_extent_lock); spin_lock(&sbi->ll_process_lock); - /* Offset statistics */ - for (i = 0; i < LL_PROCESS_HIST_MAX; i++) { - if (process[i].rw_pid == pid) { - if (process[i].rw_last_file != file) { - process[i].rw_range_start = pos; - process[i].rw_last_file_pos = pos + count; - process[i].rw_smallest_extent = count; - process[i].rw_largest_extent = count; - process[i].rw_offset = 0; - process[i].rw_last_file = file; - spin_unlock(&sbi->ll_process_lock); - return; - } + process = sbi->ll_rw_process_info; + offset = sbi->ll_rw_offset_info; + if (!process || !offset) + goto out_unlock; + + /* Offset statistics */ + for (i = 0; i < LL_PROCESS_HIST_MAX; i++) { + if (process[i].rw_pid == pid) { + if (process[i].rw_last_file != file) { + process[i].rw_range_start = pos; + process[i].rw_last_file_pos = pos + count; + process[i].rw_smallest_extent = count; + process[i].rw_largest_extent = count; + process[i].rw_offset = 0; + process[i].rw_last_file = file; + goto out_unlock; + } if (process[i].rw_last_file_pos != pos) { *off_count = (*off_count + 1) % LL_OFFSET_HIST_MAX; @@ -2152,32 +2253,33 @@ void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid, process[i].rw_offset = pos - process[i].rw_last_file_pos; } - if(process[i].rw_smallest_extent > count) - process[i].rw_smallest_extent = count; - if(process[i].rw_largest_extent < count) - process[i].rw_largest_extent = count; - process[i].rw_last_file_pos = pos + count; - spin_unlock(&sbi->ll_process_lock); - return; - } - } - *process_count = (*process_count + 1) % LL_PROCESS_HIST_MAX; - process[*process_count].rw_pid = pid; - process[*process_count].rw_op = rw; - process[*process_count].rw_range_start = pos; - process[*process_count].rw_last_file_pos = pos + count; - process[*process_count].rw_smallest_extent = count; - process[*process_count].rw_largest_extent = count; - process[*process_count].rw_offset = 0; - process[*process_count].rw_last_file = file; + if (process[i].rw_smallest_extent > count) + process[i].rw_smallest_extent = count; + if (process[i].rw_largest_extent < count) + process[i].rw_largest_extent = count; + process[i].rw_last_file_pos = pos + count; + goto out_unlock; + } + } + *process_count = (*process_count + 1) % LL_PROCESS_HIST_MAX; + process[*process_count].rw_pid = pid; + process[*process_count].rw_op = rw; + process[*process_count].rw_range_start = pos; + process[*process_count].rw_last_file_pos = pos + count; + process[*process_count].rw_smallest_extent = count; + process[*process_count].rw_largest_extent = count; + process[*process_count].rw_offset = 0; + process[*process_count].rw_last_file = file; + +out_unlock: spin_unlock(&sbi->ll_process_lock); } static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v) { struct ll_sb_info *sbi = seq->private; - struct ll_rw_process_info *offset = sbi->ll_rw_offset_info; - struct ll_rw_process_info *process = sbi->ll_rw_process_info; + struct ll_rw_process_info *offset; + struct ll_rw_process_info *process; int i; if (!sbi->ll_rw_stats_on) { @@ -2188,13 +2290,13 @@ static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v) spin_lock(&sbi->ll_process_lock); lprocfs_stats_header(seq, ktime_get(), sbi->ll_process_stats_init, 25, ":", true); - seq_printf(seq, "%3s %10s %14s %14s %17s %17s %14s\n", "R/W", "PID", "RANGE START", "RANGE END", "SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET"); /* We stored the discontiguous offsets here; print them first */ - for (i = 0; i < LL_OFFSET_HIST_MAX; i++) { + offset = sbi->ll_rw_offset_info; + for (i = 0; offset && i < LL_OFFSET_HIST_MAX; i++) { if (offset[i].rw_pid != 0) seq_printf(seq, "%3c %10d %14llu %14llu %17lu %17lu %14lld\n", @@ -2208,7 +2310,8 @@ static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v) } /* Then print the current offsets for each process */ - for (i = 0; i < LL_PROCESS_HIST_MAX; i++) { + process = sbi->ll_rw_process_info; + for (i = 0; process && i < LL_PROCESS_HIST_MAX; i++) { if (process[i].rw_pid != 0) seq_printf(seq, "%3c %10d %14llu %14llu %17lu %17lu %14lld\n", @@ -2231,8 +2334,6 @@ static ssize_t ll_rw_offset_stats_seq_write(struct file *file, { struct seq_file *seq = file->private_data; struct ll_sb_info *sbi = seq->private; - struct ll_rw_process_info *process_info = sbi->ll_rw_process_info; - struct ll_rw_process_info *offset_info = sbi->ll_rw_offset_info; __s64 value; if (len == 0) @@ -2240,19 +2341,28 @@ static ssize_t ll_rw_offset_stats_seq_write(struct file *file, value = ll_stats_pid_write(buf, len); - if (value == 0) + if (value == 0) { sbi->ll_rw_stats_on = 0; - else + } else { + if (!sbi->ll_rw_process_info || !sbi->ll_rw_offset_info) { + int rc = alloc_rw_stats_info(sbi); + + if (rc) + return rc; + } sbi->ll_rw_stats_on = 1; + } spin_lock(&sbi->ll_process_lock); sbi->ll_offset_process_count = 0; sbi->ll_rw_offset_entry_count = 0; sbi->ll_process_stats_init = ktime_get(); - memset(process_info, 0, sizeof(struct ll_rw_process_info) * - LL_PROCESS_HIST_MAX); - memset(offset_info, 0, sizeof(struct ll_rw_process_info) * - LL_OFFSET_HIST_MAX); + if (sbi->ll_rw_process_info) + memset(sbi->ll_rw_process_info, 0, + sizeof(struct ll_rw_process_info) * LL_PROCESS_HIST_MAX); + if (sbi->ll_rw_offset_info) + memset(sbi->ll_rw_offset_info, 0, + sizeof(struct ll_rw_process_info) * LL_OFFSET_HIST_MAX); spin_unlock(&sbi->ll_process_lock); return len; -- 1.8.3.1