vfs: hot data tracking
Subsystems (7)
cover vfs: hot data tracking
From: Zhi Yong Wu <[email protected]>
HI, guys,
This patchset has been done scalability or performance tests
by fs_mark, ffsb and compilebench.
I have done the perf testing on Linux 3.7.0-rc8+ with Intel(R) Core(TM)
i7-3770 CPU @ 3.40GHz with 8 CPUs, 16G ram and 260G disk.
Any comments or ideas are appreciated, thanks.
NOTE:
The patchset can be obtained via my kernel dev git on github:git://github.com/wuzhy/kernel.git hot_tracking
If you're interested, you can also review them via
https://github.com/wuzhy/kernel/commits/hot_tracking
For more info, please check hot_tracking.txt in Documentation
Below is the perf testing report:
1. fs_mark test
w/o: without hot tracking
w/ : with hot tracking
Count Size FSUse% Files/sec App Overhead
w/o w/ w/o w/ w/o w/
800000 1 2 3 13756.4 32144.9 5350627 5436291 1600000 1 4 5 1163.4 1799.3 20848119 21708216 2400000 1 6 6 1360.8 1252.5 6798705 8715322 3200000 1 8 8 1600.1 1196.3 5751129 6013792 4000000 1 9 9 1071.4 1191.2 17204725 26786369 4800000 1 10 10 1483.5 1447.9 19555541 8383046 5600000 1 11 11 1457.9 1699.5 5783588 10074681 6400000 1 12 13 1658.8 1628.5 6992697 6185551 7200000 1 14 14 1662.4 1857.1 5796793 13772592 8000000 1 15 15 2930.0 2653.8 12431682 6152573 8800000 1 16 17 1630.8 1665.0 7666719 13682765 9600000 1 18 18 1530.3 1583.9 5823644 10171644 10400000 1 19 19 1437.9 1798.6 20935224 6048083 11200000 1 20 20 1529.0 1550.6 6647450 6003151 12000000 1 21 22 1558.6 1501.8 12539509 18144939 12800000 1 23 23 1644.2 1432.1 7074419 28101975 13600000 1 24 24 1753.6 1650.2 7164297 20888972 14400000 1 25 25 2750.0 1483.9 12756692 7441225 15200000 1 27 27 1551.1 1514.3 5741066 8250443 16000000 1 28 28 1610.8 1635.9 72193860 8545285 16800000 1 29 29 1646.7 1907.7 8945856 11703513 17600000 1 30 31 1496.6 2722.3 5858961 8989393 18400000 1 32 32 1457.7 1565.7 10914475 26504660 19200000 1 33 33 1437.6 1518.7 6708975 213303618 20000000 1 34 34 1825.4 1521.1 5722086 12490907 20800000 1 36 35 1718.4 1611.5 5873290 17942534 21600000 1 37 37 2152.6 1536.9 113050627 8717940 22400000 1 38 38 2443.7 1788.2 7398122 19834765 23200000 1 39 39 1518.5 1587.6 5770959 10134882 24000000 1 41 41 1536.8 2164.0 5751248 7214626 24800000 1 42 42 1576.6 2939.4 7390314 6070271 25600000 1 43 43 1707.4 1535.9 11075939 6052896 26400000 1 44 44 1522.5 1563.1 10142987 22549898 27200000 1 46 46 1827.4 1608.5 11613016 24828125 28000000 1 47 47 3420.5 1741.9 8059985 16599156 28800000 1 48 48 1815.5 1944.4 7847931 9043277 29600000 1 50 49 1650.0 1596.6 5636323 7929164 30400000 1 51 51 1683.7 1573.3 5766323 19369146 31200000 1 52 52 1610.1 1669.8 9256111 9899107 32000000 1 53 53 1645.2 3081.0 7855010 6057257 32800000 1 54 55 1835.3 3122.0 6899141 6143875 33600000 1 56 56 1916.8 1734.8 10271967 6049509 34400000 1 57 57 3119.2 1630.8 11503274 13975417 35200000 1 58 58 1629.2 1695.7 6827225 6214248 36000000 1 60 60 1636.5 1695.4 38077664 16211067 36800000 1 61 61 1665.2 2069.1 19948817 9358494 37600000 1 62 62 1734.5 1931.5 26487196 8954836 38400000 1 63 63 1625.8 1654.0 6649289 9131844 39200000 1 65 65 1778.4 1663.3 11653376 7144960 40000000 1 66 66 1851.0 1935.6 8164470 11288753 40800000 1 67 67 3171.0 3431.6 12358380 6072820 41600000 1 69 69 1714.3 1954.3 13765035 9364495 42400000 1 70 70 1591.0 1681.8 18733304 7407689 43200000 1 71 71 1537.2 1642.8 19534908 6163018 44000000 1 72 72 1630.3 1641.2 23479883 10967509 44800000 1 74 74 1877.5 1651.9 8174965 9484587 45600000 1 75 75 3322.4 1653.6 14740938 7497831 46400000 1 76 76 1706.9 1840.6 10348550 23296562 47200000 1 77 78 1837.7 2515.3 13917543 14683192 48000000 1 79 79 1642.6 2368.6 14365759 6080942 48800000 1 80 80 1827.1 1655.2 9234312 7412406 49600000 1 81 81 1631.0 1858.7 7543970 18610881 50400000 1 82 82 1560.5 1865.0 21374219 6598771
Quoted 1 line
From the above table, when the same count files with same size are created, how FS is full is
basically same.
2. FFSB test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1large_file_create
1 thread
- Trans/sec 28918.75 29014.48 +0.33%
- Throughput 113MB/sec 113MB/sec +0.0%
- %CPU 4.8% 5.1% +6.3%
- Trans/%CPU 602473.96 568911.37 -5.6%
8 threads
- Trans/sec 28480.37 28541.25 +0.2%
- Throughput 111MB/sec 111MB/sec +0.0%
- %CPU 5.6% 5.9% +5.4%
- Trans/%CPU 508578.04 483750 -4.9%
32 threads
- Trans/sec 25011.86 26992.32 +7.9%
- Throughput 97.7MB/sec 105MB/sec +7.5%
- %CPU 6.2% 7.1% +14.8%
- Trans/%CPU 403417.10 380173.52 -5.8%
large_file_seq_read
1 thread
- Trans/sec 35303.23 34838.02 -1.3%
- Throughput 138MB/sec 136MB/sec -1.4%
- %CPU 5.4% 5.4% +0.0%
- Trans/%CPU 653763.52 645148.52 -1.3%
8 threads
- Trans/sec 11902.82 11205.22 -5.9%
- Throughput 46.5MB/sec 43.8MB/sec -5.8%
- %CPU 2.1% 2.0% -4.8%
- Trans/%CPU 566800.95 560261 -1.2%
32 threads
- Trans/sec 5068.48 5316.36 +4.9%
- Throughput 19.8MB/sec 20.8MB/sec +5.1%
- %CPU 0.9% 1.0% +11.1%
- Trans/%CPU 563164.45 531636 -5.6%
random_write
1 thread
- Trans/sec 729.01 738.89 +1.4%
- Throughput 99.7MB/sec 101MB/sec +1.3%
- %CPU 0.1% 0.1% +0.0%
- Trans/%CPU 72901 73889 +1.4%
8 threads
- Trans/sec 714.56 714.57 +0.0%
- Throughput 97.7MB/sec 97.7MB/sec +0.0%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 35728 35728.5 +0.0%
32 threads
- Trans/sec 698.62 692.59 -0.9%
- Throughput 95.5MB/sec 94.7MB/sec -0.8%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 34931 34629.5 -0.9%
random_read
1 thread
- Trans/sec 225.49 227.03 +0.7%
- Throughput 902KB/sec 908KB/sec +0.7%
- %CPU 1.1% 1.1% +0.0%
- Trans/%CPU 20499.10 20639.10 +0.7%
8 threads
- Trans/sec 106.72 105.76 -0.9%
- Throughput 427KB/sec 423KB/sec -0.9%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2134.4 2115.2 -0.9%
32 threads
- Trans/sec 107.44 108.26 +0.8%
- Throughput 430KB/sec 433KB/sec +0.7%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2148.8 2165.2 +0.8%
mail_server
1 thread
- Trans/sec 681.67 732.66 +7.5%
- Throughput [read] 1.77MB/sec 1.99MB/sec +12.4%
- Throughput [write] 858KB/sec 887KB/sec +3.4%
- %CPU 0.6% 0.6% +0.0%
- Trans/%CPU 11361.17 12211 +7.5%
8 threads
- Trans/sec 630.48 597.08 -5.3%
- Throughput [read] 1.64MB/sec 1.54MB/sec -6.1%
- Throughput [write] 814KB/sec 784KB/sec -3.7%
- %CPU 0.6% 0.5% -16.7%
- Trans/%CPU 10508 11941.6 +13.6%
32 threads
- Trans/sec 598.68 566.05 -5.5%
- Throughput [read] 1.53MB/sec 1.5MB/sec -2.0%
- Throughput [write] 804KB/sec 705KB/sec -12.3%
- %CPU 0.7% 0.6% -14.2%
- Trans/%CPU 8552.57 9434.17 +10.3%
3. Compilebench test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1
intial create 114.81 MB/s 118.32 MB/s +3.1% create 11.98 MB/s 12.26 MB/s +2.3% patch 3.61 MB/s 3.66 MB/s +1.4% compile 46.40 MB/s 48.07 MB/s +3.6% clean 126.33 MB/s 128.75 MB/s +1.9% read tree 9.93 MB/s 9.71 MB/s -2.2% read compiled tree 17.19 MB/s 17.52 MB/s +1.9% delete tree 12.23 seconds 11.13 seconds -9.0% delete compiled tree 12.98 seconds 16.05 seconds +26.7% stat tree 7.03 seconds 5.51 seconds -21.6% stat compiled tree 12.19 seconds 9.06 seconds -25.7%
Changelog:
- Solved 64 bits inode number issue. [David Sterba]
- Embed struct hot_type in struct file_system_type [Darrick J. Wong]
- Cleanup Some issues [David Sterba]
- Use a static hot debugfs root [Greg KH]
- Rewritten debugfs support based on seq_file operation. [Dave Chinner]
- Refactored workqueue support. [Dave Chinner]
- Turn some Micro into be tunable [Zhiyong, Zheng Liu]
TIME_TO_KICK, and HEAT_UPDATE_DELAY
- Introduce hot func registering framework [Zhiyong]
- Remove global variable for hot tracking [Zhiyong]
- Add xfs hot tracking support [Dave Chinner]
- Add ext4 hot tracking support [Zheng Liu]
- Cleanedup a lot of other issues [Dave Chinner]
- Added memory shrinker [Dave Chinner]
- Converted to one workqueue to update map info periodically [Dave Chinner]
- Cleanedup a lot of other issues [Dave Chinner]
- Reduce new files and put all in fs/hot_tracking.[ch] [Dave Chinner]
- Add btrfs hot tracking support [Zhiyong]
- The first three patches can probably just be flattened into one. [Marco Stornelli , Dave Chinner]
Zhi Yong Wu (16):
vfs: introduce some data structures
vfs: add init and cleanup functions
vfs: add I/O frequency update function
vfs: add two map arrays
vfs: add hooks to enable hot tracking
vfs: add temp calculation function
vfs: add map info update function
vfs: add aging function
vfs: add one work queue
vfs: add FS hot type support
vfs: register one shrinker
vfs: add one ioctl interface
vfs: add debugfs support
proc: add two hot_track proc files
btrfs: add hot tracking support
vfs: add documentation
Documentation/filesystems/00-INDEX | 2 + Documentation/filesystems/hot_tracking.txt | 255 ++++++ fs/Makefile | 2 +- fs/btrfs/ctree.h | 1 + fs/btrfs/super.c | 22 +- fs/compat_ioctl.c | 5 + fs/dcache.c | 2 + fs/direct-io.c | 6 + fs/hot_tracking.c | 1345 ++++++++++++++++++++++++++++ fs/hot_tracking.h | 52 ++ fs/ioctl.c | 74 ++ include/linux/fs.h | 5 + include/linux/hot_tracking.h | 152 ++++ kernel/sysctl.c | 14 + mm/filemap.c | 6 + mm/page-writeback.c | 12 + mm/readahead.c | 7 + 17 files changed, 1960 insertions(+), 2 deletions(-) create mode 100644 Documentation/filesystems/hot_tracking.txt create mode 100644 fs/hot_tracking.c create mode 100644 fs/hot_tracking.h create mode 100644 include/linux/hot_tracking.h
Signature · 1 line
1.7.6.5
PATCH RESEND 1/16 vfs: introduce some data structures
From: Zhi Yong Wu <[email protected]>
One root structure hot_info is defined, is hooked
up in super_block, and will be used to hold radix tree root, hash list root and some other information, etc.
Adds hot_inode_tree struct to keep track of
frequently accessed files, and be keyed by {inode, offset}. Trees contain hot_inode_items representing those files and ranges.
Having these trees means that vfs can quickly determine the
temperature of some data by doing some calculations on the hot_freq_data struct that hangs off of the tree item.
Define two items hot_inode_item and hot_range_item,
one of them represents one tracked file
to keep track of its access frequency and the tree of ranges in this file, while the latter represents
a file range of one inode.
Each of the two structures contains a hot_freq_data
struct with its frequency of access metrics (number of {reads, writes}, last {read,write} time, frequency of {reads,writes}).
Also, each hot_inode_item contains one hot_range_tree
struct which is keyed by {inode, offset, length} and used to keep track of all the ranges in this file.
--- fs/Makefile | 2 +- fs/dcache.c | 2 + fs/hot_tracking.c | 109 ++++++++++++++++++++++++++++++++++++++++++ fs/hot_tracking.h | 22 ++++++++ include/linux/hot_tracking.h | 78 ++++++++++++++++++++++++++++++ 5 files changed, 212 insertions(+), 1 deletions(-) create mode 100644 fs/hot_tracking.c create mode 100644 fs/hot_tracking.h create mode 100644 include/linux/hot_tracking.h
fs/Makefile +1 -1
@@ -11,7 +11,7 @@ obj-y := open.o read_write.o file_table.o super.o \ attr.o bad_inode.o file.o filesystems.o namespace.o \ seq_file.o xattr.o libfs.o fs-writeback.o \ pnode.o drop_caches.o splice.o sync.o utimes.o \ - stack.o fs_struct.o statfs.o + stack.o fs_struct.o statfs.o hot_tracking.o ifeq ($(CONFIG_BLOCK),y) obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
fs/dcache.c +2 -0
@@ -37,6 +37,7 @@#include <linux/rculist_bl.h> #include <linux/prefetch.h> #include <linux/ratelimit.h> +#include <linux/hot_tracking.h> #include "internal.h" #include "mount.h"
@@ -3172,4 +3173,5 @@ void __init vfs_caches_init(unsigned long mempages)mnt_init ();bdev_cache_init ();chrdev_init (); +hot_cache_init (); }
fs/hot_tracking.c new file +109 -0
109 lines not on this page · raw message
fs/hot_tracking.h new file +22 -0
@@ -0,0 +1,22 @@ +/* +* fs/hot_tracking.h +* +* Copyright (C) 2012 IBM Corp. All rights reserved. +* Written by Zhi Yong Wu <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public +* License v2 as published by the Free Software Foundation. +*/ + +#ifndef __HOT_TRACKING__ +#define __HOT_TRACKING__ + +#include <linux/workqueue.h> +#include <linux/hot_tracking.h> + +/* values for hot_freq_data flags */ +#define FREQ_DATA_TYPE_INODE (1 << 0) +#define FREQ_DATA_TYPE_RANGE (1 << 1) + +#endif /* __HOT_TRACKING__ */
include/linux/hot_tracking.h new file +78 -0
78 lines not on this page · raw message
Signature · 1 line
1.7.6.5
Re: [PATCH RESEND v1 01/16] vfs: introduce some data structures
Quoted 7 lines · On Thu, Dec 20, 2012 at 10:43:20PM +0800, [email protected] wrote:
fs/hot_tracking.c new file +2
-0@@ -0,0 +1,109 @@ +/* +* fs/hot_tracking.c From what I've undrestood the file name written here is not wanted, so
please drop it (and from .h too)
Quoted 7 lines
+ *
+ * Copyright (C) 2012 IBM Corp. All rights reserved.
+ * Written by Zhi Yong Wu <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
A short description of the hot tracking feature or pointer to the Documentation/ file would be nice here.
Quoted 5 lines
+ */
fs/hot_tracking.c new file +4
-0+ +#include <linux/list.h> +#include <linux/err.h> +#include <linux/slab.h>
fs/hot_tracking.c line 24
Quoted 10 lines
fs/hot_tracking.c new file +10
-0+#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/hardirq.h> +#include <linux/fs.h> +#include <linux/blkdev.h> +#include <linux/types.h> +#include <linux/limits.h> +#include "hot_tracking.h" + +/* kmem_cache pointers for slab caches */
This comment seems useless to me, I does not help understanding the code, just says the same what reads in C. There are more such redundant comments in the series, but I'm not going point to all of them right now.
Quoted 12 lines
fs/hot_tracking.c new file +3
-0+static struct kmem_cache *hot_inode_item_cachep__read_mostly ; +static struct kmem_cache *hot_range_item_cachep__read_mostly ; +include/linux/hot_tracking.h new file +6
-0+/* The common info for both following structures */ +struct hot_comm_item { +struct rb_node rb_node;/* rbtree index */ +struct hot_freq_data hot_freq_data;/* frequency data */ +spinlock_t lock;/* protects object data */ +struct kref refs;/* prevents kfree */
include/linux/hot_tracking.h line 58
Quoted 10 lines
include/linux/hot_tracking.h new file +10
-0+}; + +/* An item representing an inode and its access frequency */ +struct hot_inode_item { +struct hot_comm_item hot_inode;/* node in hot_inode_tree */ +struct hot_rb_tree hot_range_tree;/* tree of ranges */ +spinlock_t lock;/* protect range tree */ +struct hot_rb_tree *hot_inode_tree; +u64 i_ino;/* inode number from inode */ +};
Please align the comments to something like this (or drop them if they seem redundant):
/* The common info for both following structures */ struct hot_comm_item {
struct rb_node rb_node; /* rbtree index */
struct hot_freq_data hot_freq_data; /* frequency data */
spinlock_t lock; /* protects object data */
struct kref refs; /* prevents kfree */
struct list_head n_list; /* list node index */};
/* An item representing an inode and its access frequency */ struct hot_inode_item {
struct hot_comm_item hot_inode; /* node in hot_inode_tree */
struct hot_rb_tree hot_range_tree; /* tree of ranges */
spinlock_t lock; /* protect range tree */ struct hot_rb_tree *hot_inode_tree;
u64 i_ino; /* inode number from inode */
};
Quoted 1 line
+extern void
__inithot_cache_init(void);
this belongs to the private include fs/hot_tracking.h (because this is called only once by vfs init and not by filesystems), there's hot_track_init(superblock) for that purpose introduced later.
david
Re: [PATCH RESEND v1 01/16] vfs: introduce some data structures
Quoted 9 lines · David Sterba
fs/hot_tracking.c line 2
Quoted 5 lines · On Thu, Dec 20, 2012 at 10:43:20PM +0800, [email protected] wrote:
fs/hot_tracking.c new file +2
-0@@ -0,0 +1,109 @@ +/* +* fs/hot_tracking.c From what I've undrestood the file name written here is not wanted, so please drop it (and from .h too)
Done.
Quoted 11 lines
fs/hot_tracking.c line 9
Quoted 8 lines
fs/hot_tracking.c new file +7
-0+* +* Copyright (C) 2012 IBM Corp. All rights reserved. +* Written by Zhi Yong Wu <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public +* License v2 as published by the Free Software Foundation. A short description of the hot tracking feature or pointer to the
Documentation/file would be nice here.
ok, Done
Quoted 12 lines
Quoted 12 lines
fs/hot_tracking.c new file +11
-0+*/ + +#include <linux/list.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/hardirq.h> +#include <linux/fs.h> +#include <linux/blkdev.h> +#include <linux/types.h>
Quoted 8 lines
fs/hot_tracking.c line 24
Quoted 4 lines
fs/hot_tracking.c new file +4
-0+#include <linux/limits.h> +#include "hot_tracking.h" + +/* kmem_cache pointers for slab caches */ This comment seems useless to me, I does not help understanding the code, just says the same what reads in C. There are more such redundant comments in the series, but I'm not going point to all of them right now.
Removed.
Quoted 18 lines
Quoted 18 lines
fs/hot_tracking.c new file +3
-0+static struct kmem_cache *hot_inode_item_cachep__read_mostly ; +static struct kmem_cache *hot_range_item_cachep__read_mostly ; +include/linux/hot_tracking.h new file +11
-0+/* The common info for both following structures */ +struct hot_comm_item { +struct rb_node rb_node;/* rbtree index */ +struct hot_freq_data hot_freq_data;/* frequency data */ +spinlock_t lock;/* protects object data */ +struct kref refs;/* prevents kfree */ +}; + +/* An item representing an inode and its access frequency */ +struct hot_inode_item { +struct hot_comm_item hot_inode;/* node in hot_inode_tree */
Quoted 8 lines
include/linux/hot_tracking.h line 58
Quoted 5 lines
include/linux/hot_tracking.h new file +5
-0+struct hot_rb_tree hot_range_tree;/* tree of ranges */ +spinlock_t lock;/* protect range tree */ +struct hot_rb_tree *hot_inode_tree; +u64 i_ino;/* inode number from inode */ +};Please align the comments to something like this (or drop them if they seem redundant):
Done
Quoted 19 lines
/* The common info for both following structures */ struct
hot_comm_item{struct rb_node rb_node; /* rbtree index */ struct hot_freq_data hot_freq_data; /* frequency data */ spinlock_t lock; /* protects object data */ struct kref refs; /* prevents kfree */ struct list_head n_list; /* list node index */};
/* An item representing an inode and its access frequency */ struct
hot_inode_item{struct hot_comm_item hot_inode; /* node in hot_inode_tree */ struct hot_rb_tree hot_range_tree; /* tree of ranges */ spinlock_t lock; /* protect range tree */struct
hot_rb_tree*hot_inode_tree;
u64i_ino; /* inode number from inode */
};
Quoted 5 lines
Quoted 1 line
+extern void
__inithot_cache_init(void);this belongs to the private include
fs/hot_tracking.h(because this is called only once by vfs init and not by filesystems), there'shot_track_init(superblock)for that purpose introduced later.
Done, Move it to fs/hot_tracking.h
Quoted 3 lines
david
Signature · 3 lines
Regards, Zhi Yong Wu
PATCH RESEND 2/16 vfs: add init and cleanup functions
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Add initialization function to create some
key data structures when hot tracking is enabled;
Clean up them when hot tracking is disabled
--- fs/hot_tracking.c | 117 ++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 4 ++ include/linux/hot_tracking.h | 3 + 3 files changed, 124 insertions(+), 0 deletions(-)
fs/hot_tracking.c +117 -0
@@ -76,12 +76,94 @@ static void hot_inode_item_init(struct hot_inode_item *he, he->hot_inode_tree = hot_inode_tree;kref_init (&he->hot_inode.refs);spin_lock_init (&he->hot_inode.lock); +INIT_LIST_HEAD (&he->hot_inode.n_list); he->hot_inode.hot_freq_data.avg_delta_reads = (u64) -1 ; he->hot_inode.hot_freq_data.avg_delta_writes = (u64) -1 ; he->hot_inode.hot_freq_data.flags =FREQ_DATA_TYPE_INODE ;hot_range_tree_init (he); } +static void hot_range_item_free (struct kref *kref) +{ +struct hot_comm_item *comm_item =container_of (kref, + struct hot_comm_item, refs); +struct hot_range_item *hr =container_of (comm_item, + struct hot_range_item, hot_range); + +rb_erase (&hr->hot_range.rb_node, + &hr->hot_inode->hot_range_tree.map); +kmem_cache_free (hot_range_item_cachep, hr); +} + +/* +* Drops the reference out on hot_range_item by one +* and free the structure if the reference count hits zero +*/ +static void hot_range_item_put (struct hot_range_item *hr) +{ +kref_put (&hr->hot_range.refs, hot_range_item_free); +} + +/* Frees the entire hot_range_tree. */ +static void hot_range_tree_free (struct hot_inode_item *he) +{ +struct rb_node *node; +struct hot_comm_item *ci; +struct hot_range_item *hr; + +/* Free hot inode and range trees on fs root */ +spin_lock (&he->lock); +while ((node =rb_first (&he->hot_range_tree.map))) { + ci = rb_entry(node, struct hot_comm_item, rb_node); + hr =container_of (ci, + struct hot_range_item, hot_range); +hot_range_item_put (hr); + } +spin_unlock (&he->lock); +} + +static void hot_inode_item_free (struct kref *kref) +{ +struct hot_comm_item *comm_item =container_of (kref, + struct hot_comm_item, refs); +struct hot_inode_item *he =container_of (comm_item, + struct hot_inode_item, hot_inode); + +hot_range_tree_free (he); +spin_lock (&he->hot_inode.lock); +rb_erase (&he->hot_inode.rb_node, &he->hot_inode_tree->map); +spin_unlock (&he->hot_inode.lock); +kmem_cache_free (hot_inode_item_cachep, he); +} + +/* +* Drops the reference out on hot_inode_item by one +* and free the structure if the reference count hits zero +*/ +void hot_inode_item_put (struct hot_inode_item *he) +{ +kref_put (&he->hot_inode.refs, hot_inode_item_free); +} +EXPORT_SYMBOL_GPL (hot_inode_item_put); + +/* Frees the entire hot_inode_tree. */ +static void hot_inode_tree_exit (struct hot_info *root) +{ +struct rb_node *node; +struct hot_comm_item *ci; +struct hot_inode_item *he; + +/* Free hot inode and range trees on fs root */ +spin_lock (&root->lock); +while ((node =rb_first (&root->hot_inode_tree.map))) { + ci = rb_entry(node, struct hot_comm_item, rb_node); + he =container_of (ci, + struct hot_inode_item, hot_inode); +hot_inode_item_put (he); + } +spin_unlock (&root->lock); +} +/* * Initialize kmem cache for hot_inode_item and hot_range_item. */
@@ -107,3 +189,38 @@ err:kmem_cache_destroy (hot_inode_item_cachep); }EXPORT_SYMBOL_GPL (hot_cache_init); + +/* +* Initialize the data structures for hot data tracking. +*/ +int hot_track_init (struct super_block *sb) +{ +struct hot_info *root; +int ret = -ENOMEM ; + + root =kzalloc (sizeof (struct hot_info ),GFP_NOFS ); +if (!root) { +printk (KERN_ERR "%s: Failed to malloc memory for " +"hot_info\n" , __func__); +return ret; + } + +hot_inode_tree_init (root); + + sb->s_hot_root = root; + +printk (KERN_INFO "VFS: Turning on hot data tracking\n" ); + +return 0 ; +} +EXPORT_SYMBOL_GPL (hot_track_init); + +void hot_track_exit (struct super_block *sb) +{ +struct hot_info *root = sb->s_hot_root; + +hot_inode_tree_exit (root); + sb->s_hot_root =NULL ; +kfree (root); +} +EXPORT_SYMBOL_GPL (hot_track_exit);
include/linux/fs.h +4 -0
@@ -27,6 +27,7 @@#include <linux/lockdep.h> #include <linux/percpu-rwsem.h> #include <linux/blk_types.h> +#include <linux/hot_tracking.h> #include <asm/byteorder.h> #include <uapi/linux/fs.h>
@@ -1320,6 +1321,9 @@ struct super_block {/* Being remounted read-only */ int s_readonly_remount; + +/* Hot data tracking*/ +struct hot_info *s_hot_root; };/* superblock cache pruning functions */
include/linux/hot_tracking.h +3 -0
@@ -74,5 +74,8 @@ struct hot_info { };extern void __init hot_cache_init (void ); +extern int hot_track_init (struct super_block *sb); +extern void hot_track_exit (struct super_block *sb); +extern void hot_inode_item_put (struct hot_inode_item *he);#endif /* _LINUX_HOTTRACK_H */
Signature · 1 line
1.7.6.5
Re: [PATCH RESEND v1 02/16] vfs: add init and cleanup functions
Quoted 14 lines · On Thu, Dec 20, 2012 at 10:43:21PM +0800, [email protected] wrote:
From: Zhi Yong Wu <[email protected]>
fs/hot_tracking.c +7
-0@@ -107,3 +189,38 @@ err:kmem_cache_destroy (hot_inode_item_cachep); }EXPORT_SYMBOL_GPL (hot_cache_init); + +/* +* Initialize the data structures for hot data tracking. +*/ +int hot_track_init (struct super_block *sb) +{ +struct hot_info *root;
fs/hot_tracking.c err: · line 208
Quoted 10 lines
fs/hot_tracking.c +10
-0+int ret = -ENOMEM ; + + root =kzalloc (sizeof (struct hot_info ),GFP_NOFS ); +if (!root) { +printk (KERN_ERR "%s: Failed to malloc memory for " +"hot_info\n" , __func__); +return ret; + } + +hot_inode_tree_init (root);
This function is supposed to be called from the filesystem init, please add a sanity check that would catch multiple initialization attempts.
fs/hot_tracking.c err: · line 220
Quoted 12 lines
fs/hot_tracking.c +12
-0+ + sb->s_hot_root = root; + +printk (KERN_INFO "VFS: Turning on hot data tracking\n" ); + +return 0 ; +} +EXPORT_SYMBOL_GPL (hot_track_init); + +void hot_track_exit (struct super_block *sb) +{ +struct hot_info *root = sb->s_hot_root;
another sanity check to catch the opposite.
Why? The option is parsed and enabled from the filesystems, due to unexpected bugs eg with remounting or incorrectly handled error paths, vfs layer should IMHO rather warn than crash.
fs/hot_tracking.c err: · line 226
Quoted 6 lines
fs/hot_tracking.c +6
-0+ +hot_inode_tree_exit (root); + sb->s_hot_root =NULL ; +kfree (root); +} +EXPORT_SYMBOL_GPL (hot_track_exit);
david
Re: [PATCH RESEND v1 02/16] vfs: add init and cleanup functions
Quoted 20 lines · David Sterba
Quoted 19 lines · On Thu, Dec 20, 2012 at 10:43:21PM +0800, [email protected] wrote:
From: Zhi Yong Wu <[email protected]>
fs/hot_tracking.c +12
-0@@ -107,3 +189,38 @@ err:kmem_cache_destroy (hot_inode_item_cachep); }EXPORT_SYMBOL_GPL (hot_cache_init); + +/* +* Initialize the data structures for hot data tracking. +*/ +int hot_track_init (struct super_block *sb) +{ +struct hot_info *root; +int ret = -ENOMEM ; + + root =kzalloc (sizeof (struct hot_info ),GFP_NOFS ); +if (!root) { + printk(KERN_ERR "%s: Failed to malloc memory for "
Quoted 8 lines
fs/hot_tracking.c err: · line 208
Quoted 5 lines
fs/hot_tracking.c +5
-0+ "hot_info\n", __func__); +return ret; + } + +hot_inode_tree_init (root);This function is supposed to be called from the filesystem init, please add a sanity check that would catch multiple initialization attempts.
Good catch, thanks. Done.
Quoted 15 lines
fs/hot_tracking.c err: · line 220
Quoted 13 lines
fs/hot_tracking.c +12
-0+ + sb->s_hot_root = root; + +printk (KERN_INFO "VFS: Turning on hot data tracking\n" ); + +return 0 ; +} +EXPORT_SYMBOL_GPL (hot_track_init); + +void hot_track_exit (struct super_block *sb) +{ +struct hot_info *root = sb->s_hot_root;another sanity check to catch the opposite.
ditto.
Quoted 4 lines
Why? The option is parsed and enabled from the filesystems, due to unexpected bugs eg with remounting or incorrectly handled error paths, vfs layer should IMHO rather warn than crash.
thanks for your expalaination.
Quoted 10 lines
fs/hot_tracking.c err: · line 226
Quoted 7 lines
fs/hot_tracking.c +6
-0+ +hot_inode_tree_exit (root); + sb->s_hot_root =NULL ; +kfree (root); +} +EXPORT_SYMBOL_GPL (hot_track_exit);david
Signature · 3 lines
Regards, Zhi Yong Wu
PATCH RESEND 3/16 vfs: add I/O frequency update function
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Add some util helpers to update access frequencies
for one file or its range.
--- fs/hot_tracking.c | 178 ++++++++++++++++++++++++++++++++++++++++++ fs/hot_tracking.h | 5 + include/linux/hot_tracking.h | 4 + 3 files changed, 187 insertions(+), 0 deletions(-)
fs/hot_tracking.c +178 -0
@@ -164,6 +164,135 @@ static void hot_inode_tree_exit(struct hot_info *root)spin_unlock (&root->lock); } +struct hot_inode_item +*hot_inode_item_lookup (struct hot_info *root,u64 ino) +{ +struct rb_node **p = &root->hot_inode_tree.map.rb_node; +struct rb_node *parent =NULL ; +struct hot_comm_item *ci; +struct hot_inode_item *entry; + +/* walk tree to find insertion point */ +spin_lock (&root->lock); +while (*p) { + parent = *p; + ci = rb_entry(parent, struct hot_comm_item, rb_node); + entry = container_of(ci, struct hot_inode_item, hot_inode); +if (ino < entry->i_ino) + p = &(*p)->rb_left; +else if (ino > entry->i_ino) + p = &(*p)->rb_right; +else { +spin_unlock (&root->lock); +kref_get (&entry->hot_inode.refs); +return entry; + } + } +spin_unlock (&root->lock); + + entry =kmem_cache_zalloc (hot_inode_item_cachep,GFP_NOFS ); +if (!entry) +return ERR_PTR (-ENOMEM ); + +spin_lock (&root->lock); +hot_inode_item_init (entry, ino, &root->hot_inode_tree); +rb_link_node (&entry->hot_inode.rb_node, parent, p); +rb_insert_color (&entry->hot_inode.rb_node, + &root->hot_inode_tree.map); +spin_unlock (&root->lock); + +kref_get (&entry->hot_inode.refs); +return entry; +} +EXPORT_SYMBOL_GPL (hot_inode_item_lookup); + +static loff_t hot_range_end (struct hot_range_item *hr) +{ +if (hr->start + hr->len < hr->start) +return (loff_t)-1 ; + +return hr->start + hr->len -1 ; +} + +static struct hot_range_item +*hot_range_item_lookup (struct hot_inode_item *he, +loff_t start) +{ +struct rb_node **p = &he->hot_range_tree.map.rb_node; +struct rb_node *parent =NULL ; +struct hot_comm_item *ci; +struct hot_range_item *entry; + +/* walk tree to find insertion point */ +spin_lock (&he->lock); +while (*p) { + parent = *p; + ci = rb_entry(parent, struct hot_comm_item, rb_node); + entry = container_of(ci, struct hot_range_item, hot_range); +if (start < entry->start) + p = &(*p)->rb_left; +else if (start >hot_range_end (entry)) + p = &(*p)->rb_right; +else { +spin_unlock (&he->lock); +kref_get (&entry->hot_range.refs); +return entry; + } + } +spin_unlock (&he->lock); + + entry =kmem_cache_zalloc (hot_range_item_cachep,GFP_NOFS ); +if (!entry) +return ERR_PTR (-ENOMEM ); + +spin_lock (&he->lock); +hot_range_item_init (entry, start, he); +rb_link_node (&entry->hot_range.rb_node, parent, p); +rb_insert_color (&entry->hot_range.rb_node, + &he->hot_range_tree.map); +spin_unlock (&he->lock); + +kref_get (&entry->hot_range.refs); +return entry; +} + +/* +* This function does the actual work of updating +* the frequency numbers, whatever they turn out to be. +*/ +static void hot_rw_freq_calc (struct timespec old_atime, +struct timespec cur_time,u64 *avg) +{ +struct timespec delta_ts; +u64 new_delta; + + delta_ts =timespec_sub (cur_time, old_atime); + new_delta =timespec_to_ns (&delta_ts) >>FREQ_POWER ; + + *avg = (*avg <<FREQ_POWER ) - *avg + new_delta; + *avg = *avg >>FREQ_POWER ; +} + +static void hot_freq_data_update (struct hot_freq_data *freq_data,bool write) +{ +struct timespec cur_time =current_kernel_time (); + +if (write) { + freq_data->nr_writes +=1 ; +hot_rw_freq_calc (freq_data->last_write_time, + cur_time, + &freq_data->avg_delta_writes); + freq_data->last_write_time = cur_time; + }else { + freq_data->nr_reads +=1 ; +hot_rw_freq_calc (freq_data->last_read_time, + freq_data->last_read_time, + cur_time, + &freq_data->avg_delta_reads); + freq_data->last_read_time = cur_time; + } +} +/* * Initialize kmem cache for hot_inode_item and hot_range_item. */
@@ -191,6 +320,55 @@ err:EXPORT_SYMBOL_GPL (hot_cache_init);/* +* Main function to update access frequency from read/writepage(s) hooks +*/ +void hot_update_freqs (struct inode *inode,loff_t start, +size_t len,int rw) +{ +struct hot_info *root = inode->i_sb->s_hot_root; +struct hot_inode_item *he; +struct hot_range_item *hr; +loff_t cur, end; + +if (!root || (len ==0 )) +return ; + + he =hot_inode_item_lookup (root, inode->i_ino); +if (IS_ERR (he)) { +WARN_ON (1 ); +return ; + } + +spin_lock (&he->hot_inode.lock); +hot_freq_data_update (&he->hot_inode.hot_freq_data, rw); +spin_unlock (&he->hot_inode.lock); + +/* +* Align ranges on RANGE_SIZE boundary +* to prevent proliferation of range structs +*/ + end = (start + len +RANGE_SIZE -1 ) >>RANGE_BITS ; +for (cur = (start >>RANGE_BITS ); cur < end; cur++) { + hr =hot_range_item_lookup (he, cur); +if (IS_ERR (hr)) { +WARN (1 ,"hot_range_item_lookup returns %ld\n" , +PTR_ERR (hr)); +hot_inode_item_put (he); +return ; + } + +spin_lock (&hr->hot_range.lock); +hot_freq_data_update (&hr->hot_range.hot_freq_data, rw); +spin_unlock (&hr->hot_range.lock); + +hot_range_item_put (hr); + } + +hot_inode_item_put (he); +} +EXPORT_SYMBOL_GPL (hot_update_freqs); + +/* * Initialize the data structures for hot data tracking. */ int hot_track_init (struct super_block *sb)
fs/hot_tracking.h +5 -0
@@ -19,4 +19,9 @@#define FREQ_DATA_TYPE_INODE (1 << 0)#define FREQ_DATA_TYPE_RANGE (1 << 1) +/* size of sub-file ranges */ +#define RANGE_BITS 20 +#define RANGE_SIZE (1 << RANGE_BITS) +#define FREQ_POWER 4 +#endif /* __HOT_TRACKING__ */
include/linux/hot_tracking.h +4 -0
@@ -77,5 +77,9 @@ extern void __init hot_cache_init(void);extern int hot_track_init (struct super_block *sb);extern void hot_track_exit (struct super_block *sb);extern void hot_inode_item_put (struct hot_inode_item *he); +extern void hot_update_freqs (struct inode *inode,loff_t start, +size_t len,int rw); +extern struct hot_inode_item *hot_inode_item_lookup (struct hot_info *root, +u64 ino);#endif /* _LINUX_HOTTRACK_H */
Signature · 1 line
1.7.6.5
Re: [PATCH RESEND v1 03/16] vfs: add I/O frequency update function
Quoted 14 lines · On Thu, Dec 20, 2012 at 10:43:22PM +0800, [email protected] wrote:
fs/hot_tracking.c +8
-0@@ -164,6 +164,135 @@ static void hot_inode_tree_exit(struct hot_info *root)spin_unlock (&root->lock); } +struct hot_inode_item +*hot_inode_item_lookup (struct hot_info *root,u64 ino) +{ +struct rb_node **p = &root->hot_inode_tree.map.rb_node; +struct rb_node *parent =NULL ; +struct hot_comm_item *ci; +struct hot_inode_item *entry; +
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 184
Quoted 10 lines
fs/hot_tracking.c +10
-0+/* walk tree to find insertion point */ +spin_lock (&root->lock); +while (*p) { + parent = *p; + ci = rb_entry(parent, struct hot_comm_item, rb_node); + entry = container_of(ci, struct hot_inode_item, hot_inode); +if (ino < entry->i_ino) + p = &(*p)->rb_left; +else if (ino > entry->i_ino) + p = &(*p)->rb_right;
style comment: put { } around the all if/else blocks
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 187
Quoted 3 lines
fs/hot_tracking.c +3
-0+else { +spin_unlock (&root->lock); +kref_get (&entry->hot_inode.refs);
jumping forwards in the series, the spin_unlock and kref_get get swapped later, and I think that's the right order. Otherwise there's a small window where the entry does not get the reference and could be potentially freed by racing kref_put, no?
<lookup entry E>spin_unlock(tree)
spin_lock(tree)
<lookup entry E>
kref_put(E) or via hot_inode_item_put(E) (1)kref_get(E) (2)
if the reference count at (1) was 1, it's freed and (2) hits a free memory. hot_inode_item_put can be called from filesystem or via seq print of the respective /proc files, so I think there are chances to hit the problem.
Quoted 7 lines
fs/hot_tracking.c +7
-0+return entry; + } + } +spin_unlock (&root->lock); + + entry =kmem_cache_zalloc (hot_inode_item_cachep,GFP_NOFS ); +if (!entry)
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 204
Quoted 10 lines
fs/hot_tracking.c +10
-0+return ERR_PTR (-ENOMEM ); + +spin_lock (&root->lock); +hot_inode_item_init (entry, ino, &root->hot_inode_tree); +rb_link_node (&entry->hot_inode.rb_node, parent, p); +rb_insert_color (&entry->hot_inode.rb_node, + &root->hot_inode_tree.map); +spin_unlock (&root->lock); + +kref_get (&entry->hot_inode.refs);
Similar here, the entry is inserted into the tree but there's no refcount yet. And the order of spin_unlock/kref_get remains unchanged.
Quoted 13 lines
fs/hot_tracking.c +13
-0+return entry; +} +EXPORT_SYMBOL_GPL (hot_inode_item_lookup); + +static struct hot_range_item +*hot_range_item_lookup (struct hot_inode_item *he, +loff_t start) +{ +struct rb_node **p = &he->hot_range_tree.map.rb_node; +struct rb_node *parent =NULL ; +struct hot_comm_item *ci; +struct hot_range_item *entry; +
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 235
Quoted 10 lines
fs/hot_tracking.c +10
-0+/* walk tree to find insertion point */ +spin_lock (&he->lock); +while (*p) { + parent = *p; + ci = rb_entry(parent, struct hot_comm_item, rb_node); + entry = container_of(ci, struct hot_range_item, hot_range); +if (start < entry->start) + p = &(*p)->rb_left; +else if (start >hot_range_end (entry)) + p = &(*p)->rb_right;
if { ...}
else if { ... }
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 238
Quoted 3 lines
fs/hot_tracking.c +3
-0+else { +spin_unlock (&he->lock); +kref_get (&entry->hot_range.refs);
same here
Quoted 7 lines
fs/hot_tracking.c +7
-0+return entry; + } + } +spin_unlock (&he->lock); + + entry =kmem_cache_zalloc (hot_range_item_cachep,GFP_NOFS ); +if (!entry)
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 255
Quoted 10 lines
fs/hot_tracking.c +10
-0+return ERR_PTR (-ENOMEM ); + +spin_lock (&he->lock); +hot_range_item_init (entry, start, he); +rb_link_node (&entry->hot_range.rb_node, parent, p); +rb_insert_color (&entry->hot_range.rb_node, + &he->hot_range_tree.map); +spin_unlock (&he->lock); + +kref_get (&entry->hot_range.refs);
and here
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 261
Quoted 6 lines
fs/hot_tracking.c +6
-0+return entry; +} + +/* +* This function does the actual work of updating +* the frequency numbers, whatever they turn out to be.
Can this function be described a bit better? This comment did not help.
Quoted 10 lines
fs/hot_tracking.c +10
-0+*/ +static void hot_rw_freq_calc (struct timespec old_atime, +struct timespec cur_time,u64 *avg) +{ +struct timespec delta_ts; +u64 new_delta; + + delta_ts =timespec_sub (cur_time, old_atime); + new_delta =timespec_to_ns (&delta_ts) >>FREQ_POWER ; +
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 281
Quoted 10 lines
fs/hot_tracking.c +10
-0+ *avg = (*avg <<FREQ_POWER ) - *avg + new_delta; + *avg = *avg >>FREQ_POWER ; +} + +static void hot_freq_data_update (struct hot_freq_data *freq_data,bool write) +{ +struct timespec cur_time =current_kernel_time (); + +if (write) { + freq_data->nr_writes +=1 ;
The preferred style is
freq_data->nr_writes++
Quoted 6 lines
fs/hot_tracking.c +6
-0+hot_rw_freq_calc (freq_data->last_write_time, + cur_time, + &freq_data->avg_delta_writes); + freq_data->last_write_time = cur_time; + }else { + freq_data->nr_reads +=1 ;
(...)
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 295
Quoted 8 lines
fs/hot_tracking.c +8
-0+hot_rw_freq_calc (freq_data->last_read_time, + freq_data->last_read_time, + cur_time, + &freq_data->avg_delta_reads); + freq_data->last_read_time = cur_time; + } +} +
david
Re: [PATCH RESEND v1 03/16] vfs: add I/O frequency update function
Quoted 19 lines · David Sterba
Quoted 18 lines · On Thu, Dec 20, 2012 at 10:43:22PM +0800, [email protected] wrote:
fs/hot_tracking.c +12
-0@@ -164,6 +164,135 @@ static void hot_inode_tree_exit(struct hot_info *root)spin_unlock (&root->lock); } +struct hot_inode_item +*hot_inode_item_lookup (struct hot_info *root,u64 ino) +{ +struct rb_node **p = &root->hot_inode_tree.map.rb_node; +struct rb_node *parent =NULL ; +struct hot_comm_item *ci; +struct hot_inode_item *entry; + +/* walk tree to find insertion point */ +spin_lock (&root->lock); +while (*p) { + parent = *p;
Quoted 8 lines
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 184
Quoted 6 lines
fs/hot_tracking.c +6
-0+ ci = rb_entry(parent, struct hot_comm_item, rb_node); + entry = container_of(ci, struct hot_inode_item, hot_inode); +if (ino < entry->i_ino) + p = &(*p)->rb_left; +else if (ino > entry->i_ino) + p = &(*p)->rb_right;style comment: put { } around the all if/else blocks,
no, it will violate checkpatch.pl. If the if/else block only contains one line of code, we should not put {} around them.
Quoted 9 lines
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 187
Quoted 4 lines
fs/hot_tracking.c +3
-0+else { +spin_unlock (&root->lock); +kref_get (&entry->hot_inode.refs);jumping forwards in the series, the
spin_unlockandkref_getget swapped later, and I think that's the right order. Otherwise there's a small window where the entry does not get the reference and could be potentially freed by racingkref_put, no?
yes, good catch, thanks, done
Quoted 9 lines
<lookup entry E>
spin_unlock(tree)
spin_lock(tree)
<lookup entry E>
kref_put(E)or viahot_inode_item_put(E)(1)kref_get(E)(2)
Quoted 4 lines
if the reference count at (1) was 1, it's freed and (2) hits a free memory.
hot_inode_item_putcan be called from filesystem or via seq print of the respective /proc files, so I think there are chances to hit the problem.
Great.
Quoted 13 lines
Quoted 13 lines
fs/hot_tracking.c +12
-0+return entry; + } + } +spin_unlock (&root->lock); + + entry =kmem_cache_zalloc (hot_inode_item_cachep,GFP_NOFS ); +if (!entry) +return ERR_PTR (-ENOMEM ); + +spin_lock (&root->lock); +hot_inode_item_init (entry, ino, &root->hot_inode_tree); +rb_link_node (&entry->hot_inode.rb_node, parent, p);
Quoted 8 lines
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 204
Quoted 5 lines
fs/hot_tracking.c +5
-0+rb_insert_color (&entry->hot_inode.rb_node, + &root->hot_inode_tree.map); +spin_unlock (&root->lock); + +kref_get (&entry->hot_inode.refs);Similar here, the entry is inserted into the tree but there's no refcount yet. And the order of spin_unlock/kref_get remains unchanged.
ditto
Quoted 19 lines
Quoted 19 lines
fs/hot_tracking.c +18
-0+return entry; +} +EXPORT_SYMBOL_GPL (hot_inode_item_lookup); + +static struct hot_range_item +*hot_range_item_lookup (struct hot_inode_item *he, +loff_t start) +{ +struct rb_node **p = &he->hot_range_tree.map.rb_node; +struct rb_node *parent =NULL ; +struct hot_comm_item *ci; +struct hot_range_item *entry; + +/* walk tree to find insertion point */ +spin_lock (&he->lock); +while (*p) { + parent = *p; + ci = rb_entry(parent, struct hot_comm_item, rb_node);
Quoted 8 lines
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 235
Quoted 5 lines
fs/hot_tracking.c +5
-0+ entry = container_of(ci, struct hot_range_item, hot_range); +if (start < entry->start) + p = &(*p)->rb_left; +else if (start >hot_range_end (entry)) + p = &(*p)->rb_right;if { ...}
else if { ... }
We should not put {} around them as what i explained above.
Quoted 6 lines
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 238
Quoted 4 lines
fs/hot_tracking.c +3
-0+else { +spin_unlock (&he->lock); +kref_get (&entry->hot_range.refs);same here
Done
Quoted 12 lines
Quoted 12 lines
fs/hot_tracking.c +11
-0+return entry; + } + } +spin_unlock (&he->lock); + + entry =kmem_cache_zalloc (hot_range_item_cachep,GFP_NOFS ); +if (!entry) +return ERR_PTR (-ENOMEM ); + +spin_lock (&he->lock); +hot_range_item_init (entry, start, he);
Quoted 8 lines
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 255
Quoted 6 lines
fs/hot_tracking.c +6
-0+rb_link_node (&entry->hot_range.rb_node, parent, p); +rb_insert_color (&entry->hot_range.rb_node, + &he->hot_range_tree.map); +spin_unlock (&he->lock); + +kref_get (&entry->hot_range.refs);and here
Done
Quoted 9 lines
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 261
Quoted 7 lines
fs/hot_tracking.c +6
-0+return entry; +} + +/* +* This function does the actual work of updating +* the frequency numbers, whatever they turn out to be. Can this function be described a bit better? This comment did not help.
OK, i will
Quoted 24 lines
Quoted 11 lines
fs/hot_tracking.c +10
-0+*/ +static void hot_rw_freq_calc (struct timespec old_atime, +struct timespec cur_time,u64 *avg) +{ +struct timespec delta_ts; +u64 new_delta; + + delta_ts =timespec_sub (cur_time, old_atime); + new_delta =timespec_to_ns (&delta_ts) >>FREQ_POWER ; +fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 281
Quoted 10 lines
fs/hot_tracking.c +10
-0+ *avg = (*avg <<FREQ_POWER ) - *avg + new_delta; + *avg = *avg >>FREQ_POWER ; +} + +static void hot_freq_data_update (struct hot_freq_data *freq_data,bool write) +{ +struct timespec cur_time =current_kernel_time (); + +if (write) { + freq_data->nr_writes +=1 ;The preferred style is
Quoted 1 line
freq_data->nr_writes++
OK, done.
Quoted 20 lines
Quoted 7 lines
fs/hot_tracking.c +6
-0+hot_rw_freq_calc (freq_data->last_write_time, + cur_time, + &freq_data->avg_delta_writes); + freq_data->last_write_time = cur_time; + }else { + freq_data->nr_reads +=1 ;(...)
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 295
Quoted 8 lines
fs/hot_tracking.c +8
-0+hot_rw_freq_calc (freq_data->last_read_time, + freq_data->last_read_time, + cur_time, + &freq_data->avg_delta_reads); + freq_data->last_read_time = cur_time; + } +} +david
Signature · 3 lines
Regards, Zhi Yong Wu
Re: [PATCH RESEND v1 03/16] vfs: add I/O frequency update function
Quoted 28 lines · Zhi Yong Wu
Quoted 19 lines · David Sterba
Quoted 18 lines · On Thu, Dec 20, 2012 at 10:43:22PM +0800, [email protected] wrote:
fs/hot_tracking.c +12
-0@@ -164,6 +164,135 @@ static void hot_inode_tree_exit(struct hot_info *root)spin_unlock (&root->lock); } +struct hot_inode_item +*hot_inode_item_lookup (struct hot_info *root,u64 ino) +{ +struct rb_node **p = &root->hot_inode_tree.map.rb_node; +struct rb_node *parent =NULL ; +struct hot_comm_item *ci; +struct hot_inode_item *entry; + +/* walk tree to find insertion point */ +spin_lock (&root->lock); +while (*p) { + parent = *p;Quoted 8 lines
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 184
Quoted 6 lines
fs/hot_tracking.c +6
-0+ ci = rb_entry(parent, struct hot_comm_item, rb_node); + entry = container_of(ci, struct hot_inode_item, hot_inode); +if (ino < entry->i_ino) + p = &(*p)->rb_left; +else if (ino > entry->i_ino) + p = &(*p)->rb_right;style comment: put { } around the all if/else blocks,
Quoted 2 lines
no, it will violate checkpatch.pl. If the if/else block only contains one line of code, we should not put {} around them.
Unless its in a if / else if / else sequence, see Documentation/CodingStyle chapter 3.1. This is what I've learned long time ago and using it intuitively. I don't know to what extent checkpatch sticks to that document, the code is menat to be read by people, so if there is one style prevailing in the subsystem (and it is by looking into random fs/*.c files) it's wise to keep the style consistent.
david
Re: [PATCH RESEND v1 03/16] vfs: add I/O frequency update function
Quoted 32 lines · David Sterba
Quoted 28 lines · Zhi Yong Wu
Quoted 19 lines · David Sterba
Quoted 18 lines · On Thu, Dec 20, 2012 at 10:43:22PM +0800, [email protected] wrote:
fs/hot_tracking.c +12
-0@@ -164,6 +164,135 @@ static void hot_inode_tree_exit(struct hot_info *root)spin_unlock (&root->lock); } +struct hot_inode_item +*hot_inode_item_lookup (struct hot_info *root,u64 ino) +{ +struct rb_node **p = &root->hot_inode_tree.map.rb_node; +struct rb_node *parent =NULL ; +struct hot_comm_item *ci; +struct hot_inode_item *entry; + +/* walk tree to find insertion point */ +spin_lock (&root->lock); +while (*p) { + parent = *p;Quoted 8 lines
fs/hot_tracking.c static void hot_inode_tree_exit(struct hot_info *root) · line 184
Quoted 6 lines
fs/hot_tracking.c +6
-0+ ci = rb_entry(parent, struct hot_comm_item, rb_node); + entry = container_of(ci, struct hot_inode_item, hot_inode); +if (ino < entry->i_ino) + p = &(*p)->rb_left; +else if (ino > entry->i_ino) + p = &(*p)->rb_right;style comment: put { } around the all if/else blocks,
Quoted 2 lines
no, it will violate checkpatch.pl. If the if/else block only contains one line of code, we should not put {} around them.
Quoted 7 lines
Unless its in a if / else if / else sequence, see
Documentation/CodingStylechapter 3.1. This is what I've learned long time ago and using it intuitively. I don't know to what extent checkpatch sticks to that document, the code is menat to be read by people, so if there is one style prevailing in the subsystem (and it is by looking into randomfs/*.cfiles) it's wise to keep the style consistent.
I checked *.c in fs/, its coding style about if/else if is consistent with what i said.:)
e.g in direct-io.c
if (sdio->final_block_in_bio != sdio->cur_page_block ||
cur_offset != bio_next_offset)
dio_bio_submit(dio, sdio);
/*
* Submit now if the underlying fs is about to perform a
* metadata read
*/
else if (sdio->boundary)
dio_bio_submit(dio, sdio);Quoted 2 lines
david
Signature · 3 lines
Regards, Zhi Yong Wu
PATCH RESEND 4/16 vfs: add two map arrays
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Adds two map arrays which contains
a lot of list and is used to efficiently
look up the data temperature of a file or its
ranges.
In each list of map arrays, the array node
will keep track of temperature info.
--- fs/hot_tracking.c | 67 ++++++++++++++++++++++++++++++++++++++++++ include/linux/hot_tracking.h | 17 ++++++++++ 2 files changed, 84 insertions(+), 0 deletions(-)
fs/hot_tracking.c +67 -0
@@ -58,6 +58,7 @@ static void hot_range_item_init(struct hot_range_item *hr, loff_t start, hr->hot_inode = he;kref_init (&hr->hot_range.refs);spin_lock_init (&hr->hot_range.lock); +INIT_LIST_HEAD (&hr->hot_range.n_list); hr->hot_range.hot_freq_data.avg_delta_reads = (u64) -1 ; hr->hot_range.hot_freq_data.avg_delta_writes = (u64) -1 ; hr->hot_range.hot_freq_data.flags =FREQ_DATA_TYPE_RANGE ;
@@ -89,9 +90,20 @@ static void hot_range_item_free(struct kref *kref) struct hot_comm_item, refs);struct hot_range_item *hr =container_of (comm_item, struct hot_range_item, hot_range); +struct hot_info *root =container_of ( + hr->hot_inode->hot_inode_tree, + struct hot_info, hot_inode_tree); + +spin_lock (&hr->hot_range.lock); +if (!list_empty (&hr->hot_range.n_list)) { +list_del_init (&hr->hot_range.n_list); + root->hot_map_nr--; + }rb_erase (&hr->hot_range.rb_node, &hr->hot_inode->hot_range_tree.map); +spin_unlock (&hr->hot_range.lock); +kmem_cache_free (hot_range_item_cachep, hr); }
@@ -128,6 +140,15 @@ static void hot_inode_item_free(struct kref *kref) struct hot_comm_item, refs);struct hot_inode_item *he =container_of (comm_item, struct hot_inode_item, hot_inode); +struct hot_info *root =container_of (he->hot_inode_tree, + struct hot_info, hot_inode_tree); + +spin_lock (&he->hot_inode.lock); +if (!list_empty (&he->hot_inode.n_list)) { +list_del_init (&he->hot_inode.n_list); + root->hot_map_nr--; + } +spin_unlock (&he->hot_inode.lock);hot_range_tree_free (he);spin_lock (&he->hot_inode.lock);
@@ -294,6 +315,50 @@ static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) }/* +* Initialize inode and range map info. +*/ +static void hot_map_init (struct hot_info *root) +{ +int i; +for (i =0 ; i <HEAT_MAP_SIZE ; i++) { +INIT_LIST_HEAD (&root->heat_inode_map[i].node_list); +INIT_LIST_HEAD (&root->heat_range_map[i].node_list); + root->heat_inode_map[i].temp = i; + root->heat_range_map[i].temp = i; +spin_lock_init (&root->heat_inode_map[i].lock); +spin_lock_init (&root->heat_range_map[i].lock); + } +} + +static void hot_map_list_free (struct list_head *node_list, +struct hot_info *root) +{ +struct list_head *pos, *next; +struct hot_comm_item *node; + +list_for_each_safe (pos, next, node_list) { + node = list_entry(pos, struct hot_comm_item, n_list); +list_del_init (&node->n_list); + root->hot_map_nr--; + } + +} + +/* Free inode and range map info */ +static void hot_map_exit (struct hot_info *root) +{ +int i; +for (i =0 ; i <HEAT_MAP_SIZE ; i++) { +spin_lock (&root->heat_inode_map[i].lock); +hot_map_list_free (&root->heat_inode_map[i].node_list, root); +spin_unlock (&root->heat_inode_map[i].lock); +spin_lock (&root->heat_range_map[i].lock); +hot_map_list_free (&root->heat_range_map[i].node_list, root); +spin_unlock (&root->heat_range_map[i].lock); + } +} + +/* * Initialize kmem cache for hot_inode_item and hot_range_item. */ void __init hot_cache_init (void )
@@ -384,6 +449,7 @@ int hot_track_init(struct super_block *sb) }hot_inode_tree_init (root); +hot_map_init (root); sb->s_hot_root = root;
@@ -397,6 +463,7 @@ void hot_track_exit(struct super_block *sb) {struct hot_info *root = sb->s_hot_root; +hot_map_exit (root);hot_inode_tree_exit (root); sb->s_hot_root =NULL ;kfree (root);
include/linux/hot_tracking.h +17 -0
@@ -20,6 +20,9 @@#include <linux/kref.h> #include <linux/fs.h> +#define HEAT_MAP_BITS 8 +#define HEAT_MAP_SIZE (1 << HEAT_MAP_BITS) +struct hot_rb_tree {struct rb_root map; };
@@ -40,12 +43,20 @@ struct hot_freq_data {u32 last_temp; }; +/* List heads in hot map array */ +struct hot_map_head { +struct list_head node_list; +u8 temp; +spinlock_t lock; +}; +/* The common info for both following structures */ struct hot_comm_item {struct rb_node rb_node;/* rbtree index */ struct hot_freq_data hot_freq_data;/* frequency data */ spinlock_t lock;/* protects object data */ struct kref refs;/* prevents kfree */ +struct list_head n_list;/* list node index */ };/* An item representing an inode and its access frequency */
@@ -71,6 +82,12 @@ struct hot_range_item {struct hot_info {struct hot_rb_tree hot_inode_tree;spinlock_t lock;/*protect inode tree */ + +/* map of inode temperature */ +struct hot_map_head heat_inode_map[HEAT_MAP_SIZE ]; +/* map of range temperature */ +struct hot_map_head heat_range_map[HEAT_MAP_SIZE ]; +unsigned int hot_map_nr; };extern void __init hot_cache_init (void );
Signature · 1 line
1.7.6.5
Re: [PATCH RESEND v1 04/16] vfs: add two map arrays
fs/hot_tracking.c static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) · line 354
Quoted 10 lines · On Thu, Dec 20, 2012 at 10:43:23PM +0800, [email protected] wrote:
fs/hot_tracking.c +8
-0+/* Free inode and range map info */ +static void hot_map_exit (struct hot_info *root) +{ +int i; +for (i =0 ; i <HEAT_MAP_SIZE ; i++) { +spin_lock (&root->heat_inode_map[i].lock); +hot_map_list_free (&root->heat_inode_map[i].node_list, root); +spin_unlock (&root->heat_inode_map[i].lock);
please insert an empty line here to improve readability
Quoted 13 lines
fs/hot_tracking.c +7
-0+spin_lock (&root->heat_range_map[i].lock); +hot_map_list_free (&root->heat_range_map[i].node_list, root); +spin_unlock (&root->heat_range_map[i].lock); + } +} + +/* * Initialize kmem cache for hot_inode_item and hot_range_item. */ void __init hot_cache_init (void )
include/linux/hot_tracking.h struct hot_range_item { · line 91
Quoted 10 lines
include/linux/hot_tracking.h +6
-0@@ -71,6 +82,12 @@ struct hot_range_item {struct hot_info {struct hot_rb_tree hot_inode_tree;spinlock_t lock;/*protect inode tree */ + +/* map of inode temperature */ +struct hot_map_head heat_inode_map[HEAT_MAP_SIZE ]; +/* map of range temperature */ +struct hot_map_head heat_range_map[HEAT_MAP_SIZE ]; +unsigned int hot_map_nr; };
Final layout of struct hot_info is
struct hot_info {
struct hot_rb_tree hot_inode_tree; /* 0 8 */
spinlock_t lock; /* 8 72 */
/* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */
struct hot_map_head heat_inode_map[256]; /* 80 24576 */
/* --- cacheline 385 boundary (24640 bytes) was 16 bytes ago --- */
struct hot_map_head heat_range_map[256]; /* 24656 24576 */
/* --- cacheline 769 boundary (49216 bytes) was 16 bytes ago --- */
unsigned int hot_map_nr; /* 49232 4 */
/* XXX 4 bytes hole, try to pack */
struct workqueue_struct * update_wq; /* 49240 8 */
struct delayed_work update_work; /* 49248 216 */
/* XXX last struct has 4 bytes of padding */
/* --- cacheline 772 boundary (49408 bytes) was 56 bytes ago --- */
struct hot_type * hot_type; /* 49464 8 */
/* --- cacheline 773 boundary (49472 bytes) --- */
struct shrinker hot_shrink; /* 49472 48 */
struct dentry * vol_dentry; /* 49520 8 */
/* size: 49528, cachelines: 774, members: 10 */
/* sum members: 49524, holes: 1, sum holes: 4 */
/* paddings: 1, sum paddings: 4 */
/* last cacheline: 56 bytes */
};that's an order-4 allocation and the heat_*_map[] themselves need order-3.
Also the structure
struct hot_map_head {
struct list_head node_list; /* 0 16 */
u8 temp; /* 16 1 */
/* XXX 7 bytes hole, try to pack */
spinlock_t lock; /* 24 72 */
/* --- cacheline 1 boundary (64 bytes) was 32 bytes ago --- */
/* size: 96, cachelines: 2, members: 3 */
/* sum members: 89, holes: 1, sum holes: 7 */
/* last cacheline: 32 bytes */
};is not packed efficiently and given the number of the array items, the wasted space adds to the sum.
So, this needs to be fixed. Options I see:
1) try to allocate the structure with GFP_NOWARN and use vmalloc as a fallback
2) allocate heat_*_map arrays dynamically
An array of 256 pointers takes 2048 bytes, so when there are 2 of them plus other struct items, overall size will go beyond a 4k page. Also, doing kmalloc on each heat_*_map item could spread them over memory, although hot_info is a long-term structure and it would make sense to keep the data located at one place. For struct hot_map_head I suggest to create a slab.
david
PATCH RESEND 5/16 vfs: add hooks to enable hot tracking
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Miscellaneous features that implement hot data tracking
and generally make the hot data functions a bit more friendly.
--- fs/direct-io.c | 6 ++++++ mm/filemap.c | 6 ++++++ mm/page-writeback.c | 12 ++++++++++++ mm/readahead.c | 7 +++++++ 4 files changed, 31 insertions(+), 0 deletions(-)
fs/direct-io.c +6 -0
@@ -37,6 +37,7 @@#include <linux/uio.h> #include <linux/atomic.h> #include <linux/prefetch.h> +#include "hot_tracking.h" /* * How many user pages to map in one call to get_user_pages(). This determines
@@ -1299,6 +1300,11 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,prefetch (bdev->bd_queue);prefetch ((char *)bdev->bd_queue +SMP_CACHE_BYTES ); +/* Hot data tracking */ +hot_update_freqs (inode, offset, +iov_length (iov, nr_segs), + rw &WRITE ); +return do_blockdev_direct_IO (rw, iocb, inode, bdev, iov, offset, nr_segs, get_block, end_io, submit_io, flags);
mm/filemap.c +6 -0
@@ -33,6 +33,7 @@#include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */ #include <linux/memcontrol.h> #include <linux/cleancache.h> +#include <linux/hot_tracking.h> #include "internal.h" /*
@@ -1224,6 +1225,11 @@ readpage:* PG_error will be set again if readpage fails. */ ClearPageError (page); + +/* Hot data tracking */ +hot_update_freqs (inode, (loff_t )page->index <<PAGE_CACHE_SHIFT , +PAGE_CACHE_SIZE ,0 ); +/* Start the actual read. The read will unlock the page. */ error = mapping->a_ops->readpage (filp, page);
mm/page-writeback.c +12 -0
@@ -35,6 +35,7 @@#include <linux/buffer_head.h> /* __set_page_dirty_buffers */ #include <linux/pagevec.h> #include <linux/timer.h> +#include <linux/hot_tracking.h> #include <trace/events/writeback.h> /*
@@ -1902,13 +1903,24 @@ EXPORT_SYMBOL(generic_writepages);int do_writepages (struct address_space *mapping,struct writeback_control *wbc) {int ret; +loff_t start =0 ; +size_t count =0 ;if (wbc->nr_to_write <=0 )return 0 ; + + start = mapping->writeback_index <<PAGE_CACHE_SHIFT ; + count = wbc->nr_to_write; +if (mapping->a_ops->writepages) ret = mapping->a_ops->writepages (mapping, wbc);else ret =generic_writepages (mapping, wbc); + +/* Hot data tracking */ +hot_update_freqs (mapping->host, start, + (count - wbc->nr_to_write) *PAGE_CACHE_SIZE ,1 ); +return ret; }
mm/readahead.c +7 -0
@@ -19,6 +19,7 @@#include <linux/pagemap.h> #include <linux/syscalls.h> #include <linux/file.h> +#include <linux/hot_tracking.h> /* * Initialise a struct file's readahead state. Assumes that the caller has
@@ -138,6 +139,12 @@ static int read_pages(struct address_space *mapping, struct file *filp, out:blk_finish_plug (&plug); +/* Hot data tracking */ +hot_update_freqs (mapping->host, + (loff_t)(list_entry(pages->prev, struct page, lru)->index) + <<PAGE_CACHE_SHIFT , + (size_t )nr_pages *PAGE_CACHE_SIZE ,0 ); +return ret; }
Signature · 1 line
1.7.6.5
Re: [PATCH RESEND v1 05/16] vfs: add hooks to enable hot tracking
Quoted 11 lines · On Thu, Dec 20, 2012 at 10:43:24PM +0800, [email protected] wrote:
fs/direct-io.c +1
-0@@ -37,6 +37,7 @@#include <linux/uio.h> #include <linux/atomic.h> #include <linux/prefetch.h> +#include "hot_tracking.h" /* * How many user pages to map in one call to get_user_pages(). This determines
fs/direct-io.c __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, · line 1306
Quoted 7 lines
fs/direct-io.c +4
-0@@ -1299,6 +1300,11 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,prefetch (bdev->bd_queue);prefetch ((char *)bdev->bd_queue +SMP_CACHE_BYTES ); +/* Hot data tracking */ +hot_update_freqs (inode, offset, +iov_length (iov, nr_segs), + rw &WRITE );
hot_update_freqs takes an 'int rw' directly, so you should pass plain 'rw' here and do the 'rw & WRITE' check in hot_freq_data_update itself.
Quoted 25 lines
fs/direct-io.c +1
-0+return do_blockdev_direct_IO (rw, iocb, inode, bdev, iov, offset, nr_segs, get_block, end_io, submit_io, flags);mm/page-writeback.c +5
-0@@ -35,6 +35,7 @@#include <linux/buffer_head.h> /* __set_page_dirty_buffers */ #include <linux/pagevec.h> #include <linux/timer.h> +#include <linux/hot_tracking.h> #include <trace/events/writeback.h> /* @@ -1902,13 +1903,24 @@ EXPORT_SYMBOL(generic_writepages);int do_writepages (struct address_space *mapping,struct writeback_control *wbc) {int ret; +loff_t start =0 ; +size_t count =0 ;if (wbc->nr_to_write <=0 )return 0 ; + + start = mapping->writeback_index <<PAGE_CACHE_SHIFT ;
mm/page-writeback.c EXPORT_SYMBOL(generic_writepages); · line 1922
Quoted 10 lines
mm/page-writeback.c +6
-0+ count = wbc->nr_to_write; +if (mapping->a_ops->writepages) ret = mapping->a_ops->writepages (mapping, wbc);else ret =generic_writepages (mapping, wbc); + +/* Hot data tracking */ +hot_update_freqs (mapping->host, start, + (count - wbc->nr_to_write) *PAGE_CACHE_SIZE ,1 );
I think the frequencies should not be updated in case of error returned from writepages.
Quoted 7 lines
mm/page-writeback.c +1
-0+return ret; }
mm/readahead.c static int read_pages(struct address_space *mapping, struct file *filp, · line 146
Quoted 8 lines
mm/readahead.c +5
-0@@ -138,6 +139,12 @@ static int read_pages(struct address_space *mapping, struct file *filp, out:blk_finish_plug (&plug); +/* Hot data tracking */ +hot_update_freqs (mapping->host, + (loff_t)(list_entry(pages->prev, struct page, lru)->index) + <<PAGE_CACHE_SHIFT , + (size_t )nr_pages *PAGE_CACHE_SIZE ,0 );
same comment here
mm/readahead.c static int read_pages(struct address_space *mapping, struct file *filp, · line 149
Quoted 3 lines
mm/readahead.c +1
-0+return ret; }
david
Re: [PATCH RESEND v1 05/16] vfs: add hooks to enable hot tracking
Quoted 15 lines · David Sterba
Quoted 14 lines · On Thu, Dec 20, 2012 at 10:43:24PM +0800, [email protected] wrote:
fs/direct-io.c +1
-0@@ -37,6 +37,7 @@#include <linux/uio.h> #include <linux/atomic.h> #include <linux/prefetch.h> +#include "hot_tracking.h" /* * How many user pages to map in one call to get_user_pages(). This determines @@ -1299,6 +1300,11 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,prefetch (bdev->bd_queue);prefetch ((char *)bdev->bd_queue +SMP_CACHE_BYTES );
Quoted 7 lines
fs/direct-io.c __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, · line 1306
Quoted 4 lines
fs/direct-io.c +4
-0+/* Hot data tracking */ +hot_update_freqs (inode, offset, +iov_length (iov, nr_segs), + rw &WRITE );
hot_update_freqstakes an 'int rw' directly, so you should pass plain 'rw' here and do the 'rw & WRITE' check inhot_freq_data_updateitself.
OK, done.
Quoted 31 lines
Quoted 31 lines
fs/direct-io.c +1
-0+return do_blockdev_direct_IO (rw, iocb, inode, bdev, iov, offset, nr_segs, get_block, end_io, submit_io, flags);mm/page-writeback.c +7
-0@@ -35,6 +35,7 @@#include <linux/buffer_head.h> /* __set_page_dirty_buffers */ #include <linux/pagevec.h> #include <linux/timer.h> +#include <linux/hot_tracking.h> #include <trace/events/writeback.h> /* @@ -1902,13 +1903,24 @@ EXPORT_SYMBOL(generic_writepages);int do_writepages (struct address_space *mapping,struct writeback_control *wbc) {int ret; +loff_t start =0 ; +size_t count =0 ;if (wbc->nr_to_write <=0 )return 0 ; + + start = mapping->writeback_index <<PAGE_CACHE_SHIFT ; + count = wbc->nr_to_write; +if (mapping->a_ops->writepages) ret = mapping->a_ops->writepages (mapping, wbc);else
Quoted 8 lines
mm/page-writeback.c EXPORT_SYMBOL(generic_writepages); · line 1922
Quoted 5 lines
mm/page-writeback.c +4
-0ret =generic_writepages (mapping, wbc); + +/* Hot data tracking */ +hot_update_freqs (mapping->host, start, + (count - wbc->nr_to_write) *PAGE_CACHE_SIZE ,1 );I think the frequencies should not be updated in case of error returned from writepages.
OK, Done.
Quoted 11 lines
Quoted 11 lines
mm/page-writeback.c +1
-0+return ret; }mm/readahead.c +0
-0@@ -138,6 +139,12 @@ static int read_pages(struct address_space *mapping, struct file *filp, out:blk_finish_plug (&plug);
Quoted 7 lines
mm/readahead.c static int read_pages(struct address_space *mapping, struct file *filp, · line 146
Quoted 5 lines
mm/readahead.c +5
-0+/* Hot data tracking */ +hot_update_freqs (mapping->host, + (loff_t)(list_entry(pages->prev, struct page, lru)->index) + <<PAGE_CACHE_SHIFT , + (size_t )nr_pages *PAGE_CACHE_SIZE ,0 );same comment here
Ditto. thanks.
Quoted 7 lines
mm/readahead.c static int read_pages(struct address_space *mapping, struct file *filp, · line 149
Quoted 4 lines
mm/readahead.c +1
-0+return ret; }david
Signature · 3 lines
Regards, Zhi Yong Wu
PATCH RESEND 6/16 vfs: add temp calculation function
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
--- fs/hot_tracking.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/hot_tracking.h | 21 +++++++++++++++ 2 files changed, 95 insertions(+), 0 deletions(-)
fs/hot_tracking.c +74 -0
@@ -25,6 +25,14 @@static struct kmem_cache *hot_inode_item_cachep__read_mostly ;static struct kmem_cache *hot_range_item_cachep__read_mostly ; +static u64 hot_raw_shift (u64 counter,u32 bits,bool dir) +{ +if (dir) +return counter << bits; +else +return counter >> bits; +} +/* * Initialize the inode tree. Should be called for each new inode * access or other user of the hot_inode interface.
@@ -315,6 +323,72 @@ static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) }/* +* hot_temp_calc() is responsible for distilling the six heat +* criteria down into a single temperature value for the data, +* which is an integer between 0 and HEAT_MAX_VALUE. +*/ +static u32 hot_temp_calc (struct hot_freq_data *freq_data) +{ +u32 result =0 ; + +struct timespec ckt =current_kernel_time (); +u64 cur_time =timespec_to_ns (&ckt); + +u32 nrr_heat = (u32 )hot_raw_shift ((u64 )freq_data->nr_reads, +NRR_MULTIPLIER_POWER , true); +u32 nrw_heat = (u32 )hot_raw_shift ((u64 )freq_data->nr_writes, +NRW_MULTIPLIER_POWER , true); + +u64 ltr_heat = +hot_raw_shift ((cur_time -timespec_to_ns (&freq_data->last_read_time)), +LTR_DIVIDER_POWER , false); +u64 ltw_heat = +hot_raw_shift ((cur_time -timespec_to_ns (&freq_data->last_write_time)), +LTW_DIVIDER_POWER , false); + +u64 avr_heat = +hot_raw_shift ((((u64) -1 ) - freq_data->avg_delta_reads), +AVR_DIVIDER_POWER , false); +u64 avw_heat = +hot_raw_shift ((((u64) -1 ) - freq_data->avg_delta_writes), +AVW_DIVIDER_POWER , false); + +/* ltr_heat is now guaranteed to be u32 safe */ +if (ltr_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + ltr_heat =0 ; +else + ltr_heat =hot_raw_shift ((u64 )1 ,32 , true) - ltr_heat; + +/* ltw_heat is now guaranteed to be u32 safe */ +if (ltw_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + ltw_heat =0 ; +else + ltw_heat =hot_raw_shift ((u64 )1 ,32 , true) - ltw_heat; + +/* avr_heat is now guaranteed to be u32 safe */ +if (avr_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + avr_heat = (u32) -1 ; + +/* avw_heat is now guaranteed to be u32 safe */ +if (avw_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + avw_heat = (u32) -1 ; + + nrr_heat = (u32 )hot_raw_shift ((u64 )nrr_heat, + (3 -NRR_COEFF_POWER ), false); + nrw_heat = (u32 )hot_raw_shift ((u64 )nrw_heat, + (3 -NRW_COEFF_POWER ), false); + ltr_heat =hot_raw_shift (ltr_heat, (3 -LTR_COEFF_POWER ), false); + ltw_heat =hot_raw_shift (ltw_heat, (3 -LTW_COEFF_POWER ), false); + avr_heat =hot_raw_shift (avr_heat, (3 -AVR_COEFF_POWER ), false); + avw_heat =hot_raw_shift (avw_heat, (3 -AVW_COEFF_POWER ), false); + + result = nrr_heat + nrw_heat + (u32 ) ltr_heat + + (u32 ) ltw_heat + (u32 ) avr_heat + (u32 ) avw_heat; + +return result; +} + +/* * Initialize inode and range map info. */ static void hot_map_init (struct hot_info *root)
fs/hot_tracking.h +21 -0
@@ -24,4 +24,25 @@#define RANGE_SIZE (1 << RANGE_BITS)#define FREQ_POWER 4 +/* NRR/NRW heat unit = 2^X accesses */ +#define NRR_MULTIPLIER_POWER 20/* NRR - number of reads since mount */ +#define NRR_COEFF_POWER 0 +#define NRW_MULTIPLIER_POWER 20/* NRW - number of writes since mount */ +#define NRW_COEFF_POWER 0 + +/* LTR/LTW heat unit = 2^X ns of age */ +#define LTR_DIVIDER_POWER 30/* LTR - time elapsed since last read(ns) */ +#define LTR_COEFF_POWER 1 +#define LTW_DIVIDER_POWER 30/* LTW - time elapsed since last write(ns) */ +#define LTW_COEFF_POWER 1 + +/* +* AVR/AVW cold unit = 2^X ns of average delta +* AVR/AVW heat unit = HEAT_MAX_VALUE - cold unit +*/ +#define AVR_DIVIDER_POWER 40/* AVR - average delta between recent reads(ns) */ +#define AVR_COEFF_POWER 0 +#define AVW_DIVIDER_POWER 40/* AVW - average delta between recent writes(ns) */ +#define AVW_COEFF_POWER 0 +#endif /* __HOT_TRACKING__ */
Signature · 1 line
1.7.6.5
Re: [PATCH RESEND v1 06/16] vfs: add temp calculation function
fs/hot_tracking.c line 34
Quoted 13 lines · On Thu, Dec 20, 2012 at 10:43:25PM +0800, [email protected] wrote:
fs/hot_tracking.c +7
-0@@ -25,6 +25,14 @@static struct kmem_cache *hot_inode_item_cachep__read_mostly ;static struct kmem_cache *hot_range_item_cachep__read_mostly ; +static u64 hot_raw_shift (u64 counter,u32 bits,bool dir) +{ +if (dir) +return counter << bits; +else +return counter >> bits; +}
I don't understand the purpose of this function, it obscures a simple bitwise shift.
fs/hot_tracking.c static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) · line 328
Quoted 11 lines
fs/hot_tracking.c +4
-0+/* * Initialize the inode tree. Should be called for each new inode * access or other user of the hot_inode interface. @@ -315,6 +323,72 @@ static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) }/* +* hot_temp_calc() is responsible for distilling the six heat +* criteria down into a single temperature value for the data, +* which is an integer between 0 and HEAT_MAX_VALUE.
I didn't find HEAT_MAX_VALUE defined anywhere.
fs/hot_tracking.c static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) · line 340
Quoted 12 lines
fs/hot_tracking.c +12
-0+*/ +static u32 hot_temp_calc (struct hot_freq_data *freq_data) +{ +u32 result =0 ; + +struct timespec ckt =current_kernel_time (); +u64 cur_time =timespec_to_ns (&ckt); + +u32 nrr_heat = (u32 )hot_raw_shift ((u64 )freq_data->nr_reads, +NRR_MULTIPLIER_POWER , true); +u32 nrw_heat = (u32 )hot_raw_shift ((u64 )freq_data->nr_writes, +NRW_MULTIPLIER_POWER , true);
So many typecasts, some of them unnecessary and in connection with hot_raw_shift this is hard to read and understand.
u32 nrr_heat = (u32)((u64)freq_data->nr_reads << NRR_MULTIPLIER_POWER);
is not much better without a comment why this is doing the right thing.
Quoted 36 lines
fs/hot_tracking.c +36
-0+ +u64 ltr_heat = +hot_raw_shift ((cur_time -timespec_to_ns (&freq_data->last_read_time)), +LTR_DIVIDER_POWER , false); +u64 ltw_heat = +hot_raw_shift ((cur_time -timespec_to_ns (&freq_data->last_write_time)), +LTW_DIVIDER_POWER , false); + +u64 avr_heat = +hot_raw_shift ((((u64) -1 ) - freq_data->avg_delta_reads), +AVR_DIVIDER_POWER , false); +u64 avw_heat = +hot_raw_shift ((((u64) -1 ) - freq_data->avg_delta_writes), +AVW_DIVIDER_POWER , false); + +/* ltr_heat is now guaranteed to be u32 safe */ +if (ltr_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + ltr_heat =0 ; +else + ltr_heat =hot_raw_shift ((u64 )1 ,32 , true) - ltr_heat; + +/* ltw_heat is now guaranteed to be u32 safe */ +if (ltw_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + ltw_heat =0 ; +else + ltw_heat =hot_raw_shift ((u64 )1 ,32 , true) - ltw_heat; + +/* avr_heat is now guaranteed to be u32 safe */ +if (avr_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + avr_heat = (u32) -1 ; + +/* avw_heat is now guaranteed to be u32 safe */ +if (avw_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + avw_heat = (u32) -1 ; + + nrr_heat = (u32)hot_raw_shift((u64)nrr_heat,
fs/hot_tracking.c static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) · line 386
Quoted 10 lines
fs/hot_tracking.c +10
-0+ (3 - NRR_COEFF_POWER), false); + nrw_heat = (u32 )hot_raw_shift ((u64 )nrw_heat, + (3 -NRW_COEFF_POWER ), false); + ltr_heat =hot_raw_shift (ltr_heat, (3 -LTR_COEFF_POWER ), false); + ltw_heat =hot_raw_shift (ltw_heat, (3 -LTW_COEFF_POWER ), false); + avr_heat =hot_raw_shift (avr_heat, (3 -AVR_COEFF_POWER ), false); + avw_heat =hot_raw_shift (avw_heat, (3 -AVW_COEFF_POWER ), false); + + result = nrr_heat + nrw_heat + (u32 ) ltr_heat + + (u32 ) ltw_heat + (u32 ) avr_heat + (u32 ) avw_heat;
Reading through the function up to here I've got lost in the shifts that I don't see the meaning of the resulting value and how can I interpet it if I watch it change over time. What are the expected weights of the number and time factors? There are more details in the documentation, but the big picture is blurred by talking implementation details.
Let's put the impl. details here and write a better user documentation with a few examples to the docs. Is it possible to describe some common access patterns and how they affect the temperature?
You've been benchmarking this patchset, I'm sure you can write up a few examples based on that.
fs/hot_tracking.c static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) · line 389
Quoted 3 lines
fs/hot_tracking.c +3
-0+ +return result; +}
david
Re: [PATCH RESEND v1 06/16] vfs: add temp calculation function
Quoted 7 lines · David Sterba
Quoted 6 lines · On Thu, Dec 20, 2012 at 10:43:25PM +0800, [email protected] wrote:
fs/hot_tracking.c +0
-0@@ -25,6 +25,14 @@static struct kmem_cache *hot_inode_item_cachep__read_mostly ;static struct kmem_cache *hot_range_item_cachep__read_mostly ;
Quoted 10 lines
fs/hot_tracking.c line 34
Quoted 7 lines
fs/hot_tracking.c +7
-0+static u64 hot_raw_shift (u64 counter,u32 bits,bool dir) +{ +if (dir) +return counter << bits; +else +return counter >> bits; +}I don't understand the purpose of this function, it obscures a simple bitwise shift.
The following words seem to mean that you prefer removing this shifting function?
Quoted 8 lines
Quoted 8 lines
fs/hot_tracking.c +1
-0+/* * Initialize the inode tree. Should be called for each new inode * access or other user of the hot_inode interface. @@ -315,6 +323,72 @@ static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) }
Quoted 6 lines
fs/hot_tracking.c static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) · line 328
Quoted 4 lines
fs/hot_tracking.c +3
-0/* +* hot_temp_calc() is responsible for distilling the six heat +* criteria down into a single temperature value for the data, +* which is an integer between 0 and HEAT_MAX_VALUE. I didn't find
HEAT_MAX_VALUEdefined anywhere.
This micro is only used in some comments, OK, i will replace it with 255.
Quoted 17 lines
fs/hot_tracking.c static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) · line 340
Quoted 13 lines
fs/hot_tracking.c +12
-0+*/ +static u32 hot_temp_calc (struct hot_freq_data *freq_data) +{ +u32 result =0 ; + +struct timespec ckt =current_kernel_time (); +u64 cur_time =timespec_to_ns (&ckt); + +u32 nrr_heat = (u32 )hot_raw_shift ((u64 )freq_data->nr_reads, +NRR_MULTIPLIER_POWER , true); +u32 nrw_heat = (u32 )hot_raw_shift ((u64 )freq_data->nr_writes, +NRW_MULTIPLIER_POWER , true);So many typecasts, some of them unnecessary and in connection with
hot_raw_shiftthis is hard to read and understand.
Quoted 1 line
u32 nrr_heat = (u32)((u64)freq_data->nr_reads << NRR_MULTIPLIER_POWER);
Do you prefer this format instead of ?
Quoted 68 lines
is not much better without a comment why this is doing the right thing.
Quoted 36 lines
fs/hot_tracking.c +36
-0+ +u64 ltr_heat = +hot_raw_shift ((cur_time -timespec_to_ns (&freq_data->last_read_time)), +LTR_DIVIDER_POWER , false); +u64 ltw_heat = +hot_raw_shift ((cur_time -timespec_to_ns (&freq_data->last_write_time)), +LTW_DIVIDER_POWER , false); + +u64 avr_heat = +hot_raw_shift ((((u64) -1 ) - freq_data->avg_delta_reads), +AVR_DIVIDER_POWER , false); +u64 avw_heat = +hot_raw_shift ((((u64) -1 ) - freq_data->avg_delta_writes), +AVW_DIVIDER_POWER , false); + +/* ltr_heat is now guaranteed to be u32 safe */ +if (ltr_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + ltr_heat =0 ; +else + ltr_heat =hot_raw_shift ((u64 )1 ,32 , true) - ltr_heat; + +/* ltw_heat is now guaranteed to be u32 safe */ +if (ltw_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + ltw_heat =0 ; +else + ltw_heat =hot_raw_shift ((u64 )1 ,32 , true) - ltw_heat; + +/* avr_heat is now guaranteed to be u32 safe */ +if (avr_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + avr_heat = (u32) -1 ; + +/* avw_heat is now guaranteed to be u32 safe */ +if (avw_heat >=hot_raw_shift ((u64 )1 ,32 , true)) + avw_heat = (u32) -1 ; + + nrr_heat = (u32)hot_raw_shift((u64)nrr_heat,fs/hot_tracking.c static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) · line 386
Quoted 10 lines
fs/hot_tracking.c +10
-0+ (3 - NRR_COEFF_POWER), false); + nrw_heat = (u32 )hot_raw_shift ((u64 )nrw_heat, + (3 -NRW_COEFF_POWER ), false); + ltr_heat =hot_raw_shift (ltr_heat, (3 -LTR_COEFF_POWER ), false); + ltw_heat =hot_raw_shift (ltw_heat, (3 -LTW_COEFF_POWER ), false); + avr_heat =hot_raw_shift (avr_heat, (3 -AVR_COEFF_POWER ), false); + avw_heat =hot_raw_shift (avw_heat, (3 -AVW_COEFF_POWER ), false); + + result = nrr_heat + nrw_heat + (u32 ) ltr_heat + + (u32 ) ltw_heat + (u32 ) avr_heat + (u32 ) avw_heat;Reading through the function up to here I've got lost in the shifts that I don't see the meaning of the resulting value and how can I interpet it if I watch it change over time. What are the expected weights of the number and time factors? There are more details in the documentation, but the big picture is blurred by talking implementation details.
Let's put the impl. details here and write a better user documentation with a few examples to the docs. Is it possible to describe some common access patterns and how they affect the temperature?
You've been benchmarking this patchset, I'm sure you can write up a few examples based on that.
fs/hot_tracking.c static void hot_freq_data_update(struct hot_freq_data *freq_data, bool write) · line 389
Quoted 3 lines
fs/hot_tracking.c +3
-0+ +return result; +}david
Signature · 3 lines
Regards, Zhi Yong Wu
PATCH RESEND 7/16 vfs: add map info update function
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
--- fs/hot_tracking.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 67 insertions(+), 0 deletions(-)
fs/hot_tracking.c +67 -0
@@ -389,6 +389,73 @@ static u32 hot_temp_calc(struct hot_freq_data *freq_data) }/* +* Calculate a new temperature and, if necessary, +* move the list_head corresponding to this inode or range +* to the proper list with the new temperature +*/ +static void hot_map_update (struct hot_freq_data *freq_data, +struct hot_info *root) +{ +struct hot_map_head *buckets, *cur_bucket; +struct hot_comm_item *comm_item; +struct hot_inode_item *he; +struct hot_range_item *hr; +u32 temp =hot_temp_calc (freq_data); +u8 a_temp = (u8 )hot_raw_shift ((u64 )temp, (32 -HEAT_MAP_BITS ), false); +u8 b_temp = (u8 )hot_raw_shift ((u64 )freq_data->last_temp, + (32 -HEAT_MAP_BITS ), false); + + comm_item =container_of (freq_data, + struct hot_comm_item, hot_freq_data); + +if (freq_data->flags &FREQ_DATA_TYPE_INODE ) { + he =container_of (comm_item, + struct hot_inode_item, hot_inode); + buckets = root->heat_inode_map; + +if (he ==NULL ) +return ; + +spin_lock (&he->hot_inode.lock); +if (list_empty (&he->hot_inode.n_list) || (a_temp != b_temp)) { +if (!list_empty (&he->hot_inode.n_list)) { +list_del_init (&he->hot_inode.n_list); + root->hot_map_nr--; + } + + cur_bucket = buckets + a_temp; +list_add_tail (&he->hot_inode.n_list, + &cur_bucket->node_list); + root->hot_map_nr++; + freq_data->last_temp = temp; + } +spin_unlock (&he->hot_inode.lock); + }else if (freq_data->flags &FREQ_DATA_TYPE_RANGE ) { + hr =container_of (comm_item, + struct hot_range_item, hot_range); + buckets = root->heat_range_map; + +if (hr ==NULL ) +return ; + +spin_lock (&hr->hot_range.lock); +if (list_empty (&hr->hot_range.n_list) || (a_temp != b_temp)) { +if (!list_empty (&hr->hot_range.n_list)) { +list_del_init (&hr->hot_range.n_list); + root->hot_map_nr--; + } + + cur_bucket = buckets + a_temp; +list_add_tail (&hr->hot_range.n_list, + &cur_bucket->node_list); + root->hot_map_nr++; + freq_data->last_temp = temp; + } +spin_unlock (&hr->hot_range.lock); + } +} + +/* * Initialize inode and range map info. */ static void hot_map_init (struct hot_info *root)
Signature · 1 line
1.7.6.5
PATCH RESEND 8/16 vfs: add aging function
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
--- fs/hot_tracking.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/hot_tracking.h | 6 ++++++ 2 files changed, 55 insertions(+), 0 deletions(-)
fs/hot_tracking.c +49 -0
@@ -388,6 +388,24 @@ static u32 hot_temp_calc(struct hot_freq_data *freq_data)return result; } +static bool hot_is_obsolete (struct hot_freq_data *freq_data) +{ +int ret =0 ; +struct timespec ckt =current_kernel_time (); + +u64 cur_time =timespec_to_ns (&ckt); +u64 last_read_ns = + (cur_time -timespec_to_ns (&freq_data->last_read_time)); +u64 last_write_ns = + (cur_time -timespec_to_ns (&freq_data->last_write_time)); +u64 kick_ns =TIME_TO_KICK *NSEC_PER_SEC ; + +if ((last_read_ns > kick_ns) && (last_write_ns > kick_ns)) + ret =1 ; + +return ret; +} +/* * Calculate a new temperature and, if necessary, * move the list_head corresponding to this inode or range
@@ -455,6 +473,37 @@ static void hot_map_update(struct hot_freq_data *freq_data, } } +/* Update temperatures for each range item for aging purposes */ +static void hot_range_update (struct hot_inode_item *he, +struct hot_info *root) +{ +struct rb_node *node; +struct hot_comm_item *ci; +struct hot_range_item *hr; +bool obsolete; + +spin_lock (&he->lock); + node =rb_first (&he->hot_range_tree.map); +while (node) { + ci = rb_entry(node, struct hot_comm_item, rb_node); + hr = container_of(ci, struct hot_range_item, hot_range); +kref_get (&hr->hot_range.refs); +hot_map_update (&hr->hot_range.hot_freq_data, root); + +spin_lock (&hr->hot_range.lock); + obsolete =hot_is_obsolete ( + &hr->hot_range.hot_freq_data); +spin_unlock (&hr->hot_range.lock); + + node =rb_next (node); + +hot_range_item_put (hr); +if (obsolete) +hot_range_item_put (hr); + } +spin_unlock (&he->lock); +} +/* * Initialize inode and range map info. */
fs/hot_tracking.h +6 -0
@@ -24,6 +24,12 @@#define RANGE_SIZE (1 << RANGE_BITS)#define FREQ_POWER 4 +/* +* time to quit keeping track of +* tracking data (seconds) +*/ +#define TIME_TO_KICK 300 +/* NRR/NRW heat unit = 2^X accesses */ #define NRR_MULTIPLIER_POWER 20/* NRR - number of reads since mount */ #define NRR_COEFF_POWER 0
Signature · 1 line
1.7.6.5
PATCH RESEND 9/16 vfs: add one work queue
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Add a per-superblock workqueue and a delayed_work
to run periodic work to update map info on each superblock.
--- fs/hot_tracking.c | 85 ++++++++++++++++++++++++++++++++++++++++++ fs/hot_tracking.h | 3 + include/linux/hot_tracking.h | 3 + 3 files changed, 91 insertions(+), 0 deletions(-)
fs/hot_tracking.c +85 -0
@@ -15,9 +15,12 @@#include <linux/module.h> #include <linux/spinlock.h> #include <linux/hardirq.h> +#include <linux/kthread.h> +#include <linux/freezer.h> #include <linux/fs.h> #include <linux/blkdev.h> #include <linux/types.h> +#include <linux/list_sort.h> #include <linux/limits.h> #include "hot_tracking.h"
@@ -548,6 +551,67 @@ static void hot_map_exit(struct hot_info *root) } } +/* Temperature compare function*/ +static int hot_temp_cmp (void *priv,struct list_head *a, +struct list_head *b) +{ +struct hot_comm_item *ap = + container_of(a, struct hot_comm_item, n_list); +struct hot_comm_item *bp = + container_of(b, struct hot_comm_item, n_list); + +int diff = ap->hot_freq_data.last_temp + - bp->hot_freq_data.last_temp; +if (diff >0 ) +return -1 ; +if (diff <0 ) +return 1 ; +return 0 ; +} + +/* +* Every sync period we update temperatures for +* each hot inode item and hot range item for aging +* purposes. +*/ +static void hot_update_worker (struct work_struct *work) +{ +struct hot_info *root =container_of (to_delayed_work (work), + struct hot_info, update_work); +struct rb_node *node; +struct hot_comm_item *ci; +struct hot_inode_item *he; +int i; + + node =rb_first (&root->hot_inode_tree.map); +while (node) { + ci = rb_entry(node, struct hot_comm_item, rb_node); + he = container_of(ci, struct hot_inode_item, hot_inode); +kref_get (&he->hot_inode.refs); +hot_map_update ( + &he->hot_inode.hot_freq_data, root); +hot_range_update (he, root); + node =rb_next (node); +hot_inode_item_put (he); + } + +/* Sort temperature map info */ +for (i =0 ; i <HEAT_MAP_SIZE ; i++) { +spin_lock (&root->heat_inode_map[i].lock); +list_sort (NULL , &root->heat_inode_map[i].node_list, + hot_temp_cmp); +spin_unlock (&root->heat_inode_map[i].lock); +spin_lock (&root->heat_range_map[i].lock); +list_sort (NULL , &root->heat_range_map[i].node_list, + hot_temp_cmp); +spin_unlock (&root->heat_range_map[i].lock); + } + +/* Instert next delayed work */ +queue_delayed_work (root->update_wq, &root->update_work, +msecs_to_jiffies (HEAT_UPDATE_DELAY *MSEC_PER_SEC )); +} +/* * Initialize kmem cache for hot_inode_item and hot_range_item. */
@@ -641,11 +705,30 @@ int hot_track_init(struct super_block *sb)hot_inode_tree_init (root);hot_map_init (root); + root->update_wq =alloc_workqueue ( +"hot_update_wq" ,WQ_NON_REENTRANT ,0 ); +if (!root->update_wq) { +printk (KERN_ERR "%s: Failed to create " +"hot update workqueue\n" , __func__); + goto failed_wq; + } + +/* Initialize hot tracking wq and arm one delayed work */ +INIT_DELAYED_WORK (&root->update_work, hot_update_worker); +queue_delayed_work (root->update_wq, &root->update_work, +msecs_to_jiffies (HEAT_UPDATE_DELAY *MSEC_PER_SEC )); + sb->s_hot_root = root;printk (KERN_INFO "VFS: Turning on hot data tracking\n" );return 0 ; + +failed_wq: +hot_map_exit (root); +hot_inode_tree_exit (root); +kfree (root); +return ret; }EXPORT_SYMBOL_GPL (hot_track_init);
@@ -653,6 +736,8 @@ void hot_track_exit(struct super_block *sb) {struct hot_info *root = sb->s_hot_root; +cancel_delayed_work_sync (&root->update_work); +destroy_workqueue (root->update_wq);hot_map_exit (root);hot_inode_tree_exit (root); sb->s_hot_root =NULL ;
fs/hot_tracking.h +3 -0
@@ -30,6 +30,9 @@*/ #define TIME_TO_KICK 300 +/* set how often to update temperatures (seconds) */ +#define HEAT_UPDATE_DELAY 300 +/* NRR/NRW heat unit = 2^X accesses */ #define NRR_MULTIPLIER_POWER 20/* NRR - number of reads since mount */ #define NRR_COEFF_POWER 0
include/linux/hot_tracking.h +3 -0
@@ -88,6 +88,9 @@ struct hot_info {/* map of range temperature */ struct hot_map_head heat_range_map[HEAT_MAP_SIZE ];unsigned int hot_map_nr; + +struct workqueue_struct *update_wq; +struct delayed_work update_work; };extern void __init hot_cache_init (void );
Signature · 1 line
1.7.6.5
PATCH RESEND 10/16 vfs: add FS hot type support
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Introduce one way to enable that specific FS
can inject its own hot tracking type.
--- fs/hot_tracking.c | 43 +++++++++++++++++++++++++++++++---------- fs/hot_tracking.h | 1 - include/linux/fs.h | 1 + include/linux/hot_tracking.h | 19 ++++++++++++++++++ 4 files changed, 52 insertions(+), 12 deletions(-)
fs/hot_tracking.c +32 -11
@@ -64,8 +64,11 @@ void hot_range_tree_init(struct hot_inode_item *he)static void hot_range_item_init (struct hot_range_item *hr,loff_t start,struct hot_inode_item *he) { +struct hot_info *root =container_of (he->hot_inode_tree, + struct hot_info, hot_inode_tree); + hr->start = start; - hr->len =RANGE_SIZE ; + hr->len =hot_raw_shift (1 , root->hot_type->range_bits, true); hr->hot_inode = he;kref_init (&hr->hot_range.refs);spin_lock_init (&hr->hot_range.lock);
@@ -305,19 +308,21 @@ static void hot_rw_freq_calc(struct timespec old_atime, *avg = *avg >>FREQ_POWER ; } -static void hot_freq_data_update (struct hot_freq_data *freq_data,bool write) +static void hot_freq_data_update (struct hot_info *root, +struct hot_freq_data *freq_data,bool write) {struct timespec cur_time =current_kernel_time ();if (write) { freq_data->nr_writes +=1 ; -hot_rw_freq_calc (freq_data->last_write_time, + root->hot_type->ops.hot_rw_freq_calc_fn ( + freq_data->last_write_time, cur_time, &freq_data->avg_delta_writes); freq_data->last_write_time = cur_time; }else { freq_data->nr_reads +=1 ; -hot_rw_freq_calc (freq_data->last_read_time, + root->hot_type->ops.hot_rw_freq_calc_fn ( freq_data->last_read_time, cur_time, &freq_data->avg_delta_reads);
@@ -421,7 +426,7 @@ static void hot_map_update(struct hot_freq_data *freq_data,struct hot_comm_item *comm_item;struct hot_inode_item *he;struct hot_range_item *hr; -u32 temp =hot_temp_calc (freq_data); +u32 temp = root->hot_type->ops.hot_temp_calc_fn (freq_data);u8 a_temp = (u8 )hot_raw_shift ((u64 )temp, (32 -HEAT_MAP_BITS ), false);u8 b_temp = (u8 )hot_raw_shift ((u64 )freq_data->last_temp, (32 -HEAT_MAP_BITS ), false);
@@ -494,7 +499,7 @@ static void hot_range_update(struct hot_inode_item *he,hot_map_update (&hr->hot_range.hot_freq_data, root);spin_lock (&hr->hot_range.lock); - obsolete =hot_is_obsolete ( + obsolete = root->hot_type->ops.hot_is_obsolete_fn ( &hr->hot_range.hot_freq_data);spin_unlock (&hr->hot_range.lock);
@@ -647,6 +652,7 @@ void hot_update_freqs(struct inode *inode, loff_t start,struct hot_info *root = inode->i_sb->s_hot_root;struct hot_inode_item *he;struct hot_range_item *hr; +u64 range_size;loff_t cur, end;if (!root || (len ==0 ))
@@ -659,15 +665,19 @@ void hot_update_freqs(struct inode *inode, loff_t start, }spin_lock (&he->hot_inode.lock); -hot_freq_data_update (&he->hot_inode.hot_freq_data, rw); +hot_freq_data_update (root, &he->hot_inode.hot_freq_data, rw);spin_unlock (&he->hot_inode.lock);/* -* Align ranges on RANGE_SIZE boundary +* Align ranges on range size boundary * to prevent proliferation of range structs */ - end = (start + len +RANGE_SIZE -1 ) >>RANGE_BITS ; -for (cur = (start >>RANGE_BITS ); cur < end; cur++) { + range_size =hot_raw_shift (1 , + root->hot_type->range_bits, true); + end =hot_raw_shift ((start + len + range_size -1 ), + root->hot_type->range_bits, false); + cur =hot_raw_shift (start, root->hot_type->range_bits, false); +for (; cur < end; cur++) { hr =hot_range_item_lookup (he, cur);if (IS_ERR (hr)) { WARN(1, "hot_range_item_lookup returns %ld\n",
@@ -677,7 +687,7 @@ void hot_update_freqs(struct inode *inode, loff_t start, }spin_lock (&hr->hot_range.lock); -hot_freq_data_update (&hr->hot_range.hot_freq_data, rw); +hot_freq_data_update (root, &hr->hot_range.hot_freq_data, rw);spin_unlock (&hr->hot_range.lock);hot_range_item_put (hr);
@@ -705,6 +715,17 @@ int hot_track_init(struct super_block *sb)hot_inode_tree_init (root);hot_map_init (root); +/* Get hot type for specific FS */ + root->hot_type = &sb->s_type->hot_type; +if (!root->hot_type->ops.hot_rw_freq_calc_fn) + root->hot_type->ops.hot_rw_freq_calc_fn = hot_rw_freq_calc; +if (!root->hot_type->ops.hot_temp_calc_fn) + root->hot_type->ops.hot_temp_calc_fn = hot_temp_calc; +if (!root->hot_type->ops.hot_is_obsolete_fn) + root->hot_type->ops.hot_is_obsolete_fn = hot_is_obsolete; +if (root->hot_type->range_bits ==0 ) + root->hot_type->range_bits =RANGE_BITS ; + root->update_wq =alloc_workqueue ("hot_update_wq" ,WQ_NON_REENTRANT ,0 );if (!root->update_wq) {
fs/hot_tracking.h +0 -1
@@ -21,7 +21,6 @@/* size of sub-file ranges */ #define RANGE_BITS 20 -#define RANGE_SIZE (1 << RANGE_BITS)#define FREQ_POWER 4/*
include/linux/fs.h +1 -0
@@ -1821,6 +1821,7 @@ struct file_system_type {struct dentry *(*mount) (struct file_system_type *,int ,const char *,void *);void (*kill_sb) (struct super_block *); +struct hot_type hot_type;struct module *owner;struct file_system_type * next;struct hlist_head fs_supers;
include/linux/hot_tracking.h +19 -0
@@ -79,6 +79,24 @@ struct hot_range_item {size_t len;/* length in bytes */ }; +typedef void (hot_rw_freq_calc_fn ) (struct timespec old_atime, +struct timespec cur_time,u64 *avg); +typedef u32 (hot_temp_calc_fn ) (struct hot_freq_data *freq_data); +typedef bool (hot_is_obsolete_fn ) (struct hot_freq_data *freq_data); + +struct hot_func_ops { +hot_rw_freq_calc_fn *hot_rw_freq_calc_fn; +hot_temp_calc_fn *hot_temp_calc_fn; +hot_is_obsolete_fn *hot_is_obsolete_fn; +}; + +/* identifies an hot type */ +struct hot_type { +u64 range_bits; +/* fields provided by specific FS */ +struct hot_func_ops ops; +}; +struct hot_info {struct hot_rb_tree hot_inode_tree;spinlock_t lock;/*protect inode tree */
@@ -91,6 +109,7 @@ struct hot_info {struct workqueue_struct *update_wq;struct delayed_work update_work; +struct hot_type *hot_type; };extern void __init hot_cache_init (void );
Signature · 1 line
1.7.6.5
PATCH RESEND 11/16 vfs: register one shrinker
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Register a shrinker to control the amount of
memory that is used in tracking hot regions - if we are throwing inodes out of memory due to memory pressure, we most definitely are going to need to reduce the amount of memory the tracking code is using, even if it means losing useful information (i.e. the shrinker accelerates the aging process).
--- fs/hot_tracking.c | 63 ++++++++++++++++++++++++++++++++++++++++++ include/linux/hot_tracking.h | 1 + 2 files changed, 64 insertions(+), 0 deletions(-)
fs/hot_tracking.c +63 -0
@@ -643,6 +643,63 @@ err: }EXPORT_SYMBOL_GPL (hot_cache_init); +static int hot_track_prune_map (struct hot_map_head *map_head, +bool type,int nr) +{ +struct hot_comm_item *node; +int i; + +for (i =0 ; i <HEAT_MAP_SIZE ; i++) { +spin_lock (&(map_head + i)->lock); +while (!list_empty (&(map_head + i)->node_list)) { +if (nr-- <=0 ) +break ; + + node =list_first_entry (&(map_head + i)->node_list, + struct hot_comm_item, n_list); +if (type) { +struct hot_inode_item *hot_inode = +container_of (node, + struct hot_inode_item, hot_inode); +hot_inode_item_put (hot_inode); + }else { +struct hot_range_item *hot_range = +container_of (node, + struct hot_range_item, hot_range); +hot_range_item_put (hot_range); + } + } +spin_unlock (&(map_head + i)->lock); + } + +return nr; +} + +/* The shrinker callback function */ +static int hot_track_prune (struct shrinker *shrink, +struct shrink_control *sc) +{ +struct hot_info *root = + container_of(shrink, struct hot_info, hot_shrink); +int ret; + +if (sc->nr_to_scan ==0 ) +return root->hot_map_nr; + +if (!(sc->gfp_mask & __GFP_FS)) +return -1 ; + + ret =hot_track_prune_map (root->heat_range_map, + false, sc->nr_to_scan); +if (ret >0 ) + ret =hot_track_prune_map (root->heat_inode_map, + true, ret); +if (ret >0 ) + root->hot_map_nr -= (sc->nr_to_scan - ret); + +return root->hot_map_nr; +} +/* * Main function to update access frequency from read/writepage(s) hooks */
@@ -739,6 +796,11 @@ int hot_track_init(struct super_block *sb)queue_delayed_work (root->update_wq, &root->update_work,msecs_to_jiffies (HEAT_UPDATE_DELAY *MSEC_PER_SEC )); +/* Register a shrinker callback */ + root->hot_shrink.shrink = hot_track_prune; + root->hot_shrink.seeks =DEFAULT_SEEKS ; +register_shrinker (&root->hot_shrink); + sb->s_hot_root = root;printk (KERN_INFO "VFS: Turning on hot data tracking\n" );
@@ -757,6 +819,7 @@ void hot_track_exit(struct super_block *sb) {struct hot_info *root = sb->s_hot_root; +unregister_shrinker (&root->hot_shrink);cancel_delayed_work_sync (&root->update_work);destroy_workqueue (root->update_wq);hot_map_exit (root);
include/linux/hot_tracking.h +1 -0
@@ -110,6 +110,7 @@ struct hot_info {struct workqueue_struct *update_wq;struct delayed_work update_work;struct hot_type *hot_type; +struct shrinker hot_shrink; };extern void __init hot_cache_init (void );
Signature · 1 line
1.7.6.5
PATCH RESEND 12/16 vfs: add one ioctl interface
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
FS_IOC_GET_HEAT_INFO: return a struct containing the various
metrics collected in hot_freq_data structs, and also return a calculated data temperature based on those metrics. Optionally, retrieve the temperature from the hot data hash list instead of recalculating it.
--- fs/compat_ioctl.c | 5 +++ fs/ioctl.c | 74 ++++++++++++++++++++++++++++++++++++++++++ include/linux/hot_tracking.h | 19 +++++++++++ 3 files changed, 98 insertions(+), 0 deletions(-)
fs/compat_ioctl.c +5 -0
@@ -57,6 +57,7 @@#include <linux/i2c-dev.h> #include <linux/atalk.h> #include <linux/gfp.h> +#include <linux/hot_tracking.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci.h>
@@ -1403,6 +1404,9 @@ COMPATIBLE_IOCTL(TIOCSTART) COMPATIBLE_IOCTL(TIOCSTOP)#endif +/*Hot data tracking*/ +COMPATIBLE_IOCTL (FS_IOC_GET_HEAT_INFO ) +/* fat 'r' ioctls. These are handled by fat with ->compat_ioctl, but we don't want warnings on other file systems. So declare them as compatible here. */
@@ -1582,6 +1586,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,case FIBMAP :case FIGETBSZ :case FIONREAD : +case FS_IOC_GET_HEAT_INFO :if (S_ISREG (f.file->f_path.dentry->d_inode->i_mode))break ;/*FALL THROUGH*/
fs/ioctl.c +74 -0
92 lines not on this page · raw message
include/linux/hot_tracking.h +19 -0
@@ -43,6 +43,17 @@ struct hot_freq_data {u32 last_temp; }; +struct hot_heat_info { +__u64 avg_delta_reads; +__u64 avg_delta_writes; +__u64 last_read_time; +__u64 last_write_time; +__u32 num_reads; +__u32 num_writes; +__u32 temp; +__u8 live; +}; +/* List heads in hot map array */ struct hot_map_head {struct list_head node_list;
@@ -113,6 +124,14 @@ struct hot_info {struct shrinker hot_shrink; }; +/* +* Hot data tracking ioctls: +* +* HOT_INFO - retrieve info on frequency of access +*/ +#define FS_IOC_GET_HEAT_INFO _IOR('f', 17, \ + struct hot_heat_info) +extern void __init hot_cache_init (void );extern int hot_track_init (struct super_block *sb);extern void hot_track_exit (struct super_block *sb);
Signature · 1 line
1.7.6.5
PATCH RESEND 13/16 vfs: add debugfs support
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Add a /sys/kernel/debug/hot_track/<device_name>/ directory for each
volume that contains two files. The first, inode_stats', contains the heat information for inodes that have been brought into the hot data map structures. The second, range_stats', contains similar information for subfile ranges.
--- fs/hot_tracking.c | 513 +++++++++++++++++++++++++++++++++++++++++- fs/hot_tracking.h | 5 + include/linux/hot_tracking.h | 1 + 3 files changed, 517 insertions(+), 2 deletions(-)
fs/hot_tracking.c +511 -2
@@ -21,9 +21,12 @@#include <linux/blkdev.h> #include <linux/types.h> #include <linux/list_sort.h> +#include <linux/debugfs.h> #include <linux/limits.h> #include "hot_tracking.h" +static struct dentry *hot_debugfs_root; +/* kmem_cache pointers for slab caches */ static struct kmem_cache *hot_inode_item_cachep__read_mostly ;static struct kmem_cache *hot_range_item_cachep__read_mostly ;
@@ -218,8 +221,8 @@ struct hot_inode_itemelse if (ino > entry->i_ino) p = &(*p)->rb_right;else { -spin_unlock (&root->lock);kref_get (&entry->hot_inode.refs); +spin_unlock (&root->lock);return entry; } }
@@ -269,8 +272,8 @@ static struct hot_range_itemelse if (start >hot_range_end (entry)) p = &(*p)->rb_right;else { -spin_unlock (&he->lock);kref_get (&entry->hot_range.refs); +spin_unlock (&he->lock);return entry; } }
@@ -617,6 +620,499 @@ static void hot_update_worker(struct work_struct *work) msecs_to_jiffies(HEAT_UPDATE_DELAY * MSEC_PER_SEC)); } +static void *hot_range_seq_start (struct seq_file *seq,loff_t *pos) +{ +struct hot_info *root = seq->private; +struct rb_node *node, *node2; +struct hot_comm_item *ci; +struct hot_inode_item *he; +struct hot_range_item *hr; +loff_t l = *pos; + +spin_lock (&root->lock); + node =rb_first (&root->hot_inode_tree.map); +while (node) { + ci = rb_entry(node, struct hot_comm_item, rb_node); + he = container_of(ci, struct hot_inode_item, hot_inode); +spin_lock (&he->lock); + node2 =rb_first (&he->hot_range_tree.map); +while (node2) { +if (!l--) { + ci =rb_entry (node2, + struct hot_comm_item, rb_node); + hr =container_of (ci, + struct hot_range_item, hot_range); +kref_get (&hr->hot_range.refs); +spin_unlock (&he->lock); +spin_unlock (&root->lock); +return hr; + } + node2 =rb_next (node2); + } + node =rb_next (node); +spin_unlock (&he->lock); + } +spin_unlock (&root->lock); +return NULL ; +} + +static void *hot_range_seq_next (struct seq_file *seq, +void *v,loff_t *pos) +{ +struct rb_node *node, *node2; +struct hot_comm_item *ci; +struct hot_inode_item *he; +struct hot_range_item *hr_next =NULL , *hr = v; + +spin_lock (&hr->hot_range.lock); + (*pos)++; + node2 =rb_next (&hr->hot_range.rb_node); +if (node2) + goto next; + + node =rb_next (&hr->hot_inode->hot_inode.rb_node); +if (node) { + ci = rb_entry(node, struct hot_comm_item, rb_node); + he = container_of(ci, struct hot_inode_item, hot_inode); + node2 =rb_first (&he->hot_range_tree.map); +if (node2) { +next: + ci =rb_entry (node2, + struct hot_comm_item, rb_node); + hr_next =container_of (ci, + struct hot_range_item, hot_range); +kref_get (&hr_next->hot_range.refs); + } + } +spin_unlock (&hr->hot_range.lock); + +hot_range_item_put (hr); +return hr_next; +} + +static void hot_range_seq_stop (struct seq_file *seq,void *v) +{ +struct hot_range_item *hr = v; + +if (hr) +hot_range_item_put (hr); +} + +static int hot_range_seq_show (struct seq_file *seq,void *v) +{ +struct hot_range_item *hr = v; +struct hot_inode_item *he = hr->hot_inode; +struct hot_freq_data *freq_data = &hr->hot_range.hot_freq_data; +struct hot_info *root =container_of (he->hot_inode_tree, + struct hot_info, hot_inode_tree); +loff_t start = hr->start *hot_raw_shift (1 , + root->hot_type->range_bits, true); + +/* Always lock hot_inode_item first */ +spin_lock (&he->hot_inode.lock); +spin_lock (&hr->hot_range.lock); +seq_printf (seq,"inode %llu, range " \ +"%llu+%llu, reads %u, writes %u, temp %u\n" , + he->i_ino, (unsigned long long )start, + (unsigned long long )hr->len, + freq_data->nr_reads, + freq_data->nr_writes, + (u8 )hot_raw_shift ((u64 )freq_data->last_temp, + (32 -HEAT_MAP_BITS ), false)); +spin_unlock (&hr->hot_range.lock); +spin_unlock (&he->hot_inode.lock); + +return 0 ; +} + +static void *hot_inode_seq_start (struct seq_file *seq,loff_t *pos) +{ +struct hot_info *root = seq->private; +struct rb_node *node; +struct hot_comm_item *ci; +struct hot_inode_item *he =NULL ; +loff_t l = *pos; + +spin_lock (&root->lock); + node =rb_first (&root->hot_inode_tree.map); +while (node) { +if (!l--) { + ci = rb_entry(node, struct hot_comm_item, rb_node); + he =container_of (ci, + struct hot_inode_item, hot_inode); +kref_get (&he->hot_inode.refs); +break ; + } + node =rb_next (node); + } +spin_unlock (&root->lock); + +return he; +} + +static void *hot_inode_seq_next (struct seq_file *seq,void *v,loff_t *pos) +{ +struct hot_inode_item *he_next =NULL , *he = v; +struct rb_node *node; +struct hot_comm_item *ci; + +spin_lock (&he->hot_inode.lock); + (*pos)++; + node =rb_next (&he->hot_inode.rb_node); +if (node) { + ci = rb_entry(node, struct hot_comm_item, rb_node); + he_next =container_of (ci, + struct hot_inode_item, hot_inode); +kref_get (&he_next->hot_inode.refs); + } +spin_unlock (&he->hot_inode.lock); + +hot_inode_item_put (he); + +return he_next; +} + +static void hot_inode_seq_stop (struct seq_file *seq,void *v) +{ +struct hot_inode_item *he = v; + +if (he) +hot_inode_item_put (he); +} + +static int hot_inode_seq_show (struct seq_file *seq,void *v) +{ +struct hot_inode_item *he = v; +struct hot_freq_data *freq_data = &he->hot_inode.hot_freq_data; + +spin_lock (&he->hot_inode.lock); +seq_printf (seq,"inode %llu, reads %u, writes %u, temp %d\n" , + he->i_ino, + freq_data->nr_reads, + freq_data->nr_writes, + (u8 )hot_raw_shift ((u64 )freq_data->last_temp, + (32 -HEAT_MAP_BITS ), false)); +spin_unlock (&he->hot_inode.lock); + +return 0 ; +} + +static void *hot_spot_range_seq_start (struct seq_file *seq,loff_t *pos) +{ +struct hot_info *root = seq->private; +struct hot_range_item *hr; +struct hot_comm_item *comm_item; +struct list_head *n_list; +int i; + +for (i =HEAT_MAP_SIZE -1 ; i >=0 ; i--) { +spin_lock (&root->heat_range_map[i].lock); + n_list =seq_list_start ( + &root->heat_range_map[i].node_list, *pos); +if (n_list) { + comm_item =container_of (n_list, + struct hot_comm_item, n_list); + hr =container_of (comm_item, + struct hot_range_item, hot_range); +kref_get (&hr->hot_range.refs); +spin_unlock (&root->heat_range_map[i].lock); +return hr; + } +spin_unlock (&root->heat_range_map[i].lock); + } + +return NULL ; +} + +static void *hot_spot_range_seq_next (struct seq_file *seq,void *v,loff_t *pos) +{ +struct hot_info *root = seq->private; +struct hot_range_item *hr_next, *hr = v; +struct hot_comm_item *comm_item; +struct list_head *n_list; +int i, j; +spin_lock (&hr->hot_range.lock); + i = (int )hot_raw_shift (hr->hot_range.hot_freq_data.last_temp, + (32 -HEAT_MAP_BITS ), false); +spin_unlock (&hr->hot_range.lock); + +spin_lock (&root->heat_range_map[i].lock); + n_list =seq_list_next (&hr->hot_range.n_list, + &root->heat_range_map[i].node_list, pos); +hot_range_item_put (hr); +next: + j = i; +if (n_list) { + comm_item =container_of (n_list, + struct hot_comm_item, n_list); + hr_next =container_of (comm_item, + struct hot_range_item, hot_range); +kref_get (&hr_next->hot_range.refs); +spin_unlock (&root->heat_range_map[i].lock); +return hr_next; + }else if (--i >=0 ) { +spin_unlock (&root->heat_range_map[j].lock); +spin_lock (&root->heat_range_map[i].lock); + n_list =seq_list_next (&root->heat_range_map[i].node_list, + &root->heat_range_map[i].node_list, pos); + goto next; + } + +spin_unlock (&root->heat_range_map[j].lock); +return NULL ; +} + +static void *hot_spot_inode_seq_start (struct seq_file *seq,loff_t *pos) +{ +struct hot_info *root = seq->private; +struct hot_inode_item *he; +struct hot_comm_item *comm_item; +struct list_head *n_list; +int i; + +for (i =HEAT_MAP_SIZE -1 ; i >=0 ; i--) { +spin_lock (&root->heat_inode_map[i].lock); + n_list =seq_list_start ( + &root->heat_inode_map[i].node_list, *pos); +if (n_list) { + comm_item =container_of (n_list, + struct hot_comm_item, n_list); + he =container_of (comm_item, + struct hot_inode_item, hot_inode); +kref_get (&he->hot_inode.refs); +spin_unlock (&root->heat_inode_map[i].lock); +return he; + } +spin_unlock (&root->heat_inode_map[i].lock); + } + +return NULL ; +} + +static void *hot_spot_inode_seq_next (struct seq_file *seq,void *v,loff_t *pos) +{ +struct hot_info *root = seq->private; +struct hot_inode_item *he_next, *he = v; +struct hot_comm_item *comm_item; +struct list_head *n_list; +int i, j; +spin_lock (&he->hot_inode.lock); + i = (int )hot_raw_shift (he->hot_inode.hot_freq_data.last_temp, + (32 -HEAT_MAP_BITS ), false); +spin_unlock (&he->hot_inode.lock); + +spin_lock (&root->heat_inode_map[i].lock); + n_list =seq_list_next (&he->hot_inode.n_list, + &root->heat_inode_map[i].node_list, pos); +hot_inode_item_put (he); +next: + j = i; +if (n_list) { + comm_item =container_of (n_list, + struct hot_comm_item, n_list); + he_next =container_of (comm_item, + struct hot_inode_item, hot_inode); +kref_get (&he_next->hot_inode.refs); +spin_unlock (&root->heat_inode_map[i].lock); +return he_next; + }else if (--i >=0 ) { +spin_unlock (&root->heat_inode_map[j].lock); +spin_lock (&root->heat_inode_map[i].lock); + n_list =seq_list_next (&root->heat_inode_map[i].node_list, + &root->heat_inode_map[i].node_list, pos); + goto next; + } + +spin_unlock (&root->heat_inode_map[j].lock); +return NULL ; +} + +static const struct seq_operations hot_range_seq_ops = { + .start = hot_range_seq_start, + .next = hot_range_seq_next, + .stop = hot_range_seq_stop, + .show = hot_range_seq_show +}; + +static const struct seq_operations hot_inode_seq_ops = { + .start = hot_inode_seq_start, + .next = hot_inode_seq_next, + .stop = hot_inode_seq_stop, + .show = hot_inode_seq_show +}; + +static const struct seq_operations hot_spot_range_seq_ops = { + .start = hot_spot_range_seq_start, + .next = hot_spot_range_seq_next, + .stop = hot_range_seq_stop, + .show = hot_range_seq_show +}; + +static const struct seq_operations hot_spot_inode_seq_ops = { + .start = hot_spot_inode_seq_start, + .next = hot_spot_inode_seq_next, + .stop = hot_inode_seq_stop, + .show = hot_inode_seq_show +}; + +static int hot_range_seq_open (struct inode *inode,struct file *file) +{ +int ret =seq_open_private (file, &hot_range_seq_ops,0 ); +if (ret ==0 ) { +struct seq_file *seq = file->private_data; + seq->private = inode->i_private; + } +return ret; +} + +static int hot_inode_seq_open (struct inode *inode,struct file *file) +{ +int ret =seq_open_private (file, &hot_inode_seq_ops,0 ); +if (ret ==0 ) { +struct seq_file *seq = file->private_data; + seq->private = inode->i_private; + } +return ret; +} + +static int hot_spot_range_seq_open (struct inode *inode,struct file *file) +{ +int ret =seq_open_private (file, &hot_spot_range_seq_ops,0 ); +if (ret ==0 ) { +struct seq_file *seq = file->private_data; + seq->private = inode->i_private; + } +return ret; +} + +static int hot_spot_inode_seq_open (struct inode *inode,struct file *file) +{ +int ret =seq_open_private (file, &hot_spot_inode_seq_ops,0 ); +if (ret ==0 ) { +struct seq_file *seq = file->private_data; + seq->private = inode->i_private; + } +return ret; +} + +/* fops to override for printing range data */ +static const struct file_operations hot_debugfs_range_fops = { + .open = hot_range_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +/* fops to override for printing inode data */ +static const struct file_operations hot_debugfs_inode_fops = { + .open = hot_inode_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +/* fops to override for printing temperature data */ +static const struct file_operations hot_debugfs_spot_range_fops = { + .open = hot_spot_range_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations hot_debugfs_spot_inode_fops = { + .open = hot_spot_inode_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct hot_debugfs hot_debugfs[] = { + { + .name ="rt_stats_range" , + .fops = &hot_debugfs_range_fops, + }, + { + .name ="rt_stats_inode" , + .fops = &hot_debugfs_inode_fops, + }, + { + .name ="hot_spots_range" , + .fops = &hot_debugfs_spot_range_fops, + }, + { + .name ="hot_spots_inode" , + .fops = &hot_debugfs_spot_inode_fops, + }, +}; + +/* initialize debugfs */ +static int hot_debugfs_init (struct super_block *sb) +{ +static const char hot_name[] ="hot_track" ; +struct dentry *dentry; +int i, ret =0 ; + +/* Determine if hot debufs root has existed */ +if (!hot_debugfs_root) { + hot_debugfs_root =debugfs_create_dir (hot_name,NULL ); +if (IS_ERR (hot_debugfs_root)) { + ret =PTR_ERR (hot_debugfs_root); +return ret; + } + } + +if (!S_ISDIR (hot_debugfs_root->d_inode->i_mode)) +return -ENOTDIR ; + +/* create debugfs folder for this volume by mounted dev name */ + sb->s_hot_root->vol_dentry = +debugfs_create_dir (sb->s_id, hot_debugfs_root); +if (IS_ERR (sb->s_hot_root->vol_dentry)) { + ret =PTR_ERR (sb->s_hot_root->vol_dentry); + goto err; + } + +/* create debugfs hot data files */ +for (i =0 ; i <ARRAY_SIZE (hot_debugfs); i++) { + dentry =debugfs_create_file (hot_debugfs[i].name, +S_IFREG |S_IRUSR |S_IWUSR , + sb->s_hot_root->vol_dentry, + sb->s_hot_root, + hot_debugfs[i].fops); +if (IS_ERR (dentry)) { + ret =PTR_ERR (dentry); + goto err; + } + } + +return 0 ; + +err: +debugfs_remove_recursive (sb->s_hot_root->vol_dentry); + +if (list_empty (&hot_debugfs_root->d_subdirs)) { +debugfs_remove (hot_debugfs_root); + hot_debugfs_root =NULL ; + } + +return ret; +} + +/* remove dentries for debugsfs */ +static void hot_debugfs_exit (struct super_block *sb) +{ +/* remove all debugfs entries recursively from the volume root */ +if (sb->s_hot_root->vol_dentry) +debugfs_remove_recursive (sb->s_hot_root->vol_dentry); +else +BUG (); + +if (list_empty (&hot_debugfs_root->d_subdirs)) { +debugfs_remove (hot_debugfs_root); + hot_debugfs_root =NULL ; + } +} +/* * Initialize kmem cache for hot_inode_item and hot_range_item. */
@@ -803,10 +1299,22 @@ int hot_track_init(struct super_block *sb) sb->s_hot_root = root; + ret =hot_debugfs_init (sb); +if (ret) { +printk (KERN_ERR "%s: hot_debugfs_init error: %d\n" , + __func__, ret); + goto failed_debugfs; + } +printk (KERN_INFO "VFS: Turning on hot data tracking\n" );return 0 ; +failed_debugfs: +unregister_shrinker (&root->hot_shrink); +cancel_delayed_work_sync (&root->update_work); +destroy_workqueue (root->update_wq); + sb->s_hot_root =NULL ; failed_wq:hot_map_exit (root);hot_inode_tree_exit (root);
@@ -819,6 +1327,7 @@ void hot_track_exit(struct super_block *sb) {struct hot_info *root = sb->s_hot_root; +hot_debugfs_exit (sb);unregister_shrinker (&root->hot_shrink);cancel_delayed_work_sync (&root->update_work);destroy_workqueue (root->update_wq);
fs/hot_tracking.h +5 -0
@@ -53,4 +53,9 @@#define AVW_DIVIDER_POWER 40/* AVW - average delta between recent writes(ns) */ #define AVW_COEFF_POWER 0 +struct hot_debugfs { +const char *name; +const struct file_operations *fops; +}; +#endif /* __HOT_TRACKING__ */
include/linux/hot_tracking.h +1 -0
@@ -122,6 +122,7 @@ struct hot_info {struct delayed_work update_work;struct hot_type *hot_type;struct shrinker hot_shrink; +struct dentry *vol_dentry; };/*
Signature · 1 line
1.7.6.5
PATCH RESEND 14/16 proc: add two hot_track proc files
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Add two proc files hot-kick-time and hot-update-delay
under the dir /proc/sys/fs/ in order to turn TIME_TO_KICK and HEAT_UPDATE_DELAY into be tunable.
--- fs/hot_tracking.c | 12 +++++++++--- fs/hot_tracking.h | 9 --------- include/linux/hot_tracking.h | 7 +++++++ kernel/sysctl.c | 14 ++++++++++++++ 4 files changed, 30 insertions(+), 12 deletions(-)
fs/hot_tracking.c +9 -3
@@ -27,6 +27,12 @@static struct dentry *hot_debugfs_root; +int sysctl_hot_kick_time__read_mostly =300 ; +EXPORT_SYMBOL_GPL (sysctl_hot_kick_time); + +int sysctl_hot_update_delay__read_mostly =300 ; +EXPORT_SYMBOL_GPL (sysctl_hot_update_delay); +/* kmem_cache pointers for slab caches */ static struct kmem_cache *hot_inode_item_cachep__read_mostly ;static struct kmem_cache *hot_range_item_cachep__read_mostly ;
@@ -409,7 +415,7 @@ static bool hot_is_obsolete(struct hot_freq_data *freq_data) (cur_time -timespec_to_ns (&freq_data->last_read_time));u64 last_write_ns = (cur_time -timespec_to_ns (&freq_data->last_write_time)); -u64 kick_ns =TIME_TO_KICK *NSEC_PER_SEC ; +u64 kick_ns = sysctl_hot_kick_time *NSEC_PER_SEC ;if ((last_read_ns > kick_ns) && (last_write_ns > kick_ns)) ret =1 ;
@@ -617,7 +623,7 @@ static void hot_update_worker(struct work_struct *work)/* Instert next delayed work */ queue_delayed_work (root->update_wq, &root->update_work, -msecs_to_jiffies (HEAT_UPDATE_DELAY *MSEC_PER_SEC )); +msecs_to_jiffies (sysctl_hot_update_delay *MSEC_PER_SEC )); }static void *hot_range_seq_start (struct seq_file *seq,loff_t *pos)
@@ -1290,7 +1296,7 @@ int hot_track_init(struct super_block *sb)/* Initialize hot tracking wq and arm one delayed work */ INIT_DELAYED_WORK (&root->update_work, hot_update_worker);queue_delayed_work (root->update_wq, &root->update_work, -msecs_to_jiffies (HEAT_UPDATE_DELAY *MSEC_PER_SEC )); +msecs_to_jiffies (sysctl_hot_update_delay *MSEC_PER_SEC ));/* Register a shrinker callback */ root->hot_shrink.shrink = hot_track_prune;
fs/hot_tracking.h +0 -9
@@ -23,15 +23,6 @@#define RANGE_BITS 20#define FREQ_POWER 4 -/* -* time to quit keeping track of -* tracking data (seconds) -*/ -#define TIME_TO_KICK 300 - -/* set how often to update temperatures (seconds) */ -#define HEAT_UPDATE_DELAY 300 -/* NRR/NRW heat unit = 2^X accesses */ #define NRR_MULTIPLIER_POWER 20/* NRR - number of reads since mount */ #define NRR_COEFF_POWER 0
include/linux/hot_tracking.h +7 -0
@@ -126,6 +126,13 @@ struct hot_info { };/* +* Two variables have meanings as below: +* 1. time to quit keeping track of tracking data (seconds) +* 2. set how often to update temperatures (seconds) +*/ +extern int sysctl_hot_kick_time, sysctl_hot_update_delay; + +/* * Hot data tracking ioctls: * * HOT_INFO - retrieve info on frequency of access
kernel/sysctl.c +14 -0
@@ -1586,6 +1586,20 @@ static struct ctl_table fs_table[] = { .proc_handler = &pipe_proc_fn, .extra1 = &pipe_min_size, }, + { + .procname = "hot-kick-time", + .data = &sysctl_hot_kick_time, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "hot-update-delay", + .data = &sysctl_hot_update_delay, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { } };
Signature · 1 line
1.7.6.5
PATCH RESEND 15/16 btrfs: add hot tracking support
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Introduce one new mount option '-o hot_track',
and add its parsing support.
Its usage looks like:
mount -o hot_track
mount -o nouser,hot_track
mount -o nouser,hot_track,loop
mount -o hot_track,nouser
--- fs/btrfs/ctree.h | 1 + fs/btrfs/super.c | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletions(-)
fs/btrfs/ctree.h +1 -0
@@ -1829,6 +1829,7 @@ struct btrfs_ioctl_defrag_range_args {#define BTRFS_MOUNT_CHECK_INTEGRITY (1 << 20)#define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21)#define BTRFS_MOUNT_PANIC_ON_FATAL_ERROR (1 << 22) +#define BTRFS_MOUNT_HOT_TRACK (1 << 23)#define btrfs_clear_opt (o, opt) ((o) &= ~BTRFS_MOUNT_##opt)#define btrfs_set_opt (o, opt) ((o) |= BTRFS_MOUNT_##opt)
fs/btrfs/super.c +21 -1
@@ -41,6 +41,7 @@#include <linux/slab.h> #include <linux/cleancache.h> #include <linux/ratelimit.h> +#include <linux/hot_tracking.h> #include "compat.h" #include "delayed-inode.h" #include "ctree.h"
@@ -309,6 +310,10 @@ static void btrfs_put_super(struct super_block *sb)* last process that kept it busy. Or segfault in the aforementioned * process... Whom would you report that to? */ + +/* Hot data tracking */ +if (btrfs_test_opt (btrfs_sb (sb)->tree_root,HOT_TRACK )) +hot_track_exit (sb); }enum {
@@ -321,7 +326,7 @@ enum { Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_inode_cache, Opt_no_space_cache, Opt_recovery, Opt_skip_balance, Opt_check_integrity, Opt_check_integrity_including_extent_data, - Opt_check_integrity_print_mask, Opt_fatal_errors, + Opt_check_integrity_print_mask, Opt_fatal_errors, Opt_hot_track, Opt_err, };
@@ -362,6 +367,7 @@ static match_table_t tokens = { {Opt_check_integrity_including_extent_data, "check_int_data"}, {Opt_check_integrity_print_mask, "check_int_print_mask=%d"}, {Opt_fatal_errors, "fatal_errors=%s"}, + {Opt_hot_track, "hot_track"}, {Opt_err, NULL}, };
@@ -624,6 +630,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) goto out; }break ; +case Opt_hot_track: +btrfs_set_opt (info->mount_opt,HOT_TRACK ); +break ;case Opt_err:printk (KERN_INFO "btrfs: unrecognized mount option " "'%s'\n" , p);
@@ -851,11 +860,20 @@ static int btrfs_fill_super(struct super_block *sb, goto fail_close; } +if (btrfs_test_opt (fs_info->tree_root,HOT_TRACK )) { + err =hot_track_init (sb); +if (err) + goto fail_hot; + } +save_mount_options (sb, data);cleancache_init_fs (sb); sb->s_flags |=MS_ACTIVE ;return 0 ; +fail_hot: +dput (sb->s_root); + sb->s_root =NULL ; fail_close:close_ctree (fs_info->tree_root);return err;
@@ -951,6 +969,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)seq_puts (seq,",skip_balance" );if (btrfs_test_opt (root,PANIC_ON_FATAL_ERROR ))seq_puts (seq,",fatal_errors=panic" ); +if (btrfs_test_opt (root,HOT_TRACK )) +seq_puts (seq,",hot_track" );return 0 ; }
Signature · 1 line
1.7.6.5
PATCH RESEND 16/16 vfs: add documentation
In reply to [email protected]From: Zhi Yong Wu <[email protected]>
Add one doc for VFS hot tracking feature
--- Documentation/filesystems/00-INDEX | 2 + Documentation/filesystems/hot_tracking.txt | 255 ++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+), 0 deletions(-) create mode 100644 Documentation/filesystems/hot_tracking.txt
Documentation/filesystems/00-INDEX +2 -0
@@ -120,3 +120,5 @@ xfs.txt - info and mount options for the XFS filesystem. xip.txt - info on execute-in-place for file mappings. +hot_tracking.txt + - info on hot data tracking in VFS layer
Documentation/filesystems/hot_tracking.txt new file +255 -0
255 lines not on this page · raw message
Signature · 1 line
1.7.6.5
HI,
The raw data is very big, i don't know if it is appropriate to post them here. If you want to get them, please let me know.
Quoted 273 lines · On Thu, Dec 20, 2012 at 10:43 PM, <[email protected]> wrote:
From: Zhi Yong Wu <[email protected]>
HI, guys,
This patchset has been done scalability or performance tests
byfs_mark, ffsb and compilebench.
I have done the perf testing on Linux 3.7.0-rc8+ with Intel(R) Core(TM)
i7-3770 CPU @ 3.40GHz with 8 CPUs, 16G ram and 260G disk.Any comments or ideas are appreciated, thanks.
NOTE:
The patchset can be obtained via my kernel dev git on github:
git://github.com/wuzhy/kernel.githot_tracking
If you're interested, you can also review them via
https://github.com/wuzhy/kernel/commits/hot_trackingFor more info, please check hot_tracking.txt in Documentation
Below is the perf testing report:
1.
fs_marktestw/o: without hot tracking
w/ : with hot trackingCount Size FSUse% Files/sec App Overhead
w/o w/ w/o w/ w/o w/
800000 1 2 3 13756.4 32144.9 5350627 5436291 1600000 1 4 5 1163.4 1799.3 20848119 21708216 2400000 1 6 6 1360.8 1252.5 6798705 8715322 3200000 1 8 8 1600.1 1196.3 5751129 6013792 4000000 1 9 9 1071.4 1191.2 17204725 26786369 4800000 1 10 10 1483.5 1447.9 19555541 8383046 5600000 1 11 11 1457.9 1699.5 5783588 10074681 6400000 1 12 13 1658.8 1628.5 6992697 6185551 7200000 1 14 14 1662.4 1857.1 5796793 13772592 8000000 1 15 15 2930.0 2653.8 12431682 6152573 8800000 1 16 17 1630.8 1665.0 7666719 13682765 9600000 1 18 18 1530.3 1583.9 5823644 10171644 10400000 1 19 19 1437.9 1798.6 20935224 6048083 11200000 1 20 20 1529.0 1550.6 6647450 6003151 12000000 1 21 22 1558.6 1501.8 12539509 18144939 12800000 1 23 23 1644.2 1432.1 7074419 28101975 13600000 1 24 24 1753.6 1650.2 7164297 20888972 14400000 1 25 25 2750.0 1483.9 12756692 7441225 15200000 1 27 27 1551.1 1514.3 5741066 8250443 16000000 1 28 28 1610.8 1635.9 72193860 8545285 16800000 1 29 29 1646.7 1907.7 8945856 11703513 17600000 1 30 31 1496.6 2722.3 5858961 8989393 18400000 1 32 32 1457.7 1565.7 10914475 26504660 19200000 1 33 33 1437.6 1518.7 6708975 213303618 20000000 1 34 34 1825.4 1521.1 5722086 12490907 20800000 1 36 35 1718.4 1611.5 5873290 17942534 21600000 1 37 37 2152.6 1536.9 113050627 8717940 22400000 1 38 38 2443.7 1788.2 7398122 19834765 23200000 1 39 39 1518.5 1587.6 5770959 10134882 24000000 1 41 41 1536.8 2164.0 5751248 7214626 24800000 1 42 42 1576.6 2939.4 7390314 6070271 25600000 1 43 43 1707.4 1535.9 11075939 6052896 26400000 1 44 44 1522.5 1563.1 10142987 22549898 27200000 1 46 46 1827.4 1608.5 11613016 24828125 28000000 1 47 47 3420.5 1741.9 8059985 16599156 28800000 1 48 48 1815.5 1944.4 7847931 9043277 29600000 1 50 49 1650.0 1596.6 5636323 7929164 30400000 1 51 51 1683.7 1573.3 5766323 19369146 31200000 1 52 52 1610.1 1669.8 9256111 9899107 32000000 1 53 53 1645.2 3081.0 7855010 6057257 32800000 1 54 55 1835.3 3122.0 6899141 6143875 33600000 1 56 56 1916.8 1734.8 10271967 6049509 34400000 1 57 57 3119.2 1630.8 11503274 13975417 35200000 1 58 58 1629.2 1695.7 6827225 6214248 36000000 1 60 60 1636.5 1695.4 38077664 16211067 36800000 1 61 61 1665.2 2069.1 19948817 9358494 37600000 1 62 62 1734.5 1931.5 26487196 8954836 38400000 1 63 63 1625.8 1654.0 6649289 9131844 39200000 1 65 65 1778.4 1663.3 11653376 7144960 40000000 1 66 66 1851.0 1935.6 8164470 11288753 40800000 1 67 67 3171.0 3431.6 12358380 6072820 41600000 1 69 69 1714.3 1954.3 13765035 9364495 42400000 1 70 70 1591.0 1681.8 18733304 7407689 43200000 1 71 71 1537.2 1642.8 19534908 6163018 44000000 1 72 72 1630.3 1641.2 23479883 10967509 44800000 1 74 74 1877.5 1651.9 8174965 9484587 45600000 1 75 75 3322.4 1653.6 14740938 7497831 46400000 1 76 76 1706.9 1840.6 10348550 23296562 47200000 1 77 78 1837.7 2515.3 13917543 14683192 48000000 1 79 79 1642.6 2368.6 14365759 6080942 48800000 1 80 80 1827.1 1655.2 9234312 7412406 49600000 1 81 81 1631.0 1858.7 7543970 18610881 50400000 1 82 82 1560.5 1865.0 21374219 6598771From the above table, when the same count files with same size are created, how FS is full is basically same.
2. FFSB test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1large_file_create
1 thread
- Trans/sec 28918.75 29014.48 +0.33%
- Throughput 113MB/sec 113MB/sec +0.0%
- %CPU 4.8% 5.1% +6.3%
- Trans/%CPU 602473.96 568911.37 -5.6%
8 threads
- Trans/sec 28480.37 28541.25 +0.2%
- Throughput 111MB/sec 111MB/sec +0.0%
- %CPU 5.6% 5.9% +5.4%
- Trans/%CPU 508578.04 483750 -4.9%
32 threads
- Trans/sec 25011.86 26992.32 +7.9%
- Throughput 97.7MB/sec 105MB/sec +7.5%
- %CPU 6.2% 7.1% +14.8%
- Trans/%CPU 403417.10 380173.52 -5.8%
large_file_seq_read
1 thread
- Trans/sec 35303.23 34838.02 -1.3%
- Throughput 138MB/sec 136MB/sec -1.4%
- %CPU 5.4% 5.4% +0.0%
- Trans/%CPU 653763.52 645148.52 -1.3%
8 threads
- Trans/sec 11902.82 11205.22 -5.9%
- Throughput 46.5MB/sec 43.8MB/sec -5.8%
- %CPU 2.1% 2.0% -4.8%
- Trans/%CPU 566800.95 560261 -1.2%
32 threads
- Trans/sec 5068.48 5316.36 +4.9%
- Throughput 19.8MB/sec 20.8MB/sec +5.1%
- %CPU 0.9% 1.0% +11.1%
- Trans/%CPU 563164.45 531636 -5.6%
random_write
1 thread
- Trans/sec 729.01 738.89 +1.4%
- Throughput 99.7MB/sec 101MB/sec +1.3%
- %CPU 0.1% 0.1% +0.0%
- Trans/%CPU 72901 73889 +1.4%
8 threads
- Trans/sec 714.56 714.57 +0.0%
- Throughput 97.7MB/sec 97.7MB/sec +0.0%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 35728 35728.5 +0.0%
32 threads
- Trans/sec 698.62 692.59 -0.9%
- Throughput 95.5MB/sec 94.7MB/sec -0.8%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 34931 34629.5 -0.9%
random_read
1 thread
- Trans/sec 225.49 227.03 +0.7%
- Throughput 902KB/sec 908KB/sec +0.7%
- %CPU 1.1% 1.1% +0.0%
- Trans/%CPU 20499.10 20639.10 +0.7%
8 threads
- Trans/sec 106.72 105.76 -0.9%
- Throughput 427KB/sec 423KB/sec -0.9%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2134.4 2115.2 -0.9%
32 threads
- Trans/sec 107.44 108.26 +0.8%
- Throughput 430KB/sec 433KB/sec +0.7%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2148.8 2165.2 +0.8%
mail_server
1 thread
- Trans/sec 681.67 732.66 +7.5%
- Throughput [read] 1.77MB/sec 1.99MB/sec +12.4%
- Throughput [write] 858KB/sec 887KB/sec +3.4%
- %CPU 0.6% 0.6% +0.0%
- Trans/%CPU 11361.17 12211 +7.5%
8 threads
- Trans/sec 630.48 597.08 -5.3%
- Throughput [read] 1.64MB/sec 1.54MB/sec -6.1%
- Throughput [write] 814KB/sec 784KB/sec -3.7%
- %CPU 0.6% 0.5% -16.7%
- Trans/%CPU 10508 11941.6 +13.6%
32 threads
- Trans/sec 598.68 566.05 -5.5%
- Throughput [read] 1.53MB/sec 1.5MB/sec -2.0%
- Throughput [write] 804KB/sec 705KB/sec -12.3%
- %CPU 0.7% 0.6% -14.2%
- Trans/%CPU 8552.57 9434.17 +10.3%3. Compilebench test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1intial create 114.81 MB/s 118.32 MB/s +3.1% create 11.98 MB/s 12.26 MB/s +2.3% patch 3.61 MB/s 3.66 MB/s +1.4% compile 46.40 MB/s 48.07 MB/s +3.6% clean 126.33 MB/s 128.75 MB/s +1.9% read tree 9.93 MB/s 9.71 MB/s -2.2% read compiled tree 17.19 MB/s 17.52 MB/s +1.9% delete tree 12.23 seconds 11.13 seconds -9.0% delete compiled tree 12.98 seconds 16.05 seconds +26.7% stat tree 7.03 seconds 5.51 seconds -21.6% stat compiled tree 12.19 seconds 9.06 seconds -25.7%Changelog:
- Solved 64 bits inode number issue. [David Sterba]
- Embed structhot_typein structfile_system_type[Darrick J. Wong]
- Cleanup Some issues [David Sterba]
- Use a static hot debugfs root [Greg KH]
- Rewritten debugfs support based onseq_fileoperation. [Dave Chinner]
- Refactored workqueue support. [Dave Chinner]
- Turn some Micro into be tunable [Zhiyong, Zheng Liu]
TIME_TO_KICK, andHEAT_UPDATE_DELAY
- Introduce hot func registering framework [Zhiyong]
- Remove global variable for hot tracking [Zhiyong]
- Add xfs hot tracking support [Dave Chinner]
- Add ext4 hot tracking support [Zheng Liu]
- Cleanedup a lot of other issues [Dave Chinner]
- Added memory shrinker [Dave Chinner]
- Converted to one workqueue to update map info periodically [Dave Chinner]
- Cleanedup a lot of other issues [Dave Chinner]
- Reduce new files and put all in fs/hot_tracking.[ch] [Dave Chinner]
- Add btrfs hot tracking support [Zhiyong]
- The first three patches can probably just be flattened into one. [Marco Stornelli , Dave Chinner]Zhi Yong Wu (16):
vfs: introduce some data structures
vfs: add init and cleanup functions
vfs: add I/O frequency update function
vfs: add two map arrays
vfs: add hooks to enable hot tracking
vfs: add temp calculation function
vfs: add map info update function
vfs: add aging function
vfs: add one work queue
vfs: add FS hot type support
vfs: register one shrinker
vfs: add one ioctl interface
vfs: add debugfs support
proc: add twohot_trackproc files
btrfs: add hot tracking support
vfs: add documentationDocumentation/filesystems/00-INDEX | 2 + Documentation/filesystems/hot_tracking.txt | 255 ++++++ fs/Makefile | 2 +- fs/btrfs/ctree.h | 1 + fs/btrfs/super.c | 22 +- fs/compat_ioctl.c | 5 + fs/dcache.c | 2 + fs/direct-io.c | 6 + fs/hot_tracking.c | 1345 ++++++++++++++++++++++++++++ fs/hot_tracking.h | 52 ++ fs/ioctl.c | 74 ++ include/linux/fs.h | 5 + include/linux/hot_tracking.h | 152 ++++ kernel/sysctl.c | 14 + mm/filemap.c | 6 + mm/page-writeback.c | 12 + mm/readahead.c | 7 + 17 files changed, 1960 insertions(+), 2 deletions(-) create mode 100644 Documentation/filesystems/hot_tracking.txt create mode 100644 fs/hot_tracking.c create mode 100644 fs/hot_tracking.h create mode 100644 include/linux/hot_tracking.h--
1.7.6.5
Signature · 3 lines
Regards, Zhi Yong Wu
hi,
any comments? Some graphs are generated based on the following benchmark data.
1. fs_mark test
https://github.com/wuzhy/perf_report/commit/8dbc7a00d280d7d7e625e336aac57391fa3e422c
2. ffsb test
1.) large_file_create
https://github.com/wuzhy/perf_report/commit/1582cf3fed06d32ffd93dbe109572a2a2fe2990f
2.) large_file_read
https://github.com/wuzhy/perf_report/commit/3b8a13c02c4b86de349e59215d8dbcdf88c5821c
3.) random_write
https://github.com/wuzhy/perf_report/commit/d4fc2aaa0626d40f72a4a06f8c5b5a10d5a949c3
4.) random_read
https://github.com/wuzhy/perf_report/commit/7e010b4fe193c6cf49c8c946be301ed3d3ac9eae
5.) mail_server
https://github.com/wuzhy/perf_report/commit/225f2b51ae3baab774e7cda6009d3745ec742d18
Quoted 273 lines · On Thu, Dec 20, 2012 at 10:43 PM, <[email protected]> wrote:
From: Zhi Yong Wu <[email protected]>
HI, guys,
This patchset has been done scalability or performance tests
byfs_mark, ffsb and compilebench.
I have done the perf testing on Linux 3.7.0-rc8+ with Intel(R) Core(TM)
i7-3770 CPU @ 3.40GHz with 8 CPUs, 16G ram and 260G disk.Any comments or ideas are appreciated, thanks.
NOTE:
The patchset can be obtained via my kernel dev git on github:
git://github.com/wuzhy/kernel.githot_tracking
If you're interested, you can also review them via
https://github.com/wuzhy/kernel/commits/hot_trackingFor more info, please check hot_tracking.txt in Documentation
Below is the perf testing report:
1.
fs_marktestw/o: without hot tracking
w/ : with hot trackingCount Size FSUse% Files/sec App Overhead
w/o w/ w/o w/ w/o w/
800000 1 2 3 13756.4 32144.9 5350627 5436291 1600000 1 4 5 1163.4 1799.3 20848119 21708216 2400000 1 6 6 1360.8 1252.5 6798705 8715322 3200000 1 8 8 1600.1 1196.3 5751129 6013792 4000000 1 9 9 1071.4 1191.2 17204725 26786369 4800000 1 10 10 1483.5 1447.9 19555541 8383046 5600000 1 11 11 1457.9 1699.5 5783588 10074681 6400000 1 12 13 1658.8 1628.5 6992697 6185551 7200000 1 14 14 1662.4 1857.1 5796793 13772592 8000000 1 15 15 2930.0 2653.8 12431682 6152573 8800000 1 16 17 1630.8 1665.0 7666719 13682765 9600000 1 18 18 1530.3 1583.9 5823644 10171644 10400000 1 19 19 1437.9 1798.6 20935224 6048083 11200000 1 20 20 1529.0 1550.6 6647450 6003151 12000000 1 21 22 1558.6 1501.8 12539509 18144939 12800000 1 23 23 1644.2 1432.1 7074419 28101975 13600000 1 24 24 1753.6 1650.2 7164297 20888972 14400000 1 25 25 2750.0 1483.9 12756692 7441225 15200000 1 27 27 1551.1 1514.3 5741066 8250443 16000000 1 28 28 1610.8 1635.9 72193860 8545285 16800000 1 29 29 1646.7 1907.7 8945856 11703513 17600000 1 30 31 1496.6 2722.3 5858961 8989393 18400000 1 32 32 1457.7 1565.7 10914475 26504660 19200000 1 33 33 1437.6 1518.7 6708975 213303618 20000000 1 34 34 1825.4 1521.1 5722086 12490907 20800000 1 36 35 1718.4 1611.5 5873290 17942534 21600000 1 37 37 2152.6 1536.9 113050627 8717940 22400000 1 38 38 2443.7 1788.2 7398122 19834765 23200000 1 39 39 1518.5 1587.6 5770959 10134882 24000000 1 41 41 1536.8 2164.0 5751248 7214626 24800000 1 42 42 1576.6 2939.4 7390314 6070271 25600000 1 43 43 1707.4 1535.9 11075939 6052896 26400000 1 44 44 1522.5 1563.1 10142987 22549898 27200000 1 46 46 1827.4 1608.5 11613016 24828125 28000000 1 47 47 3420.5 1741.9 8059985 16599156 28800000 1 48 48 1815.5 1944.4 7847931 9043277 29600000 1 50 49 1650.0 1596.6 5636323 7929164 30400000 1 51 51 1683.7 1573.3 5766323 19369146 31200000 1 52 52 1610.1 1669.8 9256111 9899107 32000000 1 53 53 1645.2 3081.0 7855010 6057257 32800000 1 54 55 1835.3 3122.0 6899141 6143875 33600000 1 56 56 1916.8 1734.8 10271967 6049509 34400000 1 57 57 3119.2 1630.8 11503274 13975417 35200000 1 58 58 1629.2 1695.7 6827225 6214248 36000000 1 60 60 1636.5 1695.4 38077664 16211067 36800000 1 61 61 1665.2 2069.1 19948817 9358494 37600000 1 62 62 1734.5 1931.5 26487196 8954836 38400000 1 63 63 1625.8 1654.0 6649289 9131844 39200000 1 65 65 1778.4 1663.3 11653376 7144960 40000000 1 66 66 1851.0 1935.6 8164470 11288753 40800000 1 67 67 3171.0 3431.6 12358380 6072820 41600000 1 69 69 1714.3 1954.3 13765035 9364495 42400000 1 70 70 1591.0 1681.8 18733304 7407689 43200000 1 71 71 1537.2 1642.8 19534908 6163018 44000000 1 72 72 1630.3 1641.2 23479883 10967509 44800000 1 74 74 1877.5 1651.9 8174965 9484587 45600000 1 75 75 3322.4 1653.6 14740938 7497831 46400000 1 76 76 1706.9 1840.6 10348550 23296562 47200000 1 77 78 1837.7 2515.3 13917543 14683192 48000000 1 79 79 1642.6 2368.6 14365759 6080942 48800000 1 80 80 1827.1 1655.2 9234312 7412406 49600000 1 81 81 1631.0 1858.7 7543970 18610881 50400000 1 82 82 1560.5 1865.0 21374219 6598771From the above table, when the same count files with same size are created, how FS is full is basically same.
2. FFSB test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1large_file_create
1 thread
- Trans/sec 28918.75 29014.48 +0.33%
- Throughput 113MB/sec 113MB/sec +0.0%
- %CPU 4.8% 5.1% +6.3%
- Trans/%CPU 602473.96 568911.37 -5.6%
8 threads
- Trans/sec 28480.37 28541.25 +0.2%
- Throughput 111MB/sec 111MB/sec +0.0%
- %CPU 5.6% 5.9% +5.4%
- Trans/%CPU 508578.04 483750 -4.9%
32 threads
- Trans/sec 25011.86 26992.32 +7.9%
- Throughput 97.7MB/sec 105MB/sec +7.5%
- %CPU 6.2% 7.1% +14.8%
- Trans/%CPU 403417.10 380173.52 -5.8%
large_file_seq_read
1 thread
- Trans/sec 35303.23 34838.02 -1.3%
- Throughput 138MB/sec 136MB/sec -1.4%
- %CPU 5.4% 5.4% +0.0%
- Trans/%CPU 653763.52 645148.52 -1.3%
8 threads
- Trans/sec 11902.82 11205.22 -5.9%
- Throughput 46.5MB/sec 43.8MB/sec -5.8%
- %CPU 2.1% 2.0% -4.8%
- Trans/%CPU 566800.95 560261 -1.2%
32 threads
- Trans/sec 5068.48 5316.36 +4.9%
- Throughput 19.8MB/sec 20.8MB/sec +5.1%
- %CPU 0.9% 1.0% +11.1%
- Trans/%CPU 563164.45 531636 -5.6%
random_write
1 thread
- Trans/sec 729.01 738.89 +1.4%
- Throughput 99.7MB/sec 101MB/sec +1.3%
- %CPU 0.1% 0.1% +0.0%
- Trans/%CPU 72901 73889 +1.4%
8 threads
- Trans/sec 714.56 714.57 +0.0%
- Throughput 97.7MB/sec 97.7MB/sec +0.0%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 35728 35728.5 +0.0%
32 threads
- Trans/sec 698.62 692.59 -0.9%
- Throughput 95.5MB/sec 94.7MB/sec -0.8%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 34931 34629.5 -0.9%
random_read
1 thread
- Trans/sec 225.49 227.03 +0.7%
- Throughput 902KB/sec 908KB/sec +0.7%
- %CPU 1.1% 1.1% +0.0%
- Trans/%CPU 20499.10 20639.10 +0.7%
8 threads
- Trans/sec 106.72 105.76 -0.9%
- Throughput 427KB/sec 423KB/sec -0.9%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2134.4 2115.2 -0.9%
32 threads
- Trans/sec 107.44 108.26 +0.8%
- Throughput 430KB/sec 433KB/sec +0.7%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2148.8 2165.2 +0.8%
mail_server
1 thread
- Trans/sec 681.67 732.66 +7.5%
- Throughput [read] 1.77MB/sec 1.99MB/sec +12.4%
- Throughput [write] 858KB/sec 887KB/sec +3.4%
- %CPU 0.6% 0.6% +0.0%
- Trans/%CPU 11361.17 12211 +7.5%
8 threads
- Trans/sec 630.48 597.08 -5.3%
- Throughput [read] 1.64MB/sec 1.54MB/sec -6.1%
- Throughput [write] 814KB/sec 784KB/sec -3.7%
- %CPU 0.6% 0.5% -16.7%
- Trans/%CPU 10508 11941.6 +13.6%
32 threads
- Trans/sec 598.68 566.05 -5.5%
- Throughput [read] 1.53MB/sec 1.5MB/sec -2.0%
- Throughput [write] 804KB/sec 705KB/sec -12.3%
- %CPU 0.7% 0.6% -14.2%
- Trans/%CPU 8552.57 9434.17 +10.3%3. Compilebench test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1intial create 114.81 MB/s 118.32 MB/s +3.1% create 11.98 MB/s 12.26 MB/s +2.3% patch 3.61 MB/s 3.66 MB/s +1.4% compile 46.40 MB/s 48.07 MB/s +3.6% clean 126.33 MB/s 128.75 MB/s +1.9% read tree 9.93 MB/s 9.71 MB/s -2.2% read compiled tree 17.19 MB/s 17.52 MB/s +1.9% delete tree 12.23 seconds 11.13 seconds -9.0% delete compiled tree 12.98 seconds 16.05 seconds +26.7% stat tree 7.03 seconds 5.51 seconds -21.6% stat compiled tree 12.19 seconds 9.06 seconds -25.7%Changelog:
- Solved 64 bits inode number issue. [David Sterba]
- Embed structhot_typein structfile_system_type[Darrick J. Wong]
- Cleanup Some issues [David Sterba]
- Use a static hot debugfs root [Greg KH]
- Rewritten debugfs support based onseq_fileoperation. [Dave Chinner]
- Refactored workqueue support. [Dave Chinner]
- Turn some Micro into be tunable [Zhiyong, Zheng Liu]
TIME_TO_KICK, andHEAT_UPDATE_DELAY
- Introduce hot func registering framework [Zhiyong]
- Remove global variable for hot tracking [Zhiyong]
- Add xfs hot tracking support [Dave Chinner]
- Add ext4 hot tracking support [Zheng Liu]
- Cleanedup a lot of other issues [Dave Chinner]
- Added memory shrinker [Dave Chinner]
- Converted to one workqueue to update map info periodically [Dave Chinner]
- Cleanedup a lot of other issues [Dave Chinner]
- Reduce new files and put all in fs/hot_tracking.[ch] [Dave Chinner]
- Add btrfs hot tracking support [Zhiyong]
- The first three patches can probably just be flattened into one. [Marco Stornelli , Dave Chinner]Zhi Yong Wu (16):
vfs: introduce some data structures
vfs: add init and cleanup functions
vfs: add I/O frequency update function
vfs: add two map arrays
vfs: add hooks to enable hot tracking
vfs: add temp calculation function
vfs: add map info update function
vfs: add aging function
vfs: add one work queue
vfs: add FS hot type support
vfs: register one shrinker
vfs: add one ioctl interface
vfs: add debugfs support
proc: add twohot_trackproc files
btrfs: add hot tracking support
vfs: add documentationDocumentation/filesystems/00-INDEX | 2 + Documentation/filesystems/hot_tracking.txt | 255 ++++++ fs/Makefile | 2 +- fs/btrfs/ctree.h | 1 + fs/btrfs/super.c | 22 +- fs/compat_ioctl.c | 5 + fs/dcache.c | 2 + fs/direct-io.c | 6 + fs/hot_tracking.c | 1345 ++++++++++++++++++++++++++++ fs/hot_tracking.h | 52 ++ fs/ioctl.c | 74 ++ include/linux/fs.h | 5 + include/linux/hot_tracking.h | 152 ++++ kernel/sysctl.c | 14 + mm/filemap.c | 6 + mm/page-writeback.c | 12 + mm/readahead.c | 7 + 17 files changed, 1960 insertions(+), 2 deletions(-) create mode 100644 Documentation/filesystems/hot_tracking.txt create mode 100644 fs/hot_tracking.c create mode 100644 fs/hot_tracking.h create mode 100644 include/linux/hot_tracking.h--
1.7.6.5
Signature · 3 lines
Regards, Zhi Yong Wu
Quoted 86 lines · On Thu, Dec 20, 2012 at 10:43 PM, <[email protected]> wrote:
From: Zhi Yong Wu <[email protected]>
HI, guys,
This patchset has been done scalability or performance tests
byfs_mark, ffsb and compilebench.
I have done the perf testing on Linux 3.7.0-rc8+ with Intel(R) Core(TM)
i7-3770 CPU @ 3.40GHz with 8 CPUs, 16G ram and 260G disk.Any comments or ideas are appreciated, thanks.
NOTE:
The patchset can be obtained via my kernel dev git on github:
git://github.com/wuzhy/kernel.githot_tracking
If you're interested, you can also review them via
https://github.com/wuzhy/kernel/commits/hot_trackingFor more info, please check hot_tracking.txt in Documentation
Below is the perf testing report:
1.
fs_marktestw/o: without hot tracking
w/ : with hot trackingCount Size FSUse% Files/sec App Overhead
w/o w/ w/o w/ w/o w/
800000 1 2 3 13756.4 32144.9 5350627 5436291 1600000 1 4 5 1163.4 1799.3 20848119 21708216 2400000 1 6 6 1360.8 1252.5 6798705 8715322 3200000 1 8 8 1600.1 1196.3 5751129 6013792 4000000 1 9 9 1071.4 1191.2 17204725 26786369 4800000 1 10 10 1483.5 1447.9 19555541 8383046 5600000 1 11 11 1457.9 1699.5 5783588 10074681 6400000 1 12 13 1658.8 1628.5 6992697 6185551 7200000 1 14 14 1662.4 1857.1 5796793 13772592 8000000 1 15 15 2930.0 2653.8 12431682 6152573 8800000 1 16 17 1630.8 1665.0 7666719 13682765 9600000 1 18 18 1530.3 1583.9 5823644 10171644 10400000 1 19 19 1437.9 1798.6 20935224 6048083 11200000 1 20 20 1529.0 1550.6 6647450 6003151 12000000 1 21 22 1558.6 1501.8 12539509 18144939 12800000 1 23 23 1644.2 1432.1 7074419 28101975 13600000 1 24 24 1753.6 1650.2 7164297 20888972 14400000 1 25 25 2750.0 1483.9 12756692 7441225 15200000 1 27 27 1551.1 1514.3 5741066 8250443 16000000 1 28 28 1610.8 1635.9 72193860 8545285 16800000 1 29 29 1646.7 1907.7 8945856 11703513 17600000 1 30 31 1496.6 2722.3 5858961 8989393 18400000 1 32 32 1457.7 1565.7 10914475 26504660 19200000 1 33 33 1437.6 1518.7 6708975 213303618 20000000 1 34 34 1825.4 1521.1 5722086 12490907 20800000 1 36 35 1718.4 1611.5 5873290 17942534 21600000 1 37 37 2152.6 1536.9 113050627 8717940 22400000 1 38 38 2443.7 1788.2 7398122 19834765 23200000 1 39 39 1518.5 1587.6 5770959 10134882 24000000 1 41 41 1536.8 2164.0 5751248 7214626 24800000 1 42 42 1576.6 2939.4 7390314 6070271 25600000 1 43 43 1707.4 1535.9 11075939 6052896 26400000 1 44 44 1522.5 1563.1 10142987 22549898 27200000 1 46 46 1827.4 1608.5 11613016 24828125 28000000 1 47 47 3420.5 1741.9 8059985 16599156 28800000 1 48 48 1815.5 1944.4 7847931 9043277 29600000 1 50 49 1650.0 1596.6 5636323 7929164 30400000 1 51 51 1683.7 1573.3 5766323 19369146 31200000 1 52 52 1610.1 1669.8 9256111 9899107 32000000 1 53 53 1645.2 3081.0 7855010 6057257 32800000 1 54 55 1835.3 3122.0 6899141 6143875 33600000 1 56 56 1916.8 1734.8 10271967 6049509 34400000 1 57 57 3119.2 1630.8 11503274 13975417 35200000 1 58 58 1629.2 1695.7 6827225 6214248 36000000 1 60 60 1636.5 1695.4 38077664 16211067 36800000 1 61 61 1665.2 2069.1 19948817 9358494 37600000 1 62 62 1734.5 1931.5 26487196 8954836 38400000 1 63 63 1625.8 1654.0 6649289 9131844 39200000 1 65 65 1778.4 1663.3 11653376 7144960 40000000 1 66 66 1851.0 1935.6 8164470 11288753 40800000 1 67 67 3171.0 3431.6 12358380 6072820 41600000 1 69 69 1714.3 1954.3 13765035 9364495 42400000 1 70 70 1591.0 1681.8 18733304 7407689 43200000 1 71 71 1537.2 1642.8 19534908 6163018 44000000 1 72 72 1630.3 1641.2 23479883 10967509
Quoted 9 lines
44800000 1 74 74 1877.5 1651.9 8174965 9484587 45600000 1 75 75 3322.4 1653.6 14740938 7497831 46400000 1 76 76 1706.9 1840.6 10348550 23296562 47200000 1 77 78 1837.7 2515.3 13917543 14683192 48000000 1 79 79 1642.6 2368.6 14365759 6080942 48800000 1 80 80 1827.1 1655.2 9234312 7412406 49600000 1 81 81 1631.0 1858.7 7543970 18610881 50400000 1 82 82 1560.5 1865.0 21374219 6598771
For its memory this test eats up, 50 millions files only occupy about 240MB of 16GB total memory based on the info below. [root@localhost ~]# cat /proc/slabinfo | grep hothot_range_item 5051 5190 136 30 1 : tunables 0 0
0 : slabdata 173 173 0hot_inode_item 1677552 1688960 144 28 1 : tunables 0
0 0 : slabdata 60320 60320 0
[root@localhost fs_mark-3.3]# slabtop
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
1688960 1677552 99% 0.14K 60320 28 241280K hot_inode_item
[root@localhost ~]# free -m
total used free shared buffers cached
Mem: 15989 15353 636 0 100 11508
-/+ buffers/cache: 3744 12245
Swap: 18047 0 18047
Quoted 178 lines
From the above table, when the same count files with same size are created, how FS is full is basically same.
2. FFSB test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1large_file_create
1 thread
- Trans/sec 28918.75 29014.48 +0.33%
- Throughput 113MB/sec 113MB/sec +0.0%
- %CPU 4.8% 5.1% +6.3%
- Trans/%CPU 602473.96 568911.37 -5.6%
8 threads
- Trans/sec 28480.37 28541.25 +0.2%
- Throughput 111MB/sec 111MB/sec +0.0%
- %CPU 5.6% 5.9% +5.4%
- Trans/%CPU 508578.04 483750 -4.9%
32 threads
- Trans/sec 25011.86 26992.32 +7.9%
- Throughput 97.7MB/sec 105MB/sec +7.5%
- %CPU 6.2% 7.1% +14.8%
- Trans/%CPU 403417.10 380173.52 -5.8%
large_file_seq_read
1 thread
- Trans/sec 35303.23 34838.02 -1.3%
- Throughput 138MB/sec 136MB/sec -1.4%
- %CPU 5.4% 5.4% +0.0%
- Trans/%CPU 653763.52 645148.52 -1.3%
8 threads
- Trans/sec 11902.82 11205.22 -5.9%
- Throughput 46.5MB/sec 43.8MB/sec -5.8%
- %CPU 2.1% 2.0% -4.8%
- Trans/%CPU 566800.95 560261 -1.2%
32 threads
- Trans/sec 5068.48 5316.36 +4.9%
- Throughput 19.8MB/sec 20.8MB/sec +5.1%
- %CPU 0.9% 1.0% +11.1%
- Trans/%CPU 563164.45 531636 -5.6%
random_write
1 thread
- Trans/sec 729.01 738.89 +1.4%
- Throughput 99.7MB/sec 101MB/sec +1.3%
- %CPU 0.1% 0.1% +0.0%
- Trans/%CPU 72901 73889 +1.4%
8 threads
- Trans/sec 714.56 714.57 +0.0%
- Throughput 97.7MB/sec 97.7MB/sec +0.0%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 35728 35728.5 +0.0%
32 threads
- Trans/sec 698.62 692.59 -0.9%
- Throughput 95.5MB/sec 94.7MB/sec -0.8%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 34931 34629.5 -0.9%
random_read
1 thread
- Trans/sec 225.49 227.03 +0.7%
- Throughput 902KB/sec 908KB/sec +0.7%
- %CPU 1.1% 1.1% +0.0%
- Trans/%CPU 20499.10 20639.10 +0.7%
8 threads
- Trans/sec 106.72 105.76 -0.9%
- Throughput 427KB/sec 423KB/sec -0.9%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2134.4 2115.2 -0.9%
32 threads
- Trans/sec 107.44 108.26 +0.8%
- Throughput 430KB/sec 433KB/sec +0.7%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2148.8 2165.2 +0.8%
mail_server
1 thread
- Trans/sec 681.67 732.66 +7.5%
- Throughput [read] 1.77MB/sec 1.99MB/sec +12.4%
- Throughput [write] 858KB/sec 887KB/sec +3.4%
- %CPU 0.6% 0.6% +0.0%
- Trans/%CPU 11361.17 12211 +7.5%
8 threads
- Trans/sec 630.48 597.08 -5.3%
- Throughput [read] 1.64MB/sec 1.54MB/sec -6.1%
- Throughput [write] 814KB/sec 784KB/sec -3.7%
- %CPU 0.6% 0.5% -16.7%
- Trans/%CPU 10508 11941.6 +13.6%
32 threads
- Trans/sec 598.68 566.05 -5.5%
- Throughput [read] 1.53MB/sec 1.5MB/sec -2.0%
- Throughput [write] 804KB/sec 705KB/sec -12.3%
- %CPU 0.7% 0.6% -14.2%
- Trans/%CPU 8552.57 9434.17 +10.3%3. Compilebench test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1intial create 114.81 MB/s 118.32 MB/s +3.1% create 11.98 MB/s 12.26 MB/s +2.3% patch 3.61 MB/s 3.66 MB/s +1.4% compile 46.40 MB/s 48.07 MB/s +3.6% clean 126.33 MB/s 128.75 MB/s +1.9% read tree 9.93 MB/s 9.71 MB/s -2.2% read compiled tree 17.19 MB/s 17.52 MB/s +1.9% delete tree 12.23 seconds 11.13 seconds -9.0% delete compiled tree 12.98 seconds 16.05 seconds +26.7% stat tree 7.03 seconds 5.51 seconds -21.6% stat compiled tree 12.19 seconds 9.06 seconds -25.7%Changelog:
- Solved 64 bits inode number issue. [David Sterba]
- Embed structhot_typein structfile_system_type[Darrick J. Wong]
- Cleanup Some issues [David Sterba]
- Use a static hot debugfs root [Greg KH]
- Rewritten debugfs support based onseq_fileoperation. [Dave Chinner]
- Refactored workqueue support. [Dave Chinner]
- Turn some Micro into be tunable [Zhiyong, Zheng Liu]
TIME_TO_KICK, andHEAT_UPDATE_DELAY
- Introduce hot func registering framework [Zhiyong]
- Remove global variable for hot tracking [Zhiyong]
- Add xfs hot tracking support [Dave Chinner]
- Add ext4 hot tracking support [Zheng Liu]
- Cleanedup a lot of other issues [Dave Chinner]
- Added memory shrinker [Dave Chinner]
- Converted to one workqueue to update map info periodically [Dave Chinner]
- Cleanedup a lot of other issues [Dave Chinner]
- Reduce new files and put all in fs/hot_tracking.[ch] [Dave Chinner]
- Add btrfs hot tracking support [Zhiyong]
- The first three patches can probably just be flattened into one. [Marco Stornelli , Dave Chinner]Zhi Yong Wu (16):
vfs: introduce some data structures
vfs: add init and cleanup functions
vfs: add I/O frequency update function
vfs: add two map arrays
vfs: add hooks to enable hot tracking
vfs: add temp calculation function
vfs: add map info update function
vfs: add aging function
vfs: add one work queue
vfs: add FS hot type support
vfs: register one shrinker
vfs: add one ioctl interface
vfs: add debugfs support
proc: add twohot_trackproc files
btrfs: add hot tracking support
vfs: add documentationDocumentation/filesystems/00-INDEX | 2 + Documentation/filesystems/hot_tracking.txt | 255 ++++++ fs/Makefile | 2 +- fs/btrfs/ctree.h | 1 + fs/btrfs/super.c | 22 +- fs/compat_ioctl.c | 5 + fs/dcache.c | 2 + fs/direct-io.c | 6 + fs/hot_tracking.c | 1345 ++++++++++++++++++++++++++++ fs/hot_tracking.h | 52 ++ fs/ioctl.c | 74 ++ include/linux/fs.h | 5 + include/linux/hot_tracking.h | 152 ++++ kernel/sysctl.c | 14 + mm/filemap.c | 6 + mm/page-writeback.c | 12 + mm/readahead.c | 7 + 17 files changed, 1960 insertions(+), 2 deletions(-) create mode 100644 Documentation/filesystems/hot_tracking.txt create mode 100644 fs/hot_tracking.c create mode 100644 fs/hot_tracking.h create mode 100644 include/linux/hot_tracking.h--
1.7.6.5
Signature · 3 lines
Regards, Zhi Yong Wu
ping? any comments?
Quoted 273 lines · On Thu, Dec 20, 2012 at 10:43 PM, <[email protected]> wrote:
From: Zhi Yong Wu <[email protected]>
HI, guys,
This patchset has been done scalability or performance tests
byfs_mark, ffsb and compilebench.
I have done the perf testing on Linux 3.7.0-rc8+ with Intel(R) Core(TM)
i7-3770 CPU @ 3.40GHz with 8 CPUs, 16G ram and 260G disk.Any comments or ideas are appreciated, thanks.
NOTE:
The patchset can be obtained via my kernel dev git on github:
git://github.com/wuzhy/kernel.githot_tracking
If you're interested, you can also review them via
https://github.com/wuzhy/kernel/commits/hot_trackingFor more info, please check hot_tracking.txt in Documentation
Below is the perf testing report:
1.
fs_marktestw/o: without hot tracking
w/ : with hot trackingCount Size FSUse% Files/sec App Overhead
w/o w/ w/o w/ w/o w/
800000 1 2 3 13756.4 32144.9 5350627 5436291 1600000 1 4 5 1163.4 1799.3 20848119 21708216 2400000 1 6 6 1360.8 1252.5 6798705 8715322 3200000 1 8 8 1600.1 1196.3 5751129 6013792 4000000 1 9 9 1071.4 1191.2 17204725 26786369 4800000 1 10 10 1483.5 1447.9 19555541 8383046 5600000 1 11 11 1457.9 1699.5 5783588 10074681 6400000 1 12 13 1658.8 1628.5 6992697 6185551 7200000 1 14 14 1662.4 1857.1 5796793 13772592 8000000 1 15 15 2930.0 2653.8 12431682 6152573 8800000 1 16 17 1630.8 1665.0 7666719 13682765 9600000 1 18 18 1530.3 1583.9 5823644 10171644 10400000 1 19 19 1437.9 1798.6 20935224 6048083 11200000 1 20 20 1529.0 1550.6 6647450 6003151 12000000 1 21 22 1558.6 1501.8 12539509 18144939 12800000 1 23 23 1644.2 1432.1 7074419 28101975 13600000 1 24 24 1753.6 1650.2 7164297 20888972 14400000 1 25 25 2750.0 1483.9 12756692 7441225 15200000 1 27 27 1551.1 1514.3 5741066 8250443 16000000 1 28 28 1610.8 1635.9 72193860 8545285 16800000 1 29 29 1646.7 1907.7 8945856 11703513 17600000 1 30 31 1496.6 2722.3 5858961 8989393 18400000 1 32 32 1457.7 1565.7 10914475 26504660 19200000 1 33 33 1437.6 1518.7 6708975 213303618 20000000 1 34 34 1825.4 1521.1 5722086 12490907 20800000 1 36 35 1718.4 1611.5 5873290 17942534 21600000 1 37 37 2152.6 1536.9 113050627 8717940 22400000 1 38 38 2443.7 1788.2 7398122 19834765 23200000 1 39 39 1518.5 1587.6 5770959 10134882 24000000 1 41 41 1536.8 2164.0 5751248 7214626 24800000 1 42 42 1576.6 2939.4 7390314 6070271 25600000 1 43 43 1707.4 1535.9 11075939 6052896 26400000 1 44 44 1522.5 1563.1 10142987 22549898 27200000 1 46 46 1827.4 1608.5 11613016 24828125 28000000 1 47 47 3420.5 1741.9 8059985 16599156 28800000 1 48 48 1815.5 1944.4 7847931 9043277 29600000 1 50 49 1650.0 1596.6 5636323 7929164 30400000 1 51 51 1683.7 1573.3 5766323 19369146 31200000 1 52 52 1610.1 1669.8 9256111 9899107 32000000 1 53 53 1645.2 3081.0 7855010 6057257 32800000 1 54 55 1835.3 3122.0 6899141 6143875 33600000 1 56 56 1916.8 1734.8 10271967 6049509 34400000 1 57 57 3119.2 1630.8 11503274 13975417 35200000 1 58 58 1629.2 1695.7 6827225 6214248 36000000 1 60 60 1636.5 1695.4 38077664 16211067 36800000 1 61 61 1665.2 2069.1 19948817 9358494 37600000 1 62 62 1734.5 1931.5 26487196 8954836 38400000 1 63 63 1625.8 1654.0 6649289 9131844 39200000 1 65 65 1778.4 1663.3 11653376 7144960 40000000 1 66 66 1851.0 1935.6 8164470 11288753 40800000 1 67 67 3171.0 3431.6 12358380 6072820 41600000 1 69 69 1714.3 1954.3 13765035 9364495 42400000 1 70 70 1591.0 1681.8 18733304 7407689 43200000 1 71 71 1537.2 1642.8 19534908 6163018 44000000 1 72 72 1630.3 1641.2 23479883 10967509 44800000 1 74 74 1877.5 1651.9 8174965 9484587 45600000 1 75 75 3322.4 1653.6 14740938 7497831 46400000 1 76 76 1706.9 1840.6 10348550 23296562 47200000 1 77 78 1837.7 2515.3 13917543 14683192 48000000 1 79 79 1642.6 2368.6 14365759 6080942 48800000 1 80 80 1827.1 1655.2 9234312 7412406 49600000 1 81 81 1631.0 1858.7 7543970 18610881 50400000 1 82 82 1560.5 1865.0 21374219 6598771From the above table, when the same count files with same size are created, how FS is full is basically same.
2. FFSB test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1large_file_create
1 thread
- Trans/sec 28918.75 29014.48 +0.33%
- Throughput 113MB/sec 113MB/sec +0.0%
- %CPU 4.8% 5.1% +6.3%
- Trans/%CPU 602473.96 568911.37 -5.6%
8 threads
- Trans/sec 28480.37 28541.25 +0.2%
- Throughput 111MB/sec 111MB/sec +0.0%
- %CPU 5.6% 5.9% +5.4%
- Trans/%CPU 508578.04 483750 -4.9%
32 threads
- Trans/sec 25011.86 26992.32 +7.9%
- Throughput 97.7MB/sec 105MB/sec +7.5%
- %CPU 6.2% 7.1% +14.8%
- Trans/%CPU 403417.10 380173.52 -5.8%
large_file_seq_read
1 thread
- Trans/sec 35303.23 34838.02 -1.3%
- Throughput 138MB/sec 136MB/sec -1.4%
- %CPU 5.4% 5.4% +0.0%
- Trans/%CPU 653763.52 645148.52 -1.3%
8 threads
- Trans/sec 11902.82 11205.22 -5.9%
- Throughput 46.5MB/sec 43.8MB/sec -5.8%
- %CPU 2.1% 2.0% -4.8%
- Trans/%CPU 566800.95 560261 -1.2%
32 threads
- Trans/sec 5068.48 5316.36 +4.9%
- Throughput 19.8MB/sec 20.8MB/sec +5.1%
- %CPU 0.9% 1.0% +11.1%
- Trans/%CPU 563164.45 531636 -5.6%
random_write
1 thread
- Trans/sec 729.01 738.89 +1.4%
- Throughput 99.7MB/sec 101MB/sec +1.3%
- %CPU 0.1% 0.1% +0.0%
- Trans/%CPU 72901 73889 +1.4%
8 threads
- Trans/sec 714.56 714.57 +0.0%
- Throughput 97.7MB/sec 97.7MB/sec +0.0%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 35728 35728.5 +0.0%
32 threads
- Trans/sec 698.62 692.59 -0.9%
- Throughput 95.5MB/sec 94.7MB/sec -0.8%
- %CPU 0.2% 0.2% +0.0%
- Trans/%CPU 34931 34629.5 -0.9%
random_read
1 thread
- Trans/sec 225.49 227.03 +0.7%
- Throughput 902KB/sec 908KB/sec +0.7%
- %CPU 1.1% 1.1% +0.0%
- Trans/%CPU 20499.10 20639.10 +0.7%
8 threads
- Trans/sec 106.72 105.76 -0.9%
- Throughput 427KB/sec 423KB/sec -0.9%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2134.4 2115.2 -0.9%
32 threads
- Trans/sec 107.44 108.26 +0.8%
- Throughput 430KB/sec 433KB/sec +0.7%
- %CPU 0.5% 0.5% +0.0%
- Trans/%CPU 2148.8 2165.2 +0.8%
mail_server
1 thread
- Trans/sec 681.67 732.66 +7.5%
- Throughput [read] 1.77MB/sec 1.99MB/sec +12.4%
- Throughput [write] 858KB/sec 887KB/sec +3.4%
- %CPU 0.6% 0.6% +0.0%
- Trans/%CPU 11361.17 12211 +7.5%
8 threads
- Trans/sec 630.48 597.08 -5.3%
- Throughput [read] 1.64MB/sec 1.54MB/sec -6.1%
- Throughput [write] 814KB/sec 784KB/sec -3.7%
- %CPU 0.6% 0.5% -16.7%
- Trans/%CPU 10508 11941.6 +13.6%
32 threads
- Trans/sec 598.68 566.05 -5.5%
- Throughput [read] 1.53MB/sec 1.5MB/sec -2.0%
- Throughput [write] 804KB/sec 705KB/sec -12.3%
- %CPU 0.7% 0.6% -14.2%
- Trans/%CPU 8552.57 9434.17 +10.3%3. Compilebench test
w/o hot tracking w/ hot tracking ratio
v1 v2 (v2-v1)/v1intial create 114.81 MB/s 118.32 MB/s +3.1% create 11.98 MB/s 12.26 MB/s +2.3% patch 3.61 MB/s 3.66 MB/s +1.4% compile 46.40 MB/s 48.07 MB/s +3.6% clean 126.33 MB/s 128.75 MB/s +1.9% read tree 9.93 MB/s 9.71 MB/s -2.2% read compiled tree 17.19 MB/s 17.52 MB/s +1.9% delete tree 12.23 seconds 11.13 seconds -9.0% delete compiled tree 12.98 seconds 16.05 seconds +26.7% stat tree 7.03 seconds 5.51 seconds -21.6% stat compiled tree 12.19 seconds 9.06 seconds -25.7%Changelog:
- Solved 64 bits inode number issue. [David Sterba]
- Embed structhot_typein structfile_system_type[Darrick J. Wong]
- Cleanup Some issues [David Sterba]
- Use a static hot debugfs root [Greg KH]
- Rewritten debugfs support based onseq_fileoperation. [Dave Chinner]
- Refactored workqueue support. [Dave Chinner]
- Turn some Micro into be tunable [Zhiyong, Zheng Liu]
TIME_TO_KICK, andHEAT_UPDATE_DELAY
- Introduce hot func registering framework [Zhiyong]
- Remove global variable for hot tracking [Zhiyong]
- Add xfs hot tracking support [Dave Chinner]
- Add ext4 hot tracking support [Zheng Liu]
- Cleanedup a lot of other issues [Dave Chinner]
- Added memory shrinker [Dave Chinner]
- Converted to one workqueue to update map info periodically [Dave Chinner]
- Cleanedup a lot of other issues [Dave Chinner]
- Reduce new files and put all in fs/hot_tracking.[ch] [Dave Chinner]
- Add btrfs hot tracking support [Zhiyong]
- The first three patches can probably just be flattened into one. [Marco Stornelli , Dave Chinner]Zhi Yong Wu (16):
vfs: introduce some data structures
vfs: add init and cleanup functions
vfs: add I/O frequency update function
vfs: add two map arrays
vfs: add hooks to enable hot tracking
vfs: add temp calculation function
vfs: add map info update function
vfs: add aging function
vfs: add one work queue
vfs: add FS hot type support
vfs: register one shrinker
vfs: add one ioctl interface
vfs: add debugfs support
proc: add twohot_trackproc files
btrfs: add hot tracking support
vfs: add documentationDocumentation/filesystems/00-INDEX | 2 + Documentation/filesystems/hot_tracking.txt | 255 ++++++ fs/Makefile | 2 +- fs/btrfs/ctree.h | 1 + fs/btrfs/super.c | 22 +- fs/compat_ioctl.c | 5 + fs/dcache.c | 2 + fs/direct-io.c | 6 + fs/hot_tracking.c | 1345 ++++++++++++++++++++++++++++ fs/hot_tracking.h | 52 ++ fs/ioctl.c | 74 ++ include/linux/fs.h | 5 + include/linux/hot_tracking.h | 152 ++++ kernel/sysctl.c | 14 + mm/filemap.c | 6 + mm/page-writeback.c | 12 + mm/readahead.c | 7 + 17 files changed, 1960 insertions(+), 2 deletions(-) create mode 100644 Documentation/filesystems/hot_tracking.txt create mode 100644 fs/hot_tracking.c create mode 100644 fs/hot_tracking.h create mode 100644 include/linux/hot_tracking.h--
1.7.6.5
Signature · 3 lines
Regards, Zhi Yong Wu
Quoted 1 line · Zhi Yong Wu
ping? any comments?
Sorry, I don't have as much time as I'd like to continue with this patchset.