From: Andiry Xu <jix024@eng.ucsd.edu> To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvdimm@lists.01.org Cc: coughlan@redhat.com, miklos@szeredi.hu, Andiry Xu <jix024@cs.ucsd.edu>, david@fromorbit.com, jack@suse.com, swanson@cs.ucsd.edu, swhiteho@redhat.com, andiry.xu@gmail.com Subject: [RFC v2 83/83] Sysfs support. Date: Sat, 10 Mar 2018 10:19:04 -0800 [thread overview] Message-ID: <1520705944-6723-84-git-send-email-jix024@eng.ucsd.edu> (raw) In-Reply-To: <1520705944-6723-1-git-send-email-jix024@eng.ucsd.edu> From: Andiry Xu <jix024@cs.ucsd.edu> Sysfs support allows user to get/post information of running NOVA instance. After mount, NOVA creates four entries under proc directory /proc/fs/nova/pmem#/: timing_stats IO_stats allocator gc Show NOVA file operation timing statistics: cat /proc/fs/NOVA/pmem#/timing_stats Clear timing statistics: echo 1 > /proc/fs/NOVA/pmem#/timing_stats Show NOVA I/O statistics: cat /proc/fs/NOVA/pmem#/IO_stats Clear I/O statistics: echo 1 > /proc/fs/NOVA/pmem#/IO_stats Show NOVA allocator information: cat /proc/fs/NOVA/pmem#/allocator Manual garbage collection: echo #inode_number > /proc/fs/NOVA/pmem#/gc Signed-off-by: Andiry Xu <jix024@cs.ucsd.edu> --- fs/nova/Makefile | 2 +- fs/nova/nova.h | 6 + fs/nova/super.c | 9 ++ fs/nova/super.h | 1 + fs/nova/sysfs.c | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 fs/nova/sysfs.c diff --git a/fs/nova/Makefile b/fs/nova/Makefile index 7a5fb6d..6e1c29d 100644 --- a/fs/nova/Makefile +++ b/fs/nova/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_NOVA_FS) += nova.o nova-y := balloc.o bbuild.o dax.o dir.o file.o gc.o inode.o ioctl.o journal.o\ - log.o namei.o rebuild.o stats.o super.o symlink.o + log.o namei.o rebuild.o stats.o super.o symlink.o sysfs.o diff --git a/fs/nova/nova.h b/fs/nova/nova.h index 32b7b2f..0814676 100644 --- a/fs/nova/nova.h +++ b/fs/nova/nova.h @@ -546,6 +546,12 @@ int nova_block_symlink(struct super_block *sb, struct nova_inode *pi, struct inode *inode, const char *symname, int len, u64 epoch_id); extern const struct inode_operations nova_symlink_inode_operations; +/* sysfs.c */ +extern const char *proc_dirname; +extern struct proc_dir_entry *nova_proc_root; +void nova_sysfs_init(struct super_block *sb); +void nova_sysfs_exit(struct super_block *sb); + /* stats.c */ void nova_get_timing_stats(void); void nova_get_IO_stats(void); diff --git a/fs/nova/super.c b/fs/nova/super.c index 14b4af6..039c003 100644 --- a/fs/nova/super.c +++ b/fs/nova/super.c @@ -596,6 +596,8 @@ static int nova_fill_super(struct super_block *sb, void *data, int silent) goto out; } + nova_sysfs_init(sb); + /* Init a new nova instance */ if (sbi->s_mount_opt & NOVA_MOUNT_FORMAT) { root_pi = nova_init(sb, sbi->initsize); @@ -680,6 +682,8 @@ static int nova_fill_super(struct super_block *sb, void *data, int silent) kfree(sbi->inode_maps); sbi->inode_maps = NULL; + nova_sysfs_exit(sb); + kfree(sbi->nova_sb); kfree(sbi); nova_dbg("%s failed: return %d\n", __func__, retval); @@ -783,6 +787,8 @@ static void nova_put_super(struct super_block *sb) i, inode_map->allocated, inode_map->freed); } + nova_sysfs_exit(sb); + kfree(sbi->inode_maps); kfree(sbi->nova_sb); kfree(sbi); @@ -1007,6 +1013,8 @@ static int __init init_nova_fs(void) nova_info("Arch new instructions support: CLWB %s\n", support_clwb ? "YES" : "NO"); + nova_proc_root = proc_mkdir(proc_dirname, NULL); + rc = init_rangenode_cache(); if (rc) goto out; @@ -1041,6 +1049,7 @@ static int __init init_nova_fs(void) static void __exit exit_nova_fs(void) { unregister_filesystem(&nova_fs_type); + remove_proc_entry(proc_dirname, NULL); destroy_file_write_item_cache(); destroy_inodecache(); destroy_rangenode_cache(); diff --git a/fs/nova/super.h b/fs/nova/super.h index bcf9548..bcbe862 100644 --- a/fs/nova/super.h +++ b/fs/nova/super.h @@ -112,6 +112,7 @@ struct nova_sb_info { struct mutex s_lock; /* protects the SB's buffer-head */ int cpus; + struct proc_dir_entry *s_proc; /* Current epoch. volatile guarantees visibility */ volatile u64 s_epoch_id; diff --git a/fs/nova/sysfs.c b/fs/nova/sysfs.c new file mode 100644 index 0000000..0a73ef4 --- /dev/null +++ b/fs/nova/sysfs.c @@ -0,0 +1,379 @@ +/* + * BRIEF DESCRIPTION + * + * Proc fs operations + * + * Copyright 2015-2016 Regents of the University of California, + * UCSD Non-Volatile Systems Lab, Andiry Xu <jix024@cs.ucsd.edu> + * Copyright 2012-2013 Intel Corporation + * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com> + * Copyright 2003 Sony Corporation + * Copyright 2003 Matsushita Electric Industrial Co., Ltd. + * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam + * + * This program is free software; you can redistribute it and/or modify it + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "nova.h" +#include "inode.h" + +const char *proc_dirname = "fs/NOVA"; +struct proc_dir_entry *nova_proc_root; + +/* ====================== Statistics ======================== */ +static int nova_seq_timing_show(struct seq_file *seq, void *v) +{ + int i; + + nova_get_timing_stats(); + + seq_puts(seq, "=========== NOVA kernel timing stats ===========\n"); + for (i = 0; i < TIMING_NUM; i++) { + /* Title */ + if (Timingstring[i][0] == '=') { + seq_printf(seq, "\n%s\n\n", Timingstring[i]); + continue; + } + + if (measure_timing || Timingstats[i]) { + seq_printf(seq, "%s: count %llu, timing %llu, average %llu\n", + Timingstring[i], + Countstats[i], + Timingstats[i], + Countstats[i] ? + Timingstats[i] / Countstats[i] : 0); + } else { + seq_printf(seq, "%s: count %llu\n", + Timingstring[i], + Countstats[i]); + } + } + + seq_puts(seq, "\n"); + return 0; +} + +static int nova_seq_timing_open(struct inode *inode, struct file *file) +{ + return single_open(file, nova_seq_timing_show, PDE_DATA(inode)); +} + +ssize_t nova_seq_clear_stats(struct file *filp, const char __user *buf, + size_t len, loff_t *ppos) +{ + struct address_space *mapping = filp->f_mapping; + struct inode *inode = mapping->host; + struct super_block *sb = PDE_DATA(inode); + + nova_clear_stats(sb); + return len; +} + +static const struct file_operations nova_seq_timing_fops = { + .owner = THIS_MODULE, + .open = nova_seq_timing_open, + .read = seq_read, + .write = nova_seq_clear_stats, + .llseek = seq_lseek, + .release = single_release, +}; + +static int nova_seq_IO_show(struct seq_file *seq, void *v) +{ + struct super_block *sb = seq->private; + struct nova_sb_info *sbi = NOVA_SB(sb); + struct free_list *free_list; + unsigned long alloc_log_count = 0; + unsigned long alloc_log_pages = 0; + unsigned long alloc_data_count = 0; + unsigned long alloc_data_pages = 0; + unsigned long free_log_count = 0; + unsigned long freed_log_pages = 0; + unsigned long free_data_count = 0; + unsigned long freed_data_pages = 0; + int i; + + nova_get_timing_stats(); + nova_get_IO_stats(); + + seq_puts(seq, "============ NOVA allocation stats ============\n\n"); + + for (i = 0; i < sbi->cpus; i++) { + free_list = nova_get_free_list(sb, i); + + alloc_log_count += free_list->alloc_log_count; + alloc_log_pages += free_list->alloc_log_pages; + alloc_data_count += free_list->alloc_data_count; + alloc_data_pages += free_list->alloc_data_pages; + free_log_count += free_list->free_log_count; + freed_log_pages += free_list->freed_log_pages; + free_data_count += free_list->free_data_count; + freed_data_pages += free_list->freed_data_pages; + } + + seq_printf(seq, "alloc log count %lu, allocated log pages %lu\n" + "alloc data count %lu, allocated data pages %lu\n" + "free log count %lu, freed log pages %lu\n" + "free data count %lu, freed data pages %lu\n", + alloc_log_count, alloc_log_pages, + alloc_data_count, alloc_data_pages, + free_log_count, freed_log_pages, + free_data_count, freed_data_pages); + + seq_printf(seq, "Fast GC %llu, check pages %llu, free pages %llu, average %llu\n", + Countstats[fast_gc_t], IOstats[fast_checked_pages], + IOstats[fast_gc_pages], Countstats[fast_gc_t] ? + IOstats[fast_gc_pages] / Countstats[fast_gc_t] : 0); + seq_printf(seq, "Thorough GC %llu, checked pages %llu, free pages %llu, average %llu\n", + Countstats[thorough_gc_t], + IOstats[thorough_checked_pages], IOstats[thorough_gc_pages], + Countstats[thorough_gc_t] ? + IOstats[thorough_gc_pages] / Countstats[thorough_gc_t] + : 0); + + seq_puts(seq, "\n"); + + seq_puts(seq, "================ NOVA I/O stats ================\n\n"); + seq_printf(seq, "Read %llu, bytes %llu, average %llu\n", + Countstats[dax_read_t], IOstats[read_bytes], + Countstats[dax_read_t] ? + IOstats[read_bytes] / Countstats[dax_read_t] : 0); + seq_printf(seq, "COW write %llu, bytes %llu, average %llu, write breaks %llu, average %llu\n", + Countstats[cow_write_t], IOstats[cow_write_bytes], + Countstats[cow_write_t] ? + IOstats[cow_write_bytes] / Countstats[cow_write_t] : 0, + IOstats[cow_write_breaks], Countstats[cow_write_t] ? + IOstats[cow_write_breaks] / Countstats[cow_write_t] + : 0); + seq_printf(seq, "Inplace write %llu, bytes %llu, average %llu, write breaks %llu, average %llu\n", + Countstats[inplace_write_t], IOstats[inplace_write_bytes], + Countstats[inplace_write_t] ? + IOstats[inplace_write_bytes] / + Countstats[inplace_write_t] : 0, + IOstats[inplace_write_breaks], Countstats[inplace_write_t] ? + IOstats[inplace_write_breaks] / + Countstats[inplace_write_t] : 0); + seq_printf(seq, "Inplace write %llu, allocate new blocks %llu\n", + Countstats[inplace_write_t], + IOstats[inplace_new_blocks]); + seq_printf(seq, "DAX get blocks %llu, allocate new blocks %llu\n", + Countstats[dax_get_block_t], IOstats[dax_new_blocks]); + seq_printf(seq, "Page fault %llu\n", Countstats[mmap_fault_t]); + seq_printf(seq, "fsync %llu, fdatasync %llu\n", + Countstats[fsync_t], IOstats[fdatasync]); + + seq_puts(seq, "\n"); + + return 0; +} + +static int nova_seq_IO_open(struct inode *inode, struct file *file) +{ + return single_open(file, nova_seq_IO_show, PDE_DATA(inode)); +} + +static const struct file_operations nova_seq_IO_fops = { + .owner = THIS_MODULE, + .open = nova_seq_IO_open, + .read = seq_read, + .write = nova_seq_clear_stats, + .llseek = seq_lseek, + .release = single_release, +}; + +static int nova_seq_show_allocator(struct seq_file *seq, void *v) +{ + struct super_block *sb = seq->private; + struct nova_sb_info *sbi = NOVA_SB(sb); + struct free_list *free_list; + int i; + unsigned long log_pages = 0; + unsigned long data_pages = 0; + + seq_puts(seq, "======== NOVA per-CPU allocator stats ========\n"); + for (i = 0; i < sbi->cpus; i++) { + free_list = nova_get_free_list(sb, i); + seq_printf(seq, "Free list %d: block start %lu, block end %lu, num_blocks %lu, num_free_blocks %lu, blocknode %lu\n", + i, free_list->block_start, free_list->block_end, + free_list->block_end - free_list->block_start + 1, + free_list->num_free_blocks, free_list->num_blocknode); + + if (free_list->first_node) { + seq_printf(seq, "First node %lu - %lu\n", + free_list->first_node->range_low, + free_list->first_node->range_high); + } + + if (free_list->last_node) { + seq_printf(seq, "Last node %lu - %lu\n", + free_list->last_node->range_low, + free_list->last_node->range_high); + } + + seq_printf(seq, "Free list %d: alloc log count %lu, allocated log pages %lu, alloc data count %lu, allocated data pages %lu, free log count %lu, freed log pages %lu, free data count %lu, freed data pages %lu\n", + i, + free_list->alloc_log_count, + free_list->alloc_log_pages, + free_list->alloc_data_count, + free_list->alloc_data_pages, + free_list->free_log_count, + free_list->freed_log_pages, + free_list->free_data_count, + free_list->freed_data_pages); + + log_pages += free_list->alloc_log_pages; + log_pages -= free_list->freed_log_pages; + + data_pages += free_list->alloc_data_pages; + data_pages -= free_list->freed_data_pages; + } + + seq_printf(seq, "\nCurrently used pmem pages: log %lu, data %lu\n", + log_pages, data_pages); + + return 0; +} + +static int nova_seq_allocator_open(struct inode *inode, struct file *file) +{ + return single_open(file, nova_seq_show_allocator, + PDE_DATA(inode)); +} + +static const struct file_operations nova_seq_allocator_fops = { + .owner = THIS_MODULE, + .open = nova_seq_allocator_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + +/* ====================== GC ======================== */ + + +static int nova_seq_gc_show(struct seq_file *seq, void *v) +{ + seq_printf(seq, "Echo inode number to trigger garbage collection\n" + " example: echo 34 > /proc/fs/NOVA/pmem0/gc\n"); + return 0; +} + +static int nova_seq_gc_open(struct inode *inode, struct file *file) +{ + return single_open(file, nova_seq_gc_show, PDE_DATA(inode)); +} + +ssize_t nova_seq_gc(struct file *filp, const char __user *buf, + size_t len, loff_t *ppos) +{ + u64 target_inode_number; + struct address_space *mapping = filp->f_mapping; + struct inode *inode = mapping->host; + struct super_block *sb = PDE_DATA(inode); + struct inode *target_inode; + struct nova_inode *target_pi; + struct nova_inode_info *target_sih; + + int ret; + char *_buf; + int retval = len; + + _buf = kmalloc(len, GFP_KERNEL); + if (_buf == NULL) { + retval = -ENOMEM; + nova_dbg("%s: kmalloc failed\n", __func__); + goto out; + } + + if (copy_from_user(_buf, buf, len)) { + retval = -EFAULT; + goto out; + } + + _buf[len] = 0; + ret = kstrtoull(_buf, 0, &target_inode_number); + if (ret) { + nova_info("%s: Could not parse ino '%s'\n", __func__, _buf); + return ret; + } + nova_info("%s: target_inode_number=%llu.", __func__, + target_inode_number); + + target_inode = nova_iget(sb, target_inode_number); + if (target_inode == NULL) { + nova_info("%s: inode %llu does not exist.", __func__, + target_inode_number); + retval = -ENOENT; + goto out; + } + + target_pi = nova_get_inode(sb, target_inode); + if (target_pi == NULL) { + nova_info("%s: couldn't get nova inode %llu.", __func__, + target_inode_number); + retval = -ENOENT; + goto out; + } + + target_sih = NOVA_I(target_inode); + + nova_info("%s: got inode %llu @ 0x%p; pi=0x%p\n", __func__, + target_inode_number, target_inode, target_pi); + + nova_inode_log_fast_gc(sb, target_pi, &target_sih->header, + 0, 0, 0, 1); + iput(target_inode); + +out: + kfree(_buf); + return retval; +} + +static const struct file_operations nova_seq_gc_fops = { + .owner = THIS_MODULE, + .open = nova_seq_gc_open, + .read = seq_read, + .write = nova_seq_gc, + .llseek = seq_lseek, + .release = single_release, +}; + +/* ====================== Setup/teardown======================== */ +void nova_sysfs_init(struct super_block *sb) +{ + struct nova_sb_info *sbi = NOVA_SB(sb); + + if (nova_proc_root) + sbi->s_proc = proc_mkdir(sbi->s_bdev->bd_disk->disk_name, + nova_proc_root); + + if (sbi->s_proc) { + proc_create_data("timing_stats", 0444, sbi->s_proc, + &nova_seq_timing_fops, sb); + proc_create_data("IO_stats", 0444, sbi->s_proc, + &nova_seq_IO_fops, sb); + proc_create_data("allocator", 0444, sbi->s_proc, + &nova_seq_allocator_fops, sb); + proc_create_data("gc", 0444, sbi->s_proc, + &nova_seq_gc_fops, sb); + } +} + +void nova_sysfs_exit(struct super_block *sb) +{ + struct nova_sb_info *sbi = NOVA_SB(sb); + + if (sbi->s_proc) { + remove_proc_entry("timing_stats", sbi->s_proc); + remove_proc_entry("IO_stats", sbi->s_proc); + remove_proc_entry("allocator", sbi->s_proc); + remove_proc_entry("gc", sbi->s_proc); + remove_proc_entry(sbi->s_bdev->bd_disk->disk_name, + nova_proc_root); + } +} -- 2.7.4 _______________________________________________ Linux-nvdimm mailing list Linux-nvdimm@lists.01.org https://lists.01.org/mailman/listinfo/linux-nvdimm
WARNING: multiple messages have this Message-ID (diff)
From: Andiry Xu <jix024@eng.ucsd.edu> To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvdimm@lists.01.org Cc: dan.j.williams@intel.com, andy.rudoff@intel.com, coughlan@redhat.com, swanson@cs.ucsd.edu, david@fromorbit.com, jack@suse.com, swhiteho@redhat.com, miklos@szeredi.hu, andiry.xu@gmail.com, Andiry Xu <jix024@cs.ucsd.edu> Subject: [RFC v2 83/83] Sysfs support. Date: Sat, 10 Mar 2018 10:19:04 -0800 [thread overview] Message-ID: <1520705944-6723-84-git-send-email-jix024@eng.ucsd.edu> (raw) In-Reply-To: <1520705944-6723-1-git-send-email-jix024@eng.ucsd.edu> From: Andiry Xu <jix024@cs.ucsd.edu> Sysfs support allows user to get/post information of running NOVA instance. After mount, NOVA creates four entries under proc directory /proc/fs/nova/pmem#/: timing_stats IO_stats allocator gc Show NOVA file operation timing statistics: cat /proc/fs/NOVA/pmem#/timing_stats Clear timing statistics: echo 1 > /proc/fs/NOVA/pmem#/timing_stats Show NOVA I/O statistics: cat /proc/fs/NOVA/pmem#/IO_stats Clear I/O statistics: echo 1 > /proc/fs/NOVA/pmem#/IO_stats Show NOVA allocator information: cat /proc/fs/NOVA/pmem#/allocator Manual garbage collection: echo #inode_number > /proc/fs/NOVA/pmem#/gc Signed-off-by: Andiry Xu <jix024@cs.ucsd.edu> --- fs/nova/Makefile | 2 +- fs/nova/nova.h | 6 + fs/nova/super.c | 9 ++ fs/nova/super.h | 1 + fs/nova/sysfs.c | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 fs/nova/sysfs.c diff --git a/fs/nova/Makefile b/fs/nova/Makefile index 7a5fb6d..6e1c29d 100644 --- a/fs/nova/Makefile +++ b/fs/nova/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_NOVA_FS) += nova.o nova-y := balloc.o bbuild.o dax.o dir.o file.o gc.o inode.o ioctl.o journal.o\ - log.o namei.o rebuild.o stats.o super.o symlink.o + log.o namei.o rebuild.o stats.o super.o symlink.o sysfs.o diff --git a/fs/nova/nova.h b/fs/nova/nova.h index 32b7b2f..0814676 100644 --- a/fs/nova/nova.h +++ b/fs/nova/nova.h @@ -546,6 +546,12 @@ int nova_block_symlink(struct super_block *sb, struct nova_inode *pi, struct inode *inode, const char *symname, int len, u64 epoch_id); extern const struct inode_operations nova_symlink_inode_operations; +/* sysfs.c */ +extern const char *proc_dirname; +extern struct proc_dir_entry *nova_proc_root; +void nova_sysfs_init(struct super_block *sb); +void nova_sysfs_exit(struct super_block *sb); + /* stats.c */ void nova_get_timing_stats(void); void nova_get_IO_stats(void); diff --git a/fs/nova/super.c b/fs/nova/super.c index 14b4af6..039c003 100644 --- a/fs/nova/super.c +++ b/fs/nova/super.c @@ -596,6 +596,8 @@ static int nova_fill_super(struct super_block *sb, void *data, int silent) goto out; } + nova_sysfs_init(sb); + /* Init a new nova instance */ if (sbi->s_mount_opt & NOVA_MOUNT_FORMAT) { root_pi = nova_init(sb, sbi->initsize); @@ -680,6 +682,8 @@ static int nova_fill_super(struct super_block *sb, void *data, int silent) kfree(sbi->inode_maps); sbi->inode_maps = NULL; + nova_sysfs_exit(sb); + kfree(sbi->nova_sb); kfree(sbi); nova_dbg("%s failed: return %d\n", __func__, retval); @@ -783,6 +787,8 @@ static void nova_put_super(struct super_block *sb) i, inode_map->allocated, inode_map->freed); } + nova_sysfs_exit(sb); + kfree(sbi->inode_maps); kfree(sbi->nova_sb); kfree(sbi); @@ -1007,6 +1013,8 @@ static int __init init_nova_fs(void) nova_info("Arch new instructions support: CLWB %s\n", support_clwb ? "YES" : "NO"); + nova_proc_root = proc_mkdir(proc_dirname, NULL); + rc = init_rangenode_cache(); if (rc) goto out; @@ -1041,6 +1049,7 @@ static int __init init_nova_fs(void) static void __exit exit_nova_fs(void) { unregister_filesystem(&nova_fs_type); + remove_proc_entry(proc_dirname, NULL); destroy_file_write_item_cache(); destroy_inodecache(); destroy_rangenode_cache(); diff --git a/fs/nova/super.h b/fs/nova/super.h index bcf9548..bcbe862 100644 --- a/fs/nova/super.h +++ b/fs/nova/super.h @@ -112,6 +112,7 @@ struct nova_sb_info { struct mutex s_lock; /* protects the SB's buffer-head */ int cpus; + struct proc_dir_entry *s_proc; /* Current epoch. volatile guarantees visibility */ volatile u64 s_epoch_id; diff --git a/fs/nova/sysfs.c b/fs/nova/sysfs.c new file mode 100644 index 0000000..0a73ef4 --- /dev/null +++ b/fs/nova/sysfs.c @@ -0,0 +1,379 @@ +/* + * BRIEF DESCRIPTION + * + * Proc fs operations + * + * Copyright 2015-2016 Regents of the University of California, + * UCSD Non-Volatile Systems Lab, Andiry Xu <jix024@cs.ucsd.edu> + * Copyright 2012-2013 Intel Corporation + * Copyright 2009-2011 Marco Stornelli <marco.stornelli@gmail.com> + * Copyright 2003 Sony Corporation + * Copyright 2003 Matsushita Electric Industrial Co., Ltd. + * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam + * + * This program is free software; you can redistribute it and/or modify it + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "nova.h" +#include "inode.h" + +const char *proc_dirname = "fs/NOVA"; +struct proc_dir_entry *nova_proc_root; + +/* ====================== Statistics ======================== */ +static int nova_seq_timing_show(struct seq_file *seq, void *v) +{ + int i; + + nova_get_timing_stats(); + + seq_puts(seq, "=========== NOVA kernel timing stats ===========\n"); + for (i = 0; i < TIMING_NUM; i++) { + /* Title */ + if (Timingstring[i][0] == '=') { + seq_printf(seq, "\n%s\n\n", Timingstring[i]); + continue; + } + + if (measure_timing || Timingstats[i]) { + seq_printf(seq, "%s: count %llu, timing %llu, average %llu\n", + Timingstring[i], + Countstats[i], + Timingstats[i], + Countstats[i] ? + Timingstats[i] / Countstats[i] : 0); + } else { + seq_printf(seq, "%s: count %llu\n", + Timingstring[i], + Countstats[i]); + } + } + + seq_puts(seq, "\n"); + return 0; +} + +static int nova_seq_timing_open(struct inode *inode, struct file *file) +{ + return single_open(file, nova_seq_timing_show, PDE_DATA(inode)); +} + +ssize_t nova_seq_clear_stats(struct file *filp, const char __user *buf, + size_t len, loff_t *ppos) +{ + struct address_space *mapping = filp->f_mapping; + struct inode *inode = mapping->host; + struct super_block *sb = PDE_DATA(inode); + + nova_clear_stats(sb); + return len; +} + +static const struct file_operations nova_seq_timing_fops = { + .owner = THIS_MODULE, + .open = nova_seq_timing_open, + .read = seq_read, + .write = nova_seq_clear_stats, + .llseek = seq_lseek, + .release = single_release, +}; + +static int nova_seq_IO_show(struct seq_file *seq, void *v) +{ + struct super_block *sb = seq->private; + struct nova_sb_info *sbi = NOVA_SB(sb); + struct free_list *free_list; + unsigned long alloc_log_count = 0; + unsigned long alloc_log_pages = 0; + unsigned long alloc_data_count = 0; + unsigned long alloc_data_pages = 0; + unsigned long free_log_count = 0; + unsigned long freed_log_pages = 0; + unsigned long free_data_count = 0; + unsigned long freed_data_pages = 0; + int i; + + nova_get_timing_stats(); + nova_get_IO_stats(); + + seq_puts(seq, "============ NOVA allocation stats ============\n\n"); + + for (i = 0; i < sbi->cpus; i++) { + free_list = nova_get_free_list(sb, i); + + alloc_log_count += free_list->alloc_log_count; + alloc_log_pages += free_list->alloc_log_pages; + alloc_data_count += free_list->alloc_data_count; + alloc_data_pages += free_list->alloc_data_pages; + free_log_count += free_list->free_log_count; + freed_log_pages += free_list->freed_log_pages; + free_data_count += free_list->free_data_count; + freed_data_pages += free_list->freed_data_pages; + } + + seq_printf(seq, "alloc log count %lu, allocated log pages %lu\n" + "alloc data count %lu, allocated data pages %lu\n" + "free log count %lu, freed log pages %lu\n" + "free data count %lu, freed data pages %lu\n", + alloc_log_count, alloc_log_pages, + alloc_data_count, alloc_data_pages, + free_log_count, freed_log_pages, + free_data_count, freed_data_pages); + + seq_printf(seq, "Fast GC %llu, check pages %llu, free pages %llu, average %llu\n", + Countstats[fast_gc_t], IOstats[fast_checked_pages], + IOstats[fast_gc_pages], Countstats[fast_gc_t] ? + IOstats[fast_gc_pages] / Countstats[fast_gc_t] : 0); + seq_printf(seq, "Thorough GC %llu, checked pages %llu, free pages %llu, average %llu\n", + Countstats[thorough_gc_t], + IOstats[thorough_checked_pages], IOstats[thorough_gc_pages], + Countstats[thorough_gc_t] ? + IOstats[thorough_gc_pages] / Countstats[thorough_gc_t] + : 0); + + seq_puts(seq, "\n"); + + seq_puts(seq, "================ NOVA I/O stats ================\n\n"); + seq_printf(seq, "Read %llu, bytes %llu, average %llu\n", + Countstats[dax_read_t], IOstats[read_bytes], + Countstats[dax_read_t] ? + IOstats[read_bytes] / Countstats[dax_read_t] : 0); + seq_printf(seq, "COW write %llu, bytes %llu, average %llu, write breaks %llu, average %llu\n", + Countstats[cow_write_t], IOstats[cow_write_bytes], + Countstats[cow_write_t] ? + IOstats[cow_write_bytes] / Countstats[cow_write_t] : 0, + IOstats[cow_write_breaks], Countstats[cow_write_t] ? + IOstats[cow_write_breaks] / Countstats[cow_write_t] + : 0); + seq_printf(seq, "Inplace write %llu, bytes %llu, average %llu, write breaks %llu, average %llu\n", + Countstats[inplace_write_t], IOstats[inplace_write_bytes], + Countstats[inplace_write_t] ? + IOstats[inplace_write_bytes] / + Countstats[inplace_write_t] : 0, + IOstats[inplace_write_breaks], Countstats[inplace_write_t] ? + IOstats[inplace_write_breaks] / + Countstats[inplace_write_t] : 0); + seq_printf(seq, "Inplace write %llu, allocate new blocks %llu\n", + Countstats[inplace_write_t], + IOstats[inplace_new_blocks]); + seq_printf(seq, "DAX get blocks %llu, allocate new blocks %llu\n", + Countstats[dax_get_block_t], IOstats[dax_new_blocks]); + seq_printf(seq, "Page fault %llu\n", Countstats[mmap_fault_t]); + seq_printf(seq, "fsync %llu, fdatasync %llu\n", + Countstats[fsync_t], IOstats[fdatasync]); + + seq_puts(seq, "\n"); + + return 0; +} + +static int nova_seq_IO_open(struct inode *inode, struct file *file) +{ + return single_open(file, nova_seq_IO_show, PDE_DATA(inode)); +} + +static const struct file_operations nova_seq_IO_fops = { + .owner = THIS_MODULE, + .open = nova_seq_IO_open, + .read = seq_read, + .write = nova_seq_clear_stats, + .llseek = seq_lseek, + .release = single_release, +}; + +static int nova_seq_show_allocator(struct seq_file *seq, void *v) +{ + struct super_block *sb = seq->private; + struct nova_sb_info *sbi = NOVA_SB(sb); + struct free_list *free_list; + int i; + unsigned long log_pages = 0; + unsigned long data_pages = 0; + + seq_puts(seq, "======== NOVA per-CPU allocator stats ========\n"); + for (i = 0; i < sbi->cpus; i++) { + free_list = nova_get_free_list(sb, i); + seq_printf(seq, "Free list %d: block start %lu, block end %lu, num_blocks %lu, num_free_blocks %lu, blocknode %lu\n", + i, free_list->block_start, free_list->block_end, + free_list->block_end - free_list->block_start + 1, + free_list->num_free_blocks, free_list->num_blocknode); + + if (free_list->first_node) { + seq_printf(seq, "First node %lu - %lu\n", + free_list->first_node->range_low, + free_list->first_node->range_high); + } + + if (free_list->last_node) { + seq_printf(seq, "Last node %lu - %lu\n", + free_list->last_node->range_low, + free_list->last_node->range_high); + } + + seq_printf(seq, "Free list %d: alloc log count %lu, allocated log pages %lu, alloc data count %lu, allocated data pages %lu, free log count %lu, freed log pages %lu, free data count %lu, freed data pages %lu\n", + i, + free_list->alloc_log_count, + free_list->alloc_log_pages, + free_list->alloc_data_count, + free_list->alloc_data_pages, + free_list->free_log_count, + free_list->freed_log_pages, + free_list->free_data_count, + free_list->freed_data_pages); + + log_pages += free_list->alloc_log_pages; + log_pages -= free_list->freed_log_pages; + + data_pages += free_list->alloc_data_pages; + data_pages -= free_list->freed_data_pages; + } + + seq_printf(seq, "\nCurrently used pmem pages: log %lu, data %lu\n", + log_pages, data_pages); + + return 0; +} + +static int nova_seq_allocator_open(struct inode *inode, struct file *file) +{ + return single_open(file, nova_seq_show_allocator, + PDE_DATA(inode)); +} + +static const struct file_operations nova_seq_allocator_fops = { + .owner = THIS_MODULE, + .open = nova_seq_allocator_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + +/* ====================== GC ======================== */ + + +static int nova_seq_gc_show(struct seq_file *seq, void *v) +{ + seq_printf(seq, "Echo inode number to trigger garbage collection\n" + " example: echo 34 > /proc/fs/NOVA/pmem0/gc\n"); + return 0; +} + +static int nova_seq_gc_open(struct inode *inode, struct file *file) +{ + return single_open(file, nova_seq_gc_show, PDE_DATA(inode)); +} + +ssize_t nova_seq_gc(struct file *filp, const char __user *buf, + size_t len, loff_t *ppos) +{ + u64 target_inode_number; + struct address_space *mapping = filp->f_mapping; + struct inode *inode = mapping->host; + struct super_block *sb = PDE_DATA(inode); + struct inode *target_inode; + struct nova_inode *target_pi; + struct nova_inode_info *target_sih; + + int ret; + char *_buf; + int retval = len; + + _buf = kmalloc(len, GFP_KERNEL); + if (_buf == NULL) { + retval = -ENOMEM; + nova_dbg("%s: kmalloc failed\n", __func__); + goto out; + } + + if (copy_from_user(_buf, buf, len)) { + retval = -EFAULT; + goto out; + } + + _buf[len] = 0; + ret = kstrtoull(_buf, 0, &target_inode_number); + if (ret) { + nova_info("%s: Could not parse ino '%s'\n", __func__, _buf); + return ret; + } + nova_info("%s: target_inode_number=%llu.", __func__, + target_inode_number); + + target_inode = nova_iget(sb, target_inode_number); + if (target_inode == NULL) { + nova_info("%s: inode %llu does not exist.", __func__, + target_inode_number); + retval = -ENOENT; + goto out; + } + + target_pi = nova_get_inode(sb, target_inode); + if (target_pi == NULL) { + nova_info("%s: couldn't get nova inode %llu.", __func__, + target_inode_number); + retval = -ENOENT; + goto out; + } + + target_sih = NOVA_I(target_inode); + + nova_info("%s: got inode %llu @ 0x%p; pi=0x%p\n", __func__, + target_inode_number, target_inode, target_pi); + + nova_inode_log_fast_gc(sb, target_pi, &target_sih->header, + 0, 0, 0, 1); + iput(target_inode); + +out: + kfree(_buf); + return retval; +} + +static const struct file_operations nova_seq_gc_fops = { + .owner = THIS_MODULE, + .open = nova_seq_gc_open, + .read = seq_read, + .write = nova_seq_gc, + .llseek = seq_lseek, + .release = single_release, +}; + +/* ====================== Setup/teardown======================== */ +void nova_sysfs_init(struct super_block *sb) +{ + struct nova_sb_info *sbi = NOVA_SB(sb); + + if (nova_proc_root) + sbi->s_proc = proc_mkdir(sbi->s_bdev->bd_disk->disk_name, + nova_proc_root); + + if (sbi->s_proc) { + proc_create_data("timing_stats", 0444, sbi->s_proc, + &nova_seq_timing_fops, sb); + proc_create_data("IO_stats", 0444, sbi->s_proc, + &nova_seq_IO_fops, sb); + proc_create_data("allocator", 0444, sbi->s_proc, + &nova_seq_allocator_fops, sb); + proc_create_data("gc", 0444, sbi->s_proc, + &nova_seq_gc_fops, sb); + } +} + +void nova_sysfs_exit(struct super_block *sb) +{ + struct nova_sb_info *sbi = NOVA_SB(sb); + + if (sbi->s_proc) { + remove_proc_entry("timing_stats", sbi->s_proc); + remove_proc_entry("IO_stats", sbi->s_proc); + remove_proc_entry("allocator", sbi->s_proc); + remove_proc_entry("gc", sbi->s_proc); + remove_proc_entry(sbi->s_bdev->bd_disk->disk_name, + nova_proc_root); + } +} -- 2.7.4
next prev parent reply other threads:[~2018-03-10 18:15 UTC|newest] Thread overview: 236+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-03-10 18:17 [RFC v2 00/83] NOVA: a new file system for persistent memory Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 01/83] Introduction and documentation of NOVA filesystem Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-19 20:43 ` Randy Dunlap 2018-03-19 20:43 ` Randy Dunlap 2018-03-19 23:00 ` Andiry Xu 2018-03-19 23:00 ` Andiry Xu 2018-04-22 8:05 ` Pavel Machek 2018-03-10 18:17 ` [RFC v2 02/83] Add nova_def.h Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 03/83] Add super.h Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-15 4:54 ` Darrick J. Wong 2018-03-15 4:54 ` Darrick J. Wong 2018-03-15 6:11 ` Andiry Xu 2018-03-15 6:11 ` Andiry Xu 2018-03-15 9:05 ` Arnd Bergmann 2018-03-15 9:05 ` Arnd Bergmann 2018-03-15 17:51 ` Andiry Xu 2018-03-15 17:51 ` Andiry Xu 2018-03-15 20:04 ` Andreas Dilger 2018-03-15 20:38 ` Arnd Bergmann 2018-03-15 20:38 ` Arnd Bergmann 2018-03-16 2:59 ` Theodore Y. Ts'o 2018-03-16 2:59 ` Theodore Y. Ts'o 2018-03-16 6:17 ` Andiry Xu 2018-03-16 6:17 ` Andiry Xu 2018-03-16 6:30 ` Darrick J. Wong 2018-03-16 6:30 ` Darrick J. Wong 2018-03-16 9:19 ` Arnd Bergmann 2018-03-16 9:19 ` Arnd Bergmann 2018-03-10 18:17 ` [RFC v2 04/83] NOVA inode definition Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-15 5:06 ` Darrick J. Wong 2018-03-15 5:06 ` Darrick J. Wong 2018-03-15 6:16 ` Andiry Xu 2018-03-15 6:16 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 05/83] Add NOVA filesystem definitions and useful helper routines Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-11 12:00 ` Nikolay Borisov 2018-03-11 12:00 ` Nikolay Borisov 2018-03-11 19:22 ` Eric Biggers 2018-03-11 19:22 ` Eric Biggers 2018-03-11 21:45 ` Andiry Xu 2018-03-11 21:45 ` Andiry Xu 2018-03-19 19:39 ` Andiry Xu 2018-03-19 19:39 ` Andiry Xu 2018-03-19 20:30 ` Eric Biggers 2018-03-19 20:30 ` Eric Biggers 2018-03-19 21:59 ` Andiry Xu 2018-03-19 21:59 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 06/83] Add inode get/read methods Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-04-23 6:12 ` Darrick J. Wong 2018-04-23 6:12 ` Darrick J. Wong 2018-04-23 15:55 ` Andiry Xu 2018-04-23 15:55 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 07/83] Initialize inode_info and rebuild inode information in nova_iget() Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 08/83] NOVA superblock operations Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 09/83] Add Kconfig and Makefile Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-11 12:15 ` Nikolay Borisov 2018-03-11 12:15 ` Nikolay Borisov 2018-03-11 21:32 ` Andiry Xu 2018-03-11 21:32 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 10/83] Add superblock integrity check Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 11/83] Add timing and I/O statistics for performance analysis and profiling Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 12/83] Add timing for mount and init Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 13/83] Add remount_fs and show_options methods Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 14/83] Add range node kmem cache Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-11 11:55 ` Nikolay Borisov 2018-03-11 11:55 ` Nikolay Borisov 2018-03-11 21:31 ` Andiry Xu 2018-03-11 21:31 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 15/83] Add free list data structure Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 16/83] Initialize block map and free lists in nova_init() Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-11 12:12 ` Nikolay Borisov 2018-03-11 12:12 ` Nikolay Borisov 2018-03-11 21:30 ` Andiry Xu 2018-03-11 21:30 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 17/83] Add statfs support Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:17 ` [RFC v2 18/83] Add freelist statistics printing Andiry Xu 2018-03-10 18:17 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 19/83] Add pmem block free routines Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 20/83] Pmem block allocation routines Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 21/83] Add log structure Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 22/83] Inode log pages allocation and reclaimation Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 23/83] Save allocator to pmem in put_super Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 24/83] Initialize and allocate inode table Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 25/83] Support get normal inode address and inode table extentsion Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 26/83] Add inode_map to track inuse inodes Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 27/83] Save the inode inuse list to pmem upon umount Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 28/83] Add NOVA address space operations Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 29/83] Add write_inode and dirty_inode routines Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 30/83] New NOVA inode allocation Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 31/83] Add new vfs " Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 32/83] Add log entry definitions Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 33/83] Inode log and entry printing for debug purpose Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 34/83] Journal: NOVA light weight journal definitions Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 35/83] Journal: Lite journal helper routines Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 36/83] Journal: Lite journal recovery Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 37/83] Journal: Lite journal create and commit Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 38/83] Journal: NOVA lite journal initialization Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 39/83] Log operation: dentry append Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 40/83] Log operation: file write entry append Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 41/83] Log operation: setattr " Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 42/83] Log operation: link change append Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 43/83] Log operation: in-place update log entry Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 44/83] Log operation: invalidate log entries Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 45/83] Log operation: file inode log lookup and assign Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 46/83] Dir: Add Directory radix tree insert/remove methods Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 47/83] Dir: Add initial dentries when initializing a directory inode log Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 48/83] Dir: Readdir operation Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 49/83] Dir: Append create/remove dentry Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 50/83] Inode: Add nova_evict_inode Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 51/83] Rebuild: directory inode Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 52/83] Rebuild: file inode Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 53/83] Namei: lookup Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 54/83] Namei: create and mknod Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 55/83] Namei: mkdir Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 56/83] Namei: link and unlink Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 57/83] Namei: rmdir Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 58/83] Namei: rename Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 59/83] Namei: setattr Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 60/83] Add special inode operations Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 61/83] Super: Add nova_export_ops Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 62/83] File: getattr and file inode operations Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 63/83] File operation: llseek Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 64/83] File operation: open, fsync, flush Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 65/83] File operation: read Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 66/83] Super: Add file write item cache Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 67/83] Dax: commit list of file write items to log Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 68/83] File operation: copy-on-write write Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 69/83] Super: Add module param inplace_data_updates Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 70/83] File operation: Inplace write Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 71/83] Symlink support Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 72/83] File operation: fallocate Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 73/83] Dax: Add iomap operations Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 74/83] File operation: Mmap Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 75/83] File operation: read/write iter Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 76/83] Ioctl support Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 77/83] GC: Fast garbage collection Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:18 ` [RFC v2 78/83] GC: Thorough " Andiry Xu 2018-03-10 18:18 ` Andiry Xu 2018-03-10 18:19 ` [RFC v2 79/83] Normal recovery Andiry Xu 2018-03-10 18:19 ` Andiry Xu 2018-03-10 18:19 ` [RFC v2 80/83] Failure recovery: bitmap operations Andiry Xu 2018-03-10 18:19 ` Andiry Xu 2018-03-10 18:19 ` [RFC v2 81/83] Failure recovery: Inode pages recovery routines Andiry Xu 2018-03-10 18:19 ` Andiry Xu 2018-03-10 18:19 ` [RFC v2 82/83] Failure recovery: Per-CPU recovery Andiry Xu 2018-03-10 18:19 ` Andiry Xu 2018-03-10 18:19 ` Andiry Xu [this message] 2018-03-10 18:19 ` [RFC v2 83/83] Sysfs support Andiry Xu 2018-03-15 0:33 ` Randy Dunlap 2018-03-15 0:33 ` Randy Dunlap 2018-03-15 6:07 ` Andiry Xu 2018-03-15 6:07 ` Andiry Xu 2018-03-22 15:00 ` David Sterba 2018-03-22 15:00 ` David Sterba 2018-03-23 0:31 ` Andiry Xu 2018-03-23 0:31 ` Andiry Xu 2018-03-11 2:14 ` [RFC v2 00/83] NOVA: a new file system for persistent memory Theodore Y. Ts'o 2018-03-11 2:14 ` Theodore Y. Ts'o 2018-03-11 4:58 ` Andiry Xu 2018-03-11 4:58 ` Andiry Xu
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1520705944-6723-84-git-send-email-jix024@eng.ucsd.edu \ --to=jix024@eng.ucsd.edu \ --cc=andiry.xu@gmail.com \ --cc=coughlan@redhat.com \ --cc=david@fromorbit.com \ --cc=jack@suse.com \ --cc=jix024@cs.ucsd.edu \ --cc=linux-fsdevel@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-nvdimm@lists.01.org \ --cc=miklos@szeredi.hu \ --cc=swanson@cs.ucsd.edu \ --cc=swhiteho@redhat.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.