Merge tag 'f2fs-for-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeu...
[linux-2.6-microblaze.git] / fs / f2fs / sysfs.c
index daad532..a32fe31 100644 (file)
@@ -17,6 +17,7 @@
 #include "f2fs.h"
 #include "segment.h"
 #include "gc.h"
+#include "iostat.h"
 #include <trace/events/f2fs.h>
 
 static struct proc_dir_entry *f2fs_proc_root;
@@ -307,6 +308,14 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
                return sysfs_emit(buf, "%u\n", sbi->compr_new_inode);
 #endif
 
+       if (!strcmp(a->attr.name, "gc_segment_mode"))
+               return sysfs_emit(buf, "%u\n", sbi->gc_segment_mode);
+
+       if (!strcmp(a->attr.name, "gc_reclaimed_segments")) {
+               return sysfs_emit(buf, "%u\n",
+                       sbi->gc_reclaimed_segs[sbi->gc_segment_mode]);
+       }
+
        ui = (unsigned int *)(ptr + a->offset);
 
        return sprintf(buf, "%u\n", *ui);
@@ -343,7 +352,7 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
                        set = false;
                }
 
-               if (strlen(name) >= F2FS_EXTENSION_LEN)
+               if (!strlen(name) || strlen(name) >= F2FS_EXTENSION_LEN)
                        return -EINVAL;
 
                down_write(&sbi->sb_lock);
@@ -420,6 +429,8 @@ out:
        if (!strcmp(a->attr.name, "discard_granularity")) {
                if (t == 0 || t > MAX_PLIST_NUM)
                        return -EINVAL;
+               if (!f2fs_block_unit_discard(sbi))
+                       return -EINVAL;
                if (t == *ui)
                        return count;
                *ui = t;
@@ -467,6 +478,7 @@ out:
                return count;
        }
 
+#ifdef CONFIG_F2FS_IOSTAT
        if (!strcmp(a->attr.name, "iostat_enable")) {
                sbi->iostat_enable = !!t;
                if (!sbi->iostat_enable)
@@ -482,6 +494,7 @@ out:
                spin_unlock(&sbi->iostat_lock);
                return count;
        }
+#endif
 
 #ifdef CONFIG_F2FS_FS_COMPRESSION
        if (!strcmp(a->attr.name, "compr_written_block") ||
@@ -515,6 +528,29 @@ out:
                return count;
        }
 
+       if (!strcmp(a->attr.name, "gc_segment_mode")) {
+               if (t < MAX_GC_MODE)
+                       sbi->gc_segment_mode = t;
+               else
+                       return -EINVAL;
+               return count;
+       }
+
+       if (!strcmp(a->attr.name, "gc_reclaimed_segments")) {
+               if (t != 0)
+                       return -EINVAL;
+               sbi->gc_reclaimed_segs[sbi->gc_segment_mode] = 0;
+               return count;
+       }
+
+       if (!strcmp(a->attr.name, "seq_file_ra_mul")) {
+               if (t >= MIN_RA_MUL && t <= MAX_RA_MUL)
+                       sbi->seq_file_ra_mul = t;
+               else
+                       return -EINVAL;
+               return count;
+       }
+
        *ui = (unsigned int)t;
 
        return count;
@@ -667,8 +703,10 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, discard_idle_interval,
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info,
                umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]);
+#ifdef CONFIG_F2FS_IOSTAT
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_period_ms, iostat_period_ms);
+#endif
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_io_bytes, max_io_bytes);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold);
@@ -740,6 +778,10 @@ F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_count, max_candidate_cou
 F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_age_weight, age_weight);
 F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_age_threshold, age_threshold);
 
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, seq_file_ra_mul, seq_file_ra_mul);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_segment_mode, gc_segment_mode);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_reclaimed_segments, gc_reclaimed_segs);
+
 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
 static struct attribute *f2fs_attrs[] = {
        ATTR_LIST(gc_urgent_sleep_time),
@@ -770,8 +812,10 @@ static struct attribute *f2fs_attrs[] = {
        ATTR_LIST(discard_idle_interval),
        ATTR_LIST(gc_idle_interval),
        ATTR_LIST(umount_discard_timeout),
+#ifdef CONFIG_F2FS_IOSTAT
        ATTR_LIST(iostat_enable),
        ATTR_LIST(iostat_period_ms),
+#endif
        ATTR_LIST(readdir_ra),
        ATTR_LIST(max_io_bytes),
        ATTR_LIST(gc_pin_file_thresh),
@@ -812,6 +856,9 @@ static struct attribute *f2fs_attrs[] = {
        ATTR_LIST(atgc_candidate_count),
        ATTR_LIST(atgc_age_weight),
        ATTR_LIST(atgc_age_threshold),
+       ATTR_LIST(seq_file_ra_mul),
+       ATTR_LIST(gc_segment_mode),
+       ATTR_LIST(gc_reclaimed_segments),
        NULL,
 };
 ATTRIBUTE_GROUPS(f2fs);
@@ -1036,101 +1083,6 @@ static int __maybe_unused segment_bits_seq_show(struct seq_file *seq,
        return 0;
 }
 
-void f2fs_record_iostat(struct f2fs_sb_info *sbi)
-{
-       unsigned long long iostat_diff[NR_IO_TYPE];
-       int i;
-
-       if (time_is_after_jiffies(sbi->iostat_next_period))
-               return;
-
-       /* Need double check under the lock */
-       spin_lock(&sbi->iostat_lock);
-       if (time_is_after_jiffies(sbi->iostat_next_period)) {
-               spin_unlock(&sbi->iostat_lock);
-               return;
-       }
-       sbi->iostat_next_period = jiffies +
-                               msecs_to_jiffies(sbi->iostat_period_ms);
-
-       for (i = 0; i < NR_IO_TYPE; i++) {
-               iostat_diff[i] = sbi->rw_iostat[i] -
-                               sbi->prev_rw_iostat[i];
-               sbi->prev_rw_iostat[i] = sbi->rw_iostat[i];
-       }
-       spin_unlock(&sbi->iostat_lock);
-
-       trace_f2fs_iostat(sbi, iostat_diff);
-}
-
-static int __maybe_unused iostat_info_seq_show(struct seq_file *seq,
-                                              void *offset)
-{
-       struct super_block *sb = seq->private;
-       struct f2fs_sb_info *sbi = F2FS_SB(sb);
-       time64_t now = ktime_get_real_seconds();
-
-       if (!sbi->iostat_enable)
-               return 0;
-
-       seq_printf(seq, "time:          %-16llu\n", now);
-
-       /* print app write IOs */
-       seq_puts(seq, "[WRITE]\n");
-       seq_printf(seq, "app buffered:  %-16llu\n",
-                               sbi->rw_iostat[APP_BUFFERED_IO]);
-       seq_printf(seq, "app direct:    %-16llu\n",
-                               sbi->rw_iostat[APP_DIRECT_IO]);
-       seq_printf(seq, "app mapped:    %-16llu\n",
-                               sbi->rw_iostat[APP_MAPPED_IO]);
-
-       /* print fs write IOs */
-       seq_printf(seq, "fs data:       %-16llu\n",
-                               sbi->rw_iostat[FS_DATA_IO]);
-       seq_printf(seq, "fs node:       %-16llu\n",
-                               sbi->rw_iostat[FS_NODE_IO]);
-       seq_printf(seq, "fs meta:       %-16llu\n",
-                               sbi->rw_iostat[FS_META_IO]);
-       seq_printf(seq, "fs gc data:    %-16llu\n",
-                               sbi->rw_iostat[FS_GC_DATA_IO]);
-       seq_printf(seq, "fs gc node:    %-16llu\n",
-                               sbi->rw_iostat[FS_GC_NODE_IO]);
-       seq_printf(seq, "fs cp data:    %-16llu\n",
-                               sbi->rw_iostat[FS_CP_DATA_IO]);
-       seq_printf(seq, "fs cp node:    %-16llu\n",
-                               sbi->rw_iostat[FS_CP_NODE_IO]);
-       seq_printf(seq, "fs cp meta:    %-16llu\n",
-                               sbi->rw_iostat[FS_CP_META_IO]);
-
-       /* print app read IOs */
-       seq_puts(seq, "[READ]\n");
-       seq_printf(seq, "app buffered:  %-16llu\n",
-                               sbi->rw_iostat[APP_BUFFERED_READ_IO]);
-       seq_printf(seq, "app direct:    %-16llu\n",
-                               sbi->rw_iostat[APP_DIRECT_READ_IO]);
-       seq_printf(seq, "app mapped:    %-16llu\n",
-                               sbi->rw_iostat[APP_MAPPED_READ_IO]);
-
-       /* print fs read IOs */
-       seq_printf(seq, "fs data:       %-16llu\n",
-                               sbi->rw_iostat[FS_DATA_READ_IO]);
-       seq_printf(seq, "fs gc data:    %-16llu\n",
-                               sbi->rw_iostat[FS_GDATA_READ_IO]);
-       seq_printf(seq, "fs compr_data: %-16llu\n",
-                               sbi->rw_iostat[FS_CDATA_READ_IO]);
-       seq_printf(seq, "fs node:       %-16llu\n",
-                               sbi->rw_iostat[FS_NODE_READ_IO]);
-       seq_printf(seq, "fs meta:       %-16llu\n",
-                               sbi->rw_iostat[FS_META_READ_IO]);
-
-       /* print other IOs */
-       seq_puts(seq, "[OTHER]\n");
-       seq_printf(seq, "fs discard:    %-16llu\n",
-                               sbi->rw_iostat[FS_DISCARD]);
-
-       return 0;
-}
-
 static int __maybe_unused victim_bits_seq_show(struct seq_file *seq,
                                                void *offset)
 {
@@ -1213,13 +1165,15 @@ int f2fs_register_sysfs(struct f2fs_sb_info *sbi)
                sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
 
        if (sbi->s_proc) {
-               proc_create_single_data("segment_info", S_IRUGO, sbi->s_proc,
+               proc_create_single_data("segment_info", 0444, sbi->s_proc,
                                segment_info_seq_show, sb);
-               proc_create_single_data("segment_bits", S_IRUGO, sbi->s_proc,
+               proc_create_single_data("segment_bits", 0444, sbi->s_proc,
                                segment_bits_seq_show, sb);
-               proc_create_single_data("iostat_info", S_IRUGO, sbi->s_proc,
+#ifdef CONFIG_F2FS_IOSTAT
+               proc_create_single_data("iostat_info", 0444, sbi->s_proc,
                                iostat_info_seq_show, sb);
-               proc_create_single_data("victim_bits", S_IRUGO, sbi->s_proc,
+#endif
+               proc_create_single_data("victim_bits", 0444, sbi->s_proc,
                                victim_bits_seq_show, sb);
        }
        return 0;
@@ -1238,7 +1192,9 @@ put_sb_kobj:
 void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi)
 {
        if (sbi->s_proc) {
+#ifdef CONFIG_F2FS_IOSTAT
                remove_proc_entry("iostat_info", sbi->s_proc);
+#endif
                remove_proc_entry("segment_info", sbi->s_proc);
                remove_proc_entry("segment_bits", sbi->s_proc);
                remove_proc_entry("victim_bits", sbi->s_proc);