Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-07 Thread Zhi Yong Wu
On Thu, Nov 8, 2012 at 2:49 AM, Darrick J. Wong  wrote:
> On Wed, Nov 07, 2012 at 04:27:05PM +0800, Zhi Yong Wu wrote:
>> On Wed, Nov 7, 2012 at 6:45 AM, Darrick J. Wong  
>> wrote:
>> > On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
>> >> From: Zhi Yong Wu 
>> >>
>> >>   Add some util helpers to update access frequencies
>> >> for one file or its range.
>> >>
>> >> Signed-off-by: Zhi Yong Wu 
>> >> ---
>> >>  fs/hot_tracking.c|  179 
>> >> ++
>> >>  fs/hot_tracking.h|7 ++
>> >>  include/linux/hot_tracking.h |2 +
>> >>  3 files changed, 188 insertions(+), 0 deletions(-)
>> >>
>> >> diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
>> >> index 68591f0..0a7d9a3 100644
>> >> --- a/fs/hot_tracking.c
>> >> +++ b/fs/hot_tracking.c
>> >> @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info 
>> >> *root)
>> >>   }
>> >>  }
>> >>
>> >> +struct hot_inode_item
>> >> +*hot_inode_item_find(struct hot_info *root, u64 ino)
>> >> +{
>> >> + struct hot_inode_item *he;
>> >> + int ret;
>> >> +
>> >> +again:
>> >> + spin_lock(>lock);
>> >> + he = radix_tree_lookup(>hot_inode_tree, ino);
>> >> + if (he) {
>> >> + kref_get(>hot_inode.refs);
>> >> + spin_unlock(>lock);
>> >> + return he;
>> >> + }
>> >> + spin_unlock(>lock);
>> >> +
>> >> + he = kmem_cache_zalloc(hot_inode_item_cachep,
>> >> + GFP_KERNEL | GFP_NOFS);
>> >> + if (!he)
>> >> + return ERR_PTR(-ENOMEM);
>> >> +
>> >> + hot_inode_item_init(he, ino, >hot_inode_tree);
>> >> +
>> >> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
>> >> + if (ret) {
>> >> + kmem_cache_free(hot_inode_item_cachep, he);
>> >> + return ERR_PTR(ret);
>> >> + }
>> >> +
>> >> + spin_lock(>lock);
>> >> + ret = radix_tree_insert(>hot_inode_tree, ino, he);
>> >> + if (ret == -EEXIST) {
>> >> + kmem_cache_free(hot_inode_item_cachep, he);
>> >> + spin_unlock(>lock);
>> >> + radix_tree_preload_end();
>> >> + goto again;
>> >> + }
>> >> + spin_unlock(>lock);
>> >> + radix_tree_preload_end();
>> >> +
>> >> + kref_get(>hot_inode.refs);
>> >> + return he;
>> >> +}
>> >> +EXPORT_SYMBOL_GPL(hot_inode_item_find);
>> >> +
>> >> +static struct hot_range_item
>> >> +*hot_range_item_find(struct hot_inode_item *he,
>> >> + u32 start)
>> >> +{
>> >> + struct hot_range_item *hr;
>> >> + int ret;
>> >> +
>> >> +again:
>> >> + spin_lock(>lock);
>> >> + hr = radix_tree_lookup(>hot_range_tree, start);
>> >> + if (hr) {
>> >> + kref_get(>hot_range.refs);
>> >> + spin_unlock(>lock);
>> >> + return hr;
>> >> + }
>> >> + spin_unlock(>lock);
>> >> +
>> >> + hr = kmem_cache_zalloc(hot_range_item_cachep,
>> >> + GFP_KERNEL | GFP_NOFS);
>> >> + if (!hr)
>> >> + return ERR_PTR(-ENOMEM);
>> >> +
>> >> + hot_range_item_init(hr, start, he);
>> >> +
>> >> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
>> >> + if (ret) {
>> >> + kmem_cache_free(hot_range_item_cachep, hr);
>> >> + return ERR_PTR(ret);
>> >> + }
>> >> +
>> >> + spin_lock(>lock);
>> >> + ret = radix_tree_insert(>hot_range_tree, start, hr);
>> >> + if (ret == -EEXIST) {
>> >> + kmem_cache_free(hot_range_item_cachep, hr);
>> >> + spin_unlock(>lock);
>> >> + radix_tree_preload_end();
>> >> + goto again;
>> >> + }
>> >> + spin_unlock(>lock);
>> >> + radix_tree_preload_end();
>> >> +
>> >> + kref_get(>hot_range.refs);
>> >> + return hr;
>> >> +}
>> >> +
>> >> +/*
>> >> + * This function does the actual work of updating
>> >> + * the frequency numbers, whatever they turn out to be.
>> >> + */
>> >> +static u64 hot_average_update(struct timespec old_atime,
>> >> + struct timespec cur_time, u64 old_avg)
>> >> +{
>> >> + struct timespec delta_ts;
>> >> + u64 new_avg;
>> >> + u64 new_delta;
>> >> +
>> >> + delta_ts = timespec_sub(cur_time, old_atime);
>> >> + new_delta = timespec_to_ns(_ts) >> FREQ_POWER;
>> >> +
>> >> + new_avg = (old_avg << FREQ_POWER) - old_avg + new_delta;
>> >> + new_avg = new_avg >> FREQ_POWER;
>> >> +
>> >> + return new_avg;
>> >> +}
>> >> +
>> >> +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;
>> >> + freq_data->avg_delta_writes = hot_average_update(
>> >> + freq_data->last_write_time,
>> >> + cur_time,
>> >> + 

Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-07 Thread Darrick J. Wong
On Wed, Nov 07, 2012 at 04:27:05PM +0800, Zhi Yong Wu wrote:
> On Wed, Nov 7, 2012 at 6:45 AM, Darrick J. Wong  
> wrote:
> > On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
> >> From: Zhi Yong Wu 
> >>
> >>   Add some util helpers to update access frequencies
> >> for one file or its range.
> >>
> >> Signed-off-by: Zhi Yong Wu 
> >> ---
> >>  fs/hot_tracking.c|  179 
> >> ++
> >>  fs/hot_tracking.h|7 ++
> >>  include/linux/hot_tracking.h |2 +
> >>  3 files changed, 188 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
> >> index 68591f0..0a7d9a3 100644
> >> --- a/fs/hot_tracking.c
> >> +++ b/fs/hot_tracking.c
> >> @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info 
> >> *root)
> >>   }
> >>  }
> >>
> >> +struct hot_inode_item
> >> +*hot_inode_item_find(struct hot_info *root, u64 ino)
> >> +{
> >> + struct hot_inode_item *he;
> >> + int ret;
> >> +
> >> +again:
> >> + spin_lock(>lock);
> >> + he = radix_tree_lookup(>hot_inode_tree, ino);
> >> + if (he) {
> >> + kref_get(>hot_inode.refs);
> >> + spin_unlock(>lock);
> >> + return he;
> >> + }
> >> + spin_unlock(>lock);
> >> +
> >> + he = kmem_cache_zalloc(hot_inode_item_cachep,
> >> + GFP_KERNEL | GFP_NOFS);
> >> + if (!he)
> >> + return ERR_PTR(-ENOMEM);
> >> +
> >> + hot_inode_item_init(he, ino, >hot_inode_tree);
> >> +
> >> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
> >> + if (ret) {
> >> + kmem_cache_free(hot_inode_item_cachep, he);
> >> + return ERR_PTR(ret);
> >> + }
> >> +
> >> + spin_lock(>lock);
> >> + ret = radix_tree_insert(>hot_inode_tree, ino, he);
> >> + if (ret == -EEXIST) {
> >> + kmem_cache_free(hot_inode_item_cachep, he);
> >> + spin_unlock(>lock);
> >> + radix_tree_preload_end();
> >> + goto again;
> >> + }
> >> + spin_unlock(>lock);
> >> + radix_tree_preload_end();
> >> +
> >> + kref_get(>hot_inode.refs);
> >> + return he;
> >> +}
> >> +EXPORT_SYMBOL_GPL(hot_inode_item_find);
> >> +
> >> +static struct hot_range_item
> >> +*hot_range_item_find(struct hot_inode_item *he,
> >> + u32 start)
> >> +{
> >> + struct hot_range_item *hr;
> >> + int ret;
> >> +
> >> +again:
> >> + spin_lock(>lock);
> >> + hr = radix_tree_lookup(>hot_range_tree, start);
> >> + if (hr) {
> >> + kref_get(>hot_range.refs);
> >> + spin_unlock(>lock);
> >> + return hr;
> >> + }
> >> + spin_unlock(>lock);
> >> +
> >> + hr = kmem_cache_zalloc(hot_range_item_cachep,
> >> + GFP_KERNEL | GFP_NOFS);
> >> + if (!hr)
> >> + return ERR_PTR(-ENOMEM);
> >> +
> >> + hot_range_item_init(hr, start, he);
> >> +
> >> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
> >> + if (ret) {
> >> + kmem_cache_free(hot_range_item_cachep, hr);
> >> + return ERR_PTR(ret);
> >> + }
> >> +
> >> + spin_lock(>lock);
> >> + ret = radix_tree_insert(>hot_range_tree, start, hr);
> >> + if (ret == -EEXIST) {
> >> + kmem_cache_free(hot_range_item_cachep, hr);
> >> + spin_unlock(>lock);
> >> + radix_tree_preload_end();
> >> + goto again;
> >> + }
> >> + spin_unlock(>lock);
> >> + radix_tree_preload_end();
> >> +
> >> + kref_get(>hot_range.refs);
> >> + return hr;
> >> +}
> >> +
> >> +/*
> >> + * This function does the actual work of updating
> >> + * the frequency numbers, whatever they turn out to be.
> >> + */
> >> +static u64 hot_average_update(struct timespec old_atime,
> >> + struct timespec cur_time, u64 old_avg)
> >> +{
> >> + struct timespec delta_ts;
> >> + u64 new_avg;
> >> + u64 new_delta;
> >> +
> >> + delta_ts = timespec_sub(cur_time, old_atime);
> >> + new_delta = timespec_to_ns(_ts) >> FREQ_POWER;
> >> +
> >> + new_avg = (old_avg << FREQ_POWER) - old_avg + new_delta;
> >> + new_avg = new_avg >> FREQ_POWER;
> >> +
> >> + return new_avg;
> >> +}
> >> +
> >> +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;
> >> + freq_data->avg_delta_writes = hot_average_update(
> >> + 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;
> >> + freq_data->avg_delta_reads = 

Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-07 Thread Zhi Yong Wu
On Wed, Nov 7, 2012 at 6:45 AM, Darrick J. Wong  wrote:
> On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
>> From: Zhi Yong Wu 
>>
>>   Add some util helpers to update access frequencies
>> for one file or its range.
>>
>> Signed-off-by: Zhi Yong Wu 
>> ---
>>  fs/hot_tracking.c|  179 
>> ++
>>  fs/hot_tracking.h|7 ++
>>  include/linux/hot_tracking.h |2 +
>>  3 files changed, 188 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
>> index 68591f0..0a7d9a3 100644
>> --- a/fs/hot_tracking.c
>> +++ b/fs/hot_tracking.c
>> @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
>>   }
>>  }
>>
>> +struct hot_inode_item
>> +*hot_inode_item_find(struct hot_info *root, u64 ino)
>> +{
>> + struct hot_inode_item *he;
>> + int ret;
>> +
>> +again:
>> + spin_lock(>lock);
>> + he = radix_tree_lookup(>hot_inode_tree, ino);
>> + if (he) {
>> + kref_get(>hot_inode.refs);
>> + spin_unlock(>lock);
>> + return he;
>> + }
>> + spin_unlock(>lock);
>> +
>> + he = kmem_cache_zalloc(hot_inode_item_cachep,
>> + GFP_KERNEL | GFP_NOFS);
>> + if (!he)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + hot_inode_item_init(he, ino, >hot_inode_tree);
>> +
>> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
>> + if (ret) {
>> + kmem_cache_free(hot_inode_item_cachep, he);
>> + return ERR_PTR(ret);
>> + }
>> +
>> + spin_lock(>lock);
>> + ret = radix_tree_insert(>hot_inode_tree, ino, he);
>> + if (ret == -EEXIST) {
>> + kmem_cache_free(hot_inode_item_cachep, he);
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
>> + goto again;
>> + }
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
>> +
>> + kref_get(>hot_inode.refs);
>> + return he;
>> +}
>> +EXPORT_SYMBOL_GPL(hot_inode_item_find);
>> +
>> +static struct hot_range_item
>> +*hot_range_item_find(struct hot_inode_item *he,
>> + u32 start)
>> +{
>> + struct hot_range_item *hr;
>> + int ret;
>> +
>> +again:
>> + spin_lock(>lock);
>> + hr = radix_tree_lookup(>hot_range_tree, start);
>> + if (hr) {
>> + kref_get(>hot_range.refs);
>> + spin_unlock(>lock);
>> + return hr;
>> + }
>> + spin_unlock(>lock);
>> +
>> + hr = kmem_cache_zalloc(hot_range_item_cachep,
>> + GFP_KERNEL | GFP_NOFS);
>> + if (!hr)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + hot_range_item_init(hr, start, he);
>> +
>> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
>> + if (ret) {
>> + kmem_cache_free(hot_range_item_cachep, hr);
>> + return ERR_PTR(ret);
>> + }
>> +
>> + spin_lock(>lock);
>> + ret = radix_tree_insert(>hot_range_tree, start, hr);
>> + if (ret == -EEXIST) {
>> + kmem_cache_free(hot_range_item_cachep, hr);
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
>> + goto again;
>> + }
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
>> +
>> + kref_get(>hot_range.refs);
>> + return hr;
>> +}
>> +
>> +/*
>> + * This function does the actual work of updating
>> + * the frequency numbers, whatever they turn out to be.
>> + */
>> +static u64 hot_average_update(struct timespec old_atime,
>> + struct timespec cur_time, u64 old_avg)
>> +{
>> + struct timespec delta_ts;
>> + u64 new_avg;
>> + u64 new_delta;
>> +
>> + delta_ts = timespec_sub(cur_time, old_atime);
>> + new_delta = timespec_to_ns(_ts) >> FREQ_POWER;
>> +
>> + new_avg = (old_avg << FREQ_POWER) - old_avg + new_delta;
>> + new_avg = new_avg >> FREQ_POWER;
>> +
>> + return new_avg;
>> +}
>> +
>> +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;
>> + freq_data->avg_delta_writes = hot_average_update(
>> + 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;
>> + freq_data->avg_delta_reads = hot_average_update(
>> + freq_data->last_read_time,
>> + cur_time,
>> + freq_data->avg_delta_reads);
>
> I think you could just pass in a pointer to
> freq_data->avg_delta_{writes,reads} here...
why?
>
>> + freq_data->last_read_time = cur_time;
>> + }
>> +}
>> +
>>  /*
>>   * 

Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-07 Thread Zhi Yong Wu
On Wed, Nov 7, 2012 at 6:45 AM, Darrick J. Wong darrick.w...@oracle.com wrote:
 On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
 From: Zhi Yong Wu wu...@linux.vnet.ibm.com

   Add some util helpers to update access frequencies
 for one file or its range.

 Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com
 ---
  fs/hot_tracking.c|  179 
 ++
  fs/hot_tracking.h|7 ++
  include/linux/hot_tracking.h |2 +
  3 files changed, 188 insertions(+), 0 deletions(-)

 diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
 index 68591f0..0a7d9a3 100644
 --- a/fs/hot_tracking.c
 +++ b/fs/hot_tracking.c
 @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
   }
  }

 +struct hot_inode_item
 +*hot_inode_item_find(struct hot_info *root, u64 ino)
 +{
 + struct hot_inode_item *he;
 + int ret;
 +
 +again:
 + spin_lock(root-lock);
 + he = radix_tree_lookup(root-hot_inode_tree, ino);
 + if (he) {
 + kref_get(he-hot_inode.refs);
 + spin_unlock(root-lock);
 + return he;
 + }
 + spin_unlock(root-lock);
 +
 + he = kmem_cache_zalloc(hot_inode_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 + if (!he)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_inode_item_init(he, ino, root-hot_inode_tree);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(root-lock);
 + ret = radix_tree_insert(root-hot_inode_tree, ino, he);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 + goto again;
 + }
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 +
 + kref_get(he-hot_inode.refs);
 + return he;
 +}
 +EXPORT_SYMBOL_GPL(hot_inode_item_find);
 +
 +static struct hot_range_item
 +*hot_range_item_find(struct hot_inode_item *he,
 + u32 start)
 +{
 + struct hot_range_item *hr;
 + int ret;
 +
 +again:
 + spin_lock(he-lock);
 + hr = radix_tree_lookup(he-hot_range_tree, start);
 + if (hr) {
 + kref_get(hr-hot_range.refs);
 + spin_unlock(he-lock);
 + return hr;
 + }
 + spin_unlock(he-lock);
 +
 + hr = kmem_cache_zalloc(hot_range_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 + if (!hr)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_range_item_init(hr, start, he);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_range_item_cachep, hr);
 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(he-lock);
 + ret = radix_tree_insert(he-hot_range_tree, start, hr);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_range_item_cachep, hr);
 + spin_unlock(he-lock);
 + radix_tree_preload_end();
 + goto again;
 + }
 + spin_unlock(he-lock);
 + radix_tree_preload_end();
 +
 + kref_get(hr-hot_range.refs);
 + return hr;
 +}
 +
 +/*
 + * This function does the actual work of updating
 + * the frequency numbers, whatever they turn out to be.
 + */
 +static u64 hot_average_update(struct timespec old_atime,
 + struct timespec cur_time, u64 old_avg)
 +{
 + struct timespec delta_ts;
 + u64 new_avg;
 + u64 new_delta;
 +
 + delta_ts = timespec_sub(cur_time, old_atime);
 + new_delta = timespec_to_ns(delta_ts)  FREQ_POWER;
 +
 + new_avg = (old_avg  FREQ_POWER) - old_avg + new_delta;
 + new_avg = new_avg  FREQ_POWER;
 +
 + return new_avg;
 +}
 +
 +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;
 + freq_data-avg_delta_writes = hot_average_update(
 + 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;
 + freq_data-avg_delta_reads = hot_average_update(
 + freq_data-last_read_time,
 + cur_time,
 + freq_data-avg_delta_reads);

 I think you could just pass in a pointer to
 freq_data-avg_delta_{writes,reads} here...
why?

 + freq_data-last_read_time = cur_time;
 + }
 +}
 +
  /*
   * Initialize kmem cache for hot_inode_item and hot_range_item.
   */
 @@ -199,6 +330,54 @@ err:
  EXPORT_SYMBOL_GPL(hot_cache_init);

  /*
 + * Main function to update access frequency from 

Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-07 Thread Darrick J. Wong
On Wed, Nov 07, 2012 at 04:27:05PM +0800, Zhi Yong Wu wrote:
 On Wed, Nov 7, 2012 at 6:45 AM, Darrick J. Wong darrick.w...@oracle.com 
 wrote:
  On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
  From: Zhi Yong Wu wu...@linux.vnet.ibm.com
 
Add some util helpers to update access frequencies
  for one file or its range.
 
  Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com
  ---
   fs/hot_tracking.c|  179 
  ++
   fs/hot_tracking.h|7 ++
   include/linux/hot_tracking.h |2 +
   3 files changed, 188 insertions(+), 0 deletions(-)
 
  diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
  index 68591f0..0a7d9a3 100644
  --- a/fs/hot_tracking.c
  +++ b/fs/hot_tracking.c
  @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info 
  *root)
}
   }
 
  +struct hot_inode_item
  +*hot_inode_item_find(struct hot_info *root, u64 ino)
  +{
  + struct hot_inode_item *he;
  + int ret;
  +
  +again:
  + spin_lock(root-lock);
  + he = radix_tree_lookup(root-hot_inode_tree, ino);
  + if (he) {
  + kref_get(he-hot_inode.refs);
  + spin_unlock(root-lock);
  + return he;
  + }
  + spin_unlock(root-lock);
  +
  + he = kmem_cache_zalloc(hot_inode_item_cachep,
  + GFP_KERNEL | GFP_NOFS);
  + if (!he)
  + return ERR_PTR(-ENOMEM);
  +
  + hot_inode_item_init(he, ino, root-hot_inode_tree);
  +
  + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
  + if (ret) {
  + kmem_cache_free(hot_inode_item_cachep, he);
  + return ERR_PTR(ret);
  + }
  +
  + spin_lock(root-lock);
  + ret = radix_tree_insert(root-hot_inode_tree, ino, he);
  + if (ret == -EEXIST) {
  + kmem_cache_free(hot_inode_item_cachep, he);
  + spin_unlock(root-lock);
  + radix_tree_preload_end();
  + goto again;
  + }
  + spin_unlock(root-lock);
  + radix_tree_preload_end();
  +
  + kref_get(he-hot_inode.refs);
  + return he;
  +}
  +EXPORT_SYMBOL_GPL(hot_inode_item_find);
  +
  +static struct hot_range_item
  +*hot_range_item_find(struct hot_inode_item *he,
  + u32 start)
  +{
  + struct hot_range_item *hr;
  + int ret;
  +
  +again:
  + spin_lock(he-lock);
  + hr = radix_tree_lookup(he-hot_range_tree, start);
  + if (hr) {
  + kref_get(hr-hot_range.refs);
  + spin_unlock(he-lock);
  + return hr;
  + }
  + spin_unlock(he-lock);
  +
  + hr = kmem_cache_zalloc(hot_range_item_cachep,
  + GFP_KERNEL | GFP_NOFS);
  + if (!hr)
  + return ERR_PTR(-ENOMEM);
  +
  + hot_range_item_init(hr, start, he);
  +
  + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
  + if (ret) {
  + kmem_cache_free(hot_range_item_cachep, hr);
  + return ERR_PTR(ret);
  + }
  +
  + spin_lock(he-lock);
  + ret = radix_tree_insert(he-hot_range_tree, start, hr);
  + if (ret == -EEXIST) {
  + kmem_cache_free(hot_range_item_cachep, hr);
  + spin_unlock(he-lock);
  + radix_tree_preload_end();
  + goto again;
  + }
  + spin_unlock(he-lock);
  + radix_tree_preload_end();
  +
  + kref_get(hr-hot_range.refs);
  + return hr;
  +}
  +
  +/*
  + * This function does the actual work of updating
  + * the frequency numbers, whatever they turn out to be.
  + */
  +static u64 hot_average_update(struct timespec old_atime,
  + struct timespec cur_time, u64 old_avg)
  +{
  + struct timespec delta_ts;
  + u64 new_avg;
  + u64 new_delta;
  +
  + delta_ts = timespec_sub(cur_time, old_atime);
  + new_delta = timespec_to_ns(delta_ts)  FREQ_POWER;
  +
  + new_avg = (old_avg  FREQ_POWER) - old_avg + new_delta;
  + new_avg = new_avg  FREQ_POWER;
  +
  + return new_avg;
  +}
  +
  +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;
  + freq_data-avg_delta_writes = hot_average_update(
  + 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;
  + freq_data-avg_delta_reads = hot_average_update(
  + freq_data-last_read_time,
  + cur_time,
  + freq_data-avg_delta_reads);
 
  I think you could just pass in a pointer to
  freq_data-avg_delta_{writes,reads} here...
 why?

freq_data-avg_delta_{reads,writes} seems to be an in/out 

Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-07 Thread Zhi Yong Wu
On Thu, Nov 8, 2012 at 2:49 AM, Darrick J. Wong darrick.w...@oracle.com wrote:
 On Wed, Nov 07, 2012 at 04:27:05PM +0800, Zhi Yong Wu wrote:
 On Wed, Nov 7, 2012 at 6:45 AM, Darrick J. Wong darrick.w...@oracle.com 
 wrote:
  On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
  From: Zhi Yong Wu wu...@linux.vnet.ibm.com
 
Add some util helpers to update access frequencies
  for one file or its range.
 
  Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com
  ---
   fs/hot_tracking.c|  179 
  ++
   fs/hot_tracking.h|7 ++
   include/linux/hot_tracking.h |2 +
   3 files changed, 188 insertions(+), 0 deletions(-)
 
  diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
  index 68591f0..0a7d9a3 100644
  --- a/fs/hot_tracking.c
  +++ b/fs/hot_tracking.c
  @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info 
  *root)
}
   }
 
  +struct hot_inode_item
  +*hot_inode_item_find(struct hot_info *root, u64 ino)
  +{
  + struct hot_inode_item *he;
  + int ret;
  +
  +again:
  + spin_lock(root-lock);
  + he = radix_tree_lookup(root-hot_inode_tree, ino);
  + if (he) {
  + kref_get(he-hot_inode.refs);
  + spin_unlock(root-lock);
  + return he;
  + }
  + spin_unlock(root-lock);
  +
  + he = kmem_cache_zalloc(hot_inode_item_cachep,
  + GFP_KERNEL | GFP_NOFS);
  + if (!he)
  + return ERR_PTR(-ENOMEM);
  +
  + hot_inode_item_init(he, ino, root-hot_inode_tree);
  +
  + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
  + if (ret) {
  + kmem_cache_free(hot_inode_item_cachep, he);
  + return ERR_PTR(ret);
  + }
  +
  + spin_lock(root-lock);
  + ret = radix_tree_insert(root-hot_inode_tree, ino, he);
  + if (ret == -EEXIST) {
  + kmem_cache_free(hot_inode_item_cachep, he);
  + spin_unlock(root-lock);
  + radix_tree_preload_end();
  + goto again;
  + }
  + spin_unlock(root-lock);
  + radix_tree_preload_end();
  +
  + kref_get(he-hot_inode.refs);
  + return he;
  +}
  +EXPORT_SYMBOL_GPL(hot_inode_item_find);
  +
  +static struct hot_range_item
  +*hot_range_item_find(struct hot_inode_item *he,
  + u32 start)
  +{
  + struct hot_range_item *hr;
  + int ret;
  +
  +again:
  + spin_lock(he-lock);
  + hr = radix_tree_lookup(he-hot_range_tree, start);
  + if (hr) {
  + kref_get(hr-hot_range.refs);
  + spin_unlock(he-lock);
  + return hr;
  + }
  + spin_unlock(he-lock);
  +
  + hr = kmem_cache_zalloc(hot_range_item_cachep,
  + GFP_KERNEL | GFP_NOFS);
  + if (!hr)
  + return ERR_PTR(-ENOMEM);
  +
  + hot_range_item_init(hr, start, he);
  +
  + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
  + if (ret) {
  + kmem_cache_free(hot_range_item_cachep, hr);
  + return ERR_PTR(ret);
  + }
  +
  + spin_lock(he-lock);
  + ret = radix_tree_insert(he-hot_range_tree, start, hr);
  + if (ret == -EEXIST) {
  + kmem_cache_free(hot_range_item_cachep, hr);
  + spin_unlock(he-lock);
  + radix_tree_preload_end();
  + goto again;
  + }
  + spin_unlock(he-lock);
  + radix_tree_preload_end();
  +
  + kref_get(hr-hot_range.refs);
  + return hr;
  +}
  +
  +/*
  + * This function does the actual work of updating
  + * the frequency numbers, whatever they turn out to be.
  + */
  +static u64 hot_average_update(struct timespec old_atime,
  + struct timespec cur_time, u64 old_avg)
  +{
  + struct timespec delta_ts;
  + u64 new_avg;
  + u64 new_delta;
  +
  + delta_ts = timespec_sub(cur_time, old_atime);
  + new_delta = timespec_to_ns(delta_ts)  FREQ_POWER;
  +
  + new_avg = (old_avg  FREQ_POWER) - old_avg + new_delta;
  + new_avg = new_avg  FREQ_POWER;
  +
  + return new_avg;
  +}
  +
  +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;
  + freq_data-avg_delta_writes = hot_average_update(
  + 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;
  + freq_data-avg_delta_reads = hot_average_update(
  + freq_data-last_read_time,
  + cur_time,
  + freq_data-avg_delta_reads);
 
  I think you could just pass in a pointer to
  

Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-06 Thread Zhi Yong Wu
On Wed, Nov 7, 2012 at 6:37 AM, David Sterba  wrote:
> On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
>> --- a/fs/hot_tracking.c
>> +++ b/fs/hot_tracking.c
>> +struct hot_inode_item
>> +*hot_inode_item_find(struct hot_info *root, u64 ino)
>> +{
>> + struct hot_inode_item *he;
>> + int ret;
>> +
>> +again:
>> + spin_lock(>lock);
>> + he = radix_tree_lookup(>hot_inode_tree, ino);
>> + if (he) {
>> + kref_get(>hot_inode.refs);
>> + spin_unlock(>lock);
>> + return he;
>> + }
>> + spin_unlock(>lock);
>> +
>> + he = kmem_cache_zalloc(hot_inode_item_cachep,
>> + GFP_KERNEL | GFP_NOFS);
>> + if (!he)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + hot_inode_item_init(he, ino, >hot_inode_tree);
>> +
>> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
>> + if (ret) {
>> + kmem_cache_free(hot_inode_item_cachep, he);
>
> radix_tree_preload_end()
>
>> + return ERR_PTR(ret);
>> + }
>> +
>> + spin_lock(>lock);
>> + ret = radix_tree_insert(>hot_inode_tree, ino, he);
>> + if (ret == -EEXIST) {
>> + kmem_cache_free(hot_inode_item_cachep, he);
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
>> + goto again;
>> + }
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
>> +
>> + kref_get(>hot_inode.refs);
>> + return he;
>> +}
>> +EXPORT_SYMBOL_GPL(hot_inode_item_find);
>> +
>> +static struct hot_range_item
>> +*hot_range_item_find(struct hot_inode_item *he,
>> + u32 start)
>> +{
>> + struct hot_range_item *hr;
>> + int ret;
>> +
>> +again:
>> + spin_lock(>lock);
>> + hr = radix_tree_lookup(>hot_range_tree, start);
>> + if (hr) {
>> + kref_get(>hot_range.refs);
>> + spin_unlock(>lock);
>> + return hr;
>> + }
>> + spin_unlock(>lock);
>> +
>> + hr = kmem_cache_zalloc(hot_range_item_cachep,
>> + GFP_KERNEL | GFP_NOFS);
>> + if (!hr)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + hot_range_item_init(hr, start, he);
>> +
>> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
>> + if (ret) {
>> + kmem_cache_free(hot_range_item_cachep, hr);
>
> radix_tree_preload_end()
I checked some kernel existing cases about the usage of
radix_tree_preload(), it seems that when radix_tree_preload() fail,
its error handling doesn't need call radix_tree_preload_end() any
more.
>
>> + return ERR_PTR(ret);
>> + }
>> +
>> + spin_lock(>lock);
>> + ret = radix_tree_insert(>hot_range_tree, start, hr);
>> + if (ret == -EEXIST) {
>> + kmem_cache_free(hot_range_item_cachep, hr);
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
ditto.
>> + goto again;
>> + }
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
>> +
>> + kref_get(>hot_range.refs);
>> + return hr;
>> +}
>
> david



-- 
Regards,

Zhi Yong Wu
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-06 Thread Darrick J. Wong
On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
> From: Zhi Yong Wu 
> 
>   Add some util helpers to update access frequencies
> for one file or its range.
> 
> Signed-off-by: Zhi Yong Wu 
> ---
>  fs/hot_tracking.c|  179 
> ++
>  fs/hot_tracking.h|7 ++
>  include/linux/hot_tracking.h |2 +
>  3 files changed, 188 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
> index 68591f0..0a7d9a3 100644
> --- a/fs/hot_tracking.c
> +++ b/fs/hot_tracking.c
> @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
>   }
>  }
>  
> +struct hot_inode_item
> +*hot_inode_item_find(struct hot_info *root, u64 ino)
> +{
> + struct hot_inode_item *he;
> + int ret;
> +
> +again:
> + spin_lock(>lock);
> + he = radix_tree_lookup(>hot_inode_tree, ino);
> + if (he) {
> + kref_get(>hot_inode.refs);
> + spin_unlock(>lock);
> + return he;
> + }
> + spin_unlock(>lock);
> +
> + he = kmem_cache_zalloc(hot_inode_item_cachep,
> + GFP_KERNEL | GFP_NOFS);
> + if (!he)
> + return ERR_PTR(-ENOMEM);
> +
> + hot_inode_item_init(he, ino, >hot_inode_tree);
> +
> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
> + if (ret) {
> + kmem_cache_free(hot_inode_item_cachep, he);
> + return ERR_PTR(ret);
> + }
> +
> + spin_lock(>lock);
> + ret = radix_tree_insert(>hot_inode_tree, ino, he);
> + if (ret == -EEXIST) {
> + kmem_cache_free(hot_inode_item_cachep, he);
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> + goto again;
> + }
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> +
> + kref_get(>hot_inode.refs);
> + return he;
> +}
> +EXPORT_SYMBOL_GPL(hot_inode_item_find);
> +
> +static struct hot_range_item
> +*hot_range_item_find(struct hot_inode_item *he,
> + u32 start)
> +{
> + struct hot_range_item *hr;
> + int ret;
> +
> +again:
> + spin_lock(>lock);
> + hr = radix_tree_lookup(>hot_range_tree, start);
> + if (hr) {
> + kref_get(>hot_range.refs);
> + spin_unlock(>lock);
> + return hr;
> + }
> + spin_unlock(>lock);
> +
> + hr = kmem_cache_zalloc(hot_range_item_cachep,
> + GFP_KERNEL | GFP_NOFS);
> + if (!hr)
> + return ERR_PTR(-ENOMEM);
> +
> + hot_range_item_init(hr, start, he);
> +
> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
> + if (ret) {
> + kmem_cache_free(hot_range_item_cachep, hr);
> + return ERR_PTR(ret);
> + }
> +
> + spin_lock(>lock);
> + ret = radix_tree_insert(>hot_range_tree, start, hr);
> + if (ret == -EEXIST) {
> + kmem_cache_free(hot_range_item_cachep, hr);
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> + goto again;
> + }
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> +
> + kref_get(>hot_range.refs);
> + return hr;
> +}
> +
> +/*
> + * This function does the actual work of updating
> + * the frequency numbers, whatever they turn out to be.
> + */
> +static u64 hot_average_update(struct timespec old_atime,
> + struct timespec cur_time, u64 old_avg)
> +{
> + struct timespec delta_ts;
> + u64 new_avg;
> + u64 new_delta;
> +
> + delta_ts = timespec_sub(cur_time, old_atime);
> + new_delta = timespec_to_ns(_ts) >> FREQ_POWER;
> +
> + new_avg = (old_avg << FREQ_POWER) - old_avg + new_delta;
> + new_avg = new_avg >> FREQ_POWER;
> +
> + return new_avg;
> +}
> +
> +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;
> + freq_data->avg_delta_writes = hot_average_update(
> + 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;
> + freq_data->avg_delta_reads = hot_average_update(
> + freq_data->last_read_time,
> + cur_time,
> + freq_data->avg_delta_reads);

I think you could just pass in a pointer to
freq_data->avg_delta_{writes,reads} here...

> + freq_data->last_read_time = cur_time;
> + }
> +}
> +
>  /*
>   * Initialize kmem cache for hot_inode_item and hot_range_item.
>   */
> @@ -199,6 +330,54 @@ err:
>  EXPORT_SYMBOL_GPL(hot_cache_init);
>  
>  /*
> + * Main function to update access frequency from read/writepage(s) hooks
> + */

Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-06 Thread David Sterba
On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
> --- a/fs/hot_tracking.c
> +++ b/fs/hot_tracking.c
> +struct hot_inode_item
> +*hot_inode_item_find(struct hot_info *root, u64 ino)
> +{
> + struct hot_inode_item *he;
> + int ret;
> +
> +again:
> + spin_lock(>lock);
> + he = radix_tree_lookup(>hot_inode_tree, ino);
> + if (he) {
> + kref_get(>hot_inode.refs);
> + spin_unlock(>lock);
> + return he;
> + }
> + spin_unlock(>lock);
> +
> + he = kmem_cache_zalloc(hot_inode_item_cachep,
> + GFP_KERNEL | GFP_NOFS);
> + if (!he)
> + return ERR_PTR(-ENOMEM);
> +
> + hot_inode_item_init(he, ino, >hot_inode_tree);
> +
> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
> + if (ret) {
> + kmem_cache_free(hot_inode_item_cachep, he);

radix_tree_preload_end()

> + return ERR_PTR(ret);
> + }
> +
> + spin_lock(>lock);
> + ret = radix_tree_insert(>hot_inode_tree, ino, he);
> + if (ret == -EEXIST) {
> + kmem_cache_free(hot_inode_item_cachep, he);
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> + goto again;
> + }
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> +
> + kref_get(>hot_inode.refs);
> + return he;
> +}
> +EXPORT_SYMBOL_GPL(hot_inode_item_find);
> +
> +static struct hot_range_item
> +*hot_range_item_find(struct hot_inode_item *he,
> + u32 start)
> +{
> + struct hot_range_item *hr;
> + int ret;
> +
> +again:
> + spin_lock(>lock);
> + hr = radix_tree_lookup(>hot_range_tree, start);
> + if (hr) {
> + kref_get(>hot_range.refs);
> + spin_unlock(>lock);
> + return hr;
> + }
> + spin_unlock(>lock);
> +
> + hr = kmem_cache_zalloc(hot_range_item_cachep,
> + GFP_KERNEL | GFP_NOFS);
> + if (!hr)
> + return ERR_PTR(-ENOMEM);
> +
> + hot_range_item_init(hr, start, he);
> +
> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
> + if (ret) {
> + kmem_cache_free(hot_range_item_cachep, hr);

radix_tree_preload_end()

> + return ERR_PTR(ret);
> + }
> +
> + spin_lock(>lock);
> + ret = radix_tree_insert(>hot_range_tree, start, hr);
> + if (ret == -EEXIST) {
> + kmem_cache_free(hot_range_item_cachep, hr);
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> + goto again;
> + }
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> +
> + kref_get(>hot_range.refs);
> + return hr;
> +}

david
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-06 Thread David Sterba
On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
 --- a/fs/hot_tracking.c
 +++ b/fs/hot_tracking.c
 +struct hot_inode_item
 +*hot_inode_item_find(struct hot_info *root, u64 ino)
 +{
 + struct hot_inode_item *he;
 + int ret;
 +
 +again:
 + spin_lock(root-lock);
 + he = radix_tree_lookup(root-hot_inode_tree, ino);
 + if (he) {
 + kref_get(he-hot_inode.refs);
 + spin_unlock(root-lock);
 + return he;
 + }
 + spin_unlock(root-lock);
 +
 + he = kmem_cache_zalloc(hot_inode_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 + if (!he)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_inode_item_init(he, ino, root-hot_inode_tree);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_inode_item_cachep, he);

radix_tree_preload_end()

 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(root-lock);
 + ret = radix_tree_insert(root-hot_inode_tree, ino, he);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 + goto again;
 + }
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 +
 + kref_get(he-hot_inode.refs);
 + return he;
 +}
 +EXPORT_SYMBOL_GPL(hot_inode_item_find);
 +
 +static struct hot_range_item
 +*hot_range_item_find(struct hot_inode_item *he,
 + u32 start)
 +{
 + struct hot_range_item *hr;
 + int ret;
 +
 +again:
 + spin_lock(he-lock);
 + hr = radix_tree_lookup(he-hot_range_tree, start);
 + if (hr) {
 + kref_get(hr-hot_range.refs);
 + spin_unlock(he-lock);
 + return hr;
 + }
 + spin_unlock(he-lock);
 +
 + hr = kmem_cache_zalloc(hot_range_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 + if (!hr)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_range_item_init(hr, start, he);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_range_item_cachep, hr);

radix_tree_preload_end()

 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(he-lock);
 + ret = radix_tree_insert(he-hot_range_tree, start, hr);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_range_item_cachep, hr);
 + spin_unlock(he-lock);
 + radix_tree_preload_end();
 + goto again;
 + }
 + spin_unlock(he-lock);
 + radix_tree_preload_end();
 +
 + kref_get(hr-hot_range.refs);
 + return hr;
 +}

david
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-06 Thread Darrick J. Wong
On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
 From: Zhi Yong Wu wu...@linux.vnet.ibm.com
 
   Add some util helpers to update access frequencies
 for one file or its range.
 
 Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com
 ---
  fs/hot_tracking.c|  179 
 ++
  fs/hot_tracking.h|7 ++
  include/linux/hot_tracking.h |2 +
  3 files changed, 188 insertions(+), 0 deletions(-)
 
 diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
 index 68591f0..0a7d9a3 100644
 --- a/fs/hot_tracking.c
 +++ b/fs/hot_tracking.c
 @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
   }
  }
  
 +struct hot_inode_item
 +*hot_inode_item_find(struct hot_info *root, u64 ino)
 +{
 + struct hot_inode_item *he;
 + int ret;
 +
 +again:
 + spin_lock(root-lock);
 + he = radix_tree_lookup(root-hot_inode_tree, ino);
 + if (he) {
 + kref_get(he-hot_inode.refs);
 + spin_unlock(root-lock);
 + return he;
 + }
 + spin_unlock(root-lock);
 +
 + he = kmem_cache_zalloc(hot_inode_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 + if (!he)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_inode_item_init(he, ino, root-hot_inode_tree);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(root-lock);
 + ret = radix_tree_insert(root-hot_inode_tree, ino, he);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 + goto again;
 + }
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 +
 + kref_get(he-hot_inode.refs);
 + return he;
 +}
 +EXPORT_SYMBOL_GPL(hot_inode_item_find);
 +
 +static struct hot_range_item
 +*hot_range_item_find(struct hot_inode_item *he,
 + u32 start)
 +{
 + struct hot_range_item *hr;
 + int ret;
 +
 +again:
 + spin_lock(he-lock);
 + hr = radix_tree_lookup(he-hot_range_tree, start);
 + if (hr) {
 + kref_get(hr-hot_range.refs);
 + spin_unlock(he-lock);
 + return hr;
 + }
 + spin_unlock(he-lock);
 +
 + hr = kmem_cache_zalloc(hot_range_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 + if (!hr)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_range_item_init(hr, start, he);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_range_item_cachep, hr);
 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(he-lock);
 + ret = radix_tree_insert(he-hot_range_tree, start, hr);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_range_item_cachep, hr);
 + spin_unlock(he-lock);
 + radix_tree_preload_end();
 + goto again;
 + }
 + spin_unlock(he-lock);
 + radix_tree_preload_end();
 +
 + kref_get(hr-hot_range.refs);
 + return hr;
 +}
 +
 +/*
 + * This function does the actual work of updating
 + * the frequency numbers, whatever they turn out to be.
 + */
 +static u64 hot_average_update(struct timespec old_atime,
 + struct timespec cur_time, u64 old_avg)
 +{
 + struct timespec delta_ts;
 + u64 new_avg;
 + u64 new_delta;
 +
 + delta_ts = timespec_sub(cur_time, old_atime);
 + new_delta = timespec_to_ns(delta_ts)  FREQ_POWER;
 +
 + new_avg = (old_avg  FREQ_POWER) - old_avg + new_delta;
 + new_avg = new_avg  FREQ_POWER;
 +
 + return new_avg;
 +}
 +
 +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;
 + freq_data-avg_delta_writes = hot_average_update(
 + 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;
 + freq_data-avg_delta_reads = hot_average_update(
 + freq_data-last_read_time,
 + cur_time,
 + freq_data-avg_delta_reads);

I think you could just pass in a pointer to
freq_data-avg_delta_{writes,reads} here...

 + freq_data-last_read_time = cur_time;
 + }
 +}
 +
  /*
   * Initialize kmem cache for hot_inode_item and hot_range_item.
   */
 @@ -199,6 +330,54 @@ 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, u64 start,
 +  

Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-06 Thread Zhi Yong Wu
On Wed, Nov 7, 2012 at 6:37 AM, David Sterba d...@jikos.cz wrote:
 On Mon, Oct 29, 2012 at 12:30:45PM +0800, zwu.ker...@gmail.com wrote:
 --- a/fs/hot_tracking.c
 +++ b/fs/hot_tracking.c
 +struct hot_inode_item
 +*hot_inode_item_find(struct hot_info *root, u64 ino)
 +{
 + struct hot_inode_item *he;
 + int ret;
 +
 +again:
 + spin_lock(root-lock);
 + he = radix_tree_lookup(root-hot_inode_tree, ino);
 + if (he) {
 + kref_get(he-hot_inode.refs);
 + spin_unlock(root-lock);
 + return he;
 + }
 + spin_unlock(root-lock);
 +
 + he = kmem_cache_zalloc(hot_inode_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 + if (!he)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_inode_item_init(he, ino, root-hot_inode_tree);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_inode_item_cachep, he);

 radix_tree_preload_end()

 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(root-lock);
 + ret = radix_tree_insert(root-hot_inode_tree, ino, he);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 + goto again;
 + }
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 +
 + kref_get(he-hot_inode.refs);
 + return he;
 +}
 +EXPORT_SYMBOL_GPL(hot_inode_item_find);
 +
 +static struct hot_range_item
 +*hot_range_item_find(struct hot_inode_item *he,
 + u32 start)
 +{
 + struct hot_range_item *hr;
 + int ret;
 +
 +again:
 + spin_lock(he-lock);
 + hr = radix_tree_lookup(he-hot_range_tree, start);
 + if (hr) {
 + kref_get(hr-hot_range.refs);
 + spin_unlock(he-lock);
 + return hr;
 + }
 + spin_unlock(he-lock);
 +
 + hr = kmem_cache_zalloc(hot_range_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 + if (!hr)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_range_item_init(hr, start, he);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_range_item_cachep, hr);

 radix_tree_preload_end()
I checked some kernel existing cases about the usage of
radix_tree_preload(), it seems that when radix_tree_preload() fail,
its error handling doesn't need call radix_tree_preload_end() any
more.

 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(he-lock);
 + ret = radix_tree_insert(he-hot_range_tree, start, hr);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_range_item_cachep, hr);
 + spin_unlock(he-lock);
 + radix_tree_preload_end();
ditto.
 + goto again;
 + }
 + spin_unlock(he-lock);
 + radix_tree_preload_end();
 +
 + kref_get(hr-hot_range.refs);
 + return hr;
 +}

 david



-- 
Regards,

Zhi Yong Wu
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-05 Thread Zhi Yong Wu
On Mon, Nov 5, 2012 at 7:07 PM, Steven Whitehouse  wrote:
> Hi,
>
> On Mon, 2012-10-29 at 12:30 +0800, zwu.ker...@gmail.com wrote:
>> From: Zhi Yong Wu 
>>
>>   Add some util helpers to update access frequencies
>> for one file or its range.
>>
>> Signed-off-by: Zhi Yong Wu 
>> ---
>>  fs/hot_tracking.c|  179 
>> ++
>>  fs/hot_tracking.h|7 ++
>>  include/linux/hot_tracking.h |2 +
>>  3 files changed, 188 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
>> index 68591f0..0a7d9a3 100644
>> --- a/fs/hot_tracking.c
>> +++ b/fs/hot_tracking.c
>> @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
>>   }
>>  }
>>
>> +struct hot_inode_item
>> +*hot_inode_item_find(struct hot_info *root, u64 ino)
>> +{
>> + struct hot_inode_item *he;
>> + int ret;
>> +
>> +again:
>> + spin_lock(>lock);
>> + he = radix_tree_lookup(>hot_inode_tree, ino);
>> + if (he) {
>> + kref_get(>hot_inode.refs);
>> + spin_unlock(>lock);
>> + return he;
>> + }
>> + spin_unlock(>lock);
>> +
>> + he = kmem_cache_zalloc(hot_inode_item_cachep,
>> + GFP_KERNEL | GFP_NOFS);
> This doesn't look quite right... which of these two did you mean? I
> assume probably just GFP_NOFS
Yes, good catch, thanks.
>
>> + if (!he)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + hot_inode_item_init(he, ino, >hot_inode_tree);
>> +
>> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
>> + if (ret) {
>> + kmem_cache_free(hot_inode_item_cachep, he);
>> + return ERR_PTR(ret);
>> + }
>> +
>> + spin_lock(>lock);
>> + ret = radix_tree_insert(>hot_inode_tree, ino, he);
>> + if (ret == -EEXIST) {
>> + kmem_cache_free(hot_inode_item_cachep, he);
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
>> + goto again;
>> + }
>> + spin_unlock(>lock);
>> + radix_tree_preload_end();
>> +
>> + kref_get(>hot_inode.refs);
>> + return he;
>> +}
>> +EXPORT_SYMBOL_GPL(hot_inode_item_find);
>> +
>> +static struct hot_range_item
>> +*hot_range_item_find(struct hot_inode_item *he,
>> + u32 start)
>> +{
>> + struct hot_range_item *hr;
>> + int ret;
>> +
>> +again:
>> + spin_lock(>lock);
>> + hr = radix_tree_lookup(>hot_range_tree, start);
>> + if (hr) {
>> + kref_get(>hot_range.refs);
>> + spin_unlock(>lock);
>> + return hr;
>> + }
>> + spin_unlock(>lock);
>> +
>> + hr = kmem_cache_zalloc(hot_range_item_cachep,
>> + GFP_KERNEL | GFP_NOFS);
> Likewise, here too.
ditto
>
> Steve.
>
>
>



-- 
Regards,

Zhi Yong Wu
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-05 Thread Steven Whitehouse
Hi,

On Mon, 2012-10-29 at 12:30 +0800, zwu.ker...@gmail.com wrote:
> From: Zhi Yong Wu 
> 
>   Add some util helpers to update access frequencies
> for one file or its range.
> 
> Signed-off-by: Zhi Yong Wu 
> ---
>  fs/hot_tracking.c|  179 
> ++
>  fs/hot_tracking.h|7 ++
>  include/linux/hot_tracking.h |2 +
>  3 files changed, 188 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
> index 68591f0..0a7d9a3 100644
> --- a/fs/hot_tracking.c
> +++ b/fs/hot_tracking.c
> @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
>   }
>  }
>  
> +struct hot_inode_item
> +*hot_inode_item_find(struct hot_info *root, u64 ino)
> +{
> + struct hot_inode_item *he;
> + int ret;
> +
> +again:
> + spin_lock(>lock);
> + he = radix_tree_lookup(>hot_inode_tree, ino);
> + if (he) {
> + kref_get(>hot_inode.refs);
> + spin_unlock(>lock);
> + return he;
> + }
> + spin_unlock(>lock);
> +
> + he = kmem_cache_zalloc(hot_inode_item_cachep,
> + GFP_KERNEL | GFP_NOFS);
This doesn't look quite right... which of these two did you mean? I
assume probably just GFP_NOFS

> + if (!he)
> + return ERR_PTR(-ENOMEM);
> +
> + hot_inode_item_init(he, ino, >hot_inode_tree);
> +
> + ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
> + if (ret) {
> + kmem_cache_free(hot_inode_item_cachep, he);
> + return ERR_PTR(ret);
> + }
> +
> + spin_lock(>lock);
> + ret = radix_tree_insert(>hot_inode_tree, ino, he);
> + if (ret == -EEXIST) {
> + kmem_cache_free(hot_inode_item_cachep, he);
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> + goto again;
> + }
> + spin_unlock(>lock);
> + radix_tree_preload_end();
> +
> + kref_get(>hot_inode.refs);
> + return he;
> +}
> +EXPORT_SYMBOL_GPL(hot_inode_item_find);
> +
> +static struct hot_range_item
> +*hot_range_item_find(struct hot_inode_item *he,
> + u32 start)
> +{
> + struct hot_range_item *hr;
> + int ret;
> +
> +again:
> + spin_lock(>lock);
> + hr = radix_tree_lookup(>hot_range_tree, start);
> + if (hr) {
> + kref_get(>hot_range.refs);
> + spin_unlock(>lock);
> + return hr;
> + }
> + spin_unlock(>lock);
> +
> + hr = kmem_cache_zalloc(hot_range_item_cachep,
> + GFP_KERNEL | GFP_NOFS);
Likewise, here too.

Steve.



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-05 Thread Steven Whitehouse
Hi,

On Mon, 2012-10-29 at 12:30 +0800, zwu.ker...@gmail.com wrote:
 From: Zhi Yong Wu wu...@linux.vnet.ibm.com
 
   Add some util helpers to update access frequencies
 for one file or its range.
 
 Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com
 ---
  fs/hot_tracking.c|  179 
 ++
  fs/hot_tracking.h|7 ++
  include/linux/hot_tracking.h |2 +
  3 files changed, 188 insertions(+), 0 deletions(-)
 
 diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
 index 68591f0..0a7d9a3 100644
 --- a/fs/hot_tracking.c
 +++ b/fs/hot_tracking.c
 @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
   }
  }
  
 +struct hot_inode_item
 +*hot_inode_item_find(struct hot_info *root, u64 ino)
 +{
 + struct hot_inode_item *he;
 + int ret;
 +
 +again:
 + spin_lock(root-lock);
 + he = radix_tree_lookup(root-hot_inode_tree, ino);
 + if (he) {
 + kref_get(he-hot_inode.refs);
 + spin_unlock(root-lock);
 + return he;
 + }
 + spin_unlock(root-lock);
 +
 + he = kmem_cache_zalloc(hot_inode_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
This doesn't look quite right... which of these two did you mean? I
assume probably just GFP_NOFS

 + if (!he)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_inode_item_init(he, ino, root-hot_inode_tree);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(root-lock);
 + ret = radix_tree_insert(root-hot_inode_tree, ino, he);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 + goto again;
 + }
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 +
 + kref_get(he-hot_inode.refs);
 + return he;
 +}
 +EXPORT_SYMBOL_GPL(hot_inode_item_find);
 +
 +static struct hot_range_item
 +*hot_range_item_find(struct hot_inode_item *he,
 + u32 start)
 +{
 + struct hot_range_item *hr;
 + int ret;
 +
 +again:
 + spin_lock(he-lock);
 + hr = radix_tree_lookup(he-hot_range_tree, start);
 + if (hr) {
 + kref_get(hr-hot_range.refs);
 + spin_unlock(he-lock);
 + return hr;
 + }
 + spin_unlock(he-lock);
 +
 + hr = kmem_cache_zalloc(hot_range_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
Likewise, here too.

Steve.



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-11-05 Thread Zhi Yong Wu
On Mon, Nov 5, 2012 at 7:07 PM, Steven Whitehouse swhit...@redhat.com wrote:
 Hi,

 On Mon, 2012-10-29 at 12:30 +0800, zwu.ker...@gmail.com wrote:
 From: Zhi Yong Wu wu...@linux.vnet.ibm.com

   Add some util helpers to update access frequencies
 for one file or its range.

 Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com
 ---
  fs/hot_tracking.c|  179 
 ++
  fs/hot_tracking.h|7 ++
  include/linux/hot_tracking.h |2 +
  3 files changed, 188 insertions(+), 0 deletions(-)

 diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
 index 68591f0..0a7d9a3 100644
 --- a/fs/hot_tracking.c
 +++ b/fs/hot_tracking.c
 @@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
   }
  }

 +struct hot_inode_item
 +*hot_inode_item_find(struct hot_info *root, u64 ino)
 +{
 + struct hot_inode_item *he;
 + int ret;
 +
 +again:
 + spin_lock(root-lock);
 + he = radix_tree_lookup(root-hot_inode_tree, ino);
 + if (he) {
 + kref_get(he-hot_inode.refs);
 + spin_unlock(root-lock);
 + return he;
 + }
 + spin_unlock(root-lock);
 +
 + he = kmem_cache_zalloc(hot_inode_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 This doesn't look quite right... which of these two did you mean? I
 assume probably just GFP_NOFS
Yes, good catch, thanks.

 + if (!he)
 + return ERR_PTR(-ENOMEM);
 +
 + hot_inode_item_init(he, ino, root-hot_inode_tree);
 +
 + ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
 + if (ret) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + return ERR_PTR(ret);
 + }
 +
 + spin_lock(root-lock);
 + ret = radix_tree_insert(root-hot_inode_tree, ino, he);
 + if (ret == -EEXIST) {
 + kmem_cache_free(hot_inode_item_cachep, he);
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 + goto again;
 + }
 + spin_unlock(root-lock);
 + radix_tree_preload_end();
 +
 + kref_get(he-hot_inode.refs);
 + return he;
 +}
 +EXPORT_SYMBOL_GPL(hot_inode_item_find);
 +
 +static struct hot_range_item
 +*hot_range_item_find(struct hot_inode_item *he,
 + u32 start)
 +{
 + struct hot_range_item *hr;
 + int ret;
 +
 +again:
 + spin_lock(he-lock);
 + hr = radix_tree_lookup(he-hot_range_tree, start);
 + if (hr) {
 + kref_get(hr-hot_range.refs);
 + spin_unlock(he-lock);
 + return hr;
 + }
 + spin_unlock(he-lock);
 +
 + hr = kmem_cache_zalloc(hot_range_item_cachep,
 + GFP_KERNEL | GFP_NOFS);
 Likewise, here too.
ditto

 Steve.






-- 
Regards,

Zhi Yong Wu
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-10-28 Thread zwu . kernel
From: Zhi Yong Wu 

  Add some util helpers to update access frequencies
for one file or its range.

Signed-off-by: Zhi Yong Wu 
---
 fs/hot_tracking.c|  179 ++
 fs/hot_tracking.h|7 ++
 include/linux/hot_tracking.h |2 +
 3 files changed, 188 insertions(+), 0 deletions(-)

diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
index 68591f0..0a7d9a3 100644
--- a/fs/hot_tracking.c
+++ b/fs/hot_tracking.c
@@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
}
 }
 
+struct hot_inode_item
+*hot_inode_item_find(struct hot_info *root, u64 ino)
+{
+   struct hot_inode_item *he;
+   int ret;
+
+again:
+   spin_lock(>lock);
+   he = radix_tree_lookup(>hot_inode_tree, ino);
+   if (he) {
+   kref_get(>hot_inode.refs);
+   spin_unlock(>lock);
+   return he;
+   }
+   spin_unlock(>lock);
+
+   he = kmem_cache_zalloc(hot_inode_item_cachep,
+   GFP_KERNEL | GFP_NOFS);
+   if (!he)
+   return ERR_PTR(-ENOMEM);
+
+   hot_inode_item_init(he, ino, >hot_inode_tree);
+
+   ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
+   if (ret) {
+   kmem_cache_free(hot_inode_item_cachep, he);
+   return ERR_PTR(ret);
+   }
+
+   spin_lock(>lock);
+   ret = radix_tree_insert(>hot_inode_tree, ino, he);
+   if (ret == -EEXIST) {
+   kmem_cache_free(hot_inode_item_cachep, he);
+   spin_unlock(>lock);
+   radix_tree_preload_end();
+   goto again;
+   }
+   spin_unlock(>lock);
+   radix_tree_preload_end();
+
+   kref_get(>hot_inode.refs);
+   return he;
+}
+EXPORT_SYMBOL_GPL(hot_inode_item_find);
+
+static struct hot_range_item
+*hot_range_item_find(struct hot_inode_item *he,
+   u32 start)
+{
+   struct hot_range_item *hr;
+   int ret;
+
+again:
+   spin_lock(>lock);
+   hr = radix_tree_lookup(>hot_range_tree, start);
+   if (hr) {
+   kref_get(>hot_range.refs);
+   spin_unlock(>lock);
+   return hr;
+   }
+   spin_unlock(>lock);
+
+   hr = kmem_cache_zalloc(hot_range_item_cachep,
+   GFP_KERNEL | GFP_NOFS);
+   if (!hr)
+   return ERR_PTR(-ENOMEM);
+
+   hot_range_item_init(hr, start, he);
+
+   ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
+   if (ret) {
+   kmem_cache_free(hot_range_item_cachep, hr);
+   return ERR_PTR(ret);
+   }
+
+   spin_lock(>lock);
+   ret = radix_tree_insert(>hot_range_tree, start, hr);
+   if (ret == -EEXIST) {
+   kmem_cache_free(hot_range_item_cachep, hr);
+   spin_unlock(>lock);
+   radix_tree_preload_end();
+   goto again;
+   }
+   spin_unlock(>lock);
+   radix_tree_preload_end();
+
+   kref_get(>hot_range.refs);
+   return hr;
+}
+
+/*
+ * This function does the actual work of updating
+ * the frequency numbers, whatever they turn out to be.
+ */
+static u64 hot_average_update(struct timespec old_atime,
+   struct timespec cur_time, u64 old_avg)
+{
+   struct timespec delta_ts;
+   u64 new_avg;
+   u64 new_delta;
+
+   delta_ts = timespec_sub(cur_time, old_atime);
+   new_delta = timespec_to_ns(_ts) >> FREQ_POWER;
+
+   new_avg = (old_avg << FREQ_POWER) - old_avg + new_delta;
+   new_avg = new_avg >> FREQ_POWER;
+
+   return new_avg;
+}
+
+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;
+   freq_data->avg_delta_writes = hot_average_update(
+   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;
+   freq_data->avg_delta_reads = hot_average_update(
+   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.
  */
@@ -199,6 +330,54 @@ 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, u64 start,
+   u64 len, int rw)
+{
+   struct hot_info *root = inode->i_sb->s_hot_root;
+   struct hot_inode_item *he;
+   struct hot_range_item *hr;
+   u32 cur, end;
+
+   if (!root || (len == 0))
+   

[RFC v4+ hot_track 03/19] vfs: add I/O frequency update function

2012-10-28 Thread zwu . kernel
From: Zhi Yong Wu wu...@linux.vnet.ibm.com

  Add some util helpers to update access frequencies
for one file or its range.

Signed-off-by: Zhi Yong Wu wu...@linux.vnet.ibm.com
---
 fs/hot_tracking.c|  179 ++
 fs/hot_tracking.h|7 ++
 include/linux/hot_tracking.h |2 +
 3 files changed, 188 insertions(+), 0 deletions(-)

diff --git a/fs/hot_tracking.c b/fs/hot_tracking.c
index 68591f0..0a7d9a3 100644
--- a/fs/hot_tracking.c
+++ b/fs/hot_tracking.c
@@ -172,6 +172,137 @@ static void hot_inode_tree_exit(struct hot_info *root)
}
 }
 
+struct hot_inode_item
+*hot_inode_item_find(struct hot_info *root, u64 ino)
+{
+   struct hot_inode_item *he;
+   int ret;
+
+again:
+   spin_lock(root-lock);
+   he = radix_tree_lookup(root-hot_inode_tree, ino);
+   if (he) {
+   kref_get(he-hot_inode.refs);
+   spin_unlock(root-lock);
+   return he;
+   }
+   spin_unlock(root-lock);
+
+   he = kmem_cache_zalloc(hot_inode_item_cachep,
+   GFP_KERNEL | GFP_NOFS);
+   if (!he)
+   return ERR_PTR(-ENOMEM);
+
+   hot_inode_item_init(he, ino, root-hot_inode_tree);
+
+   ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
+   if (ret) {
+   kmem_cache_free(hot_inode_item_cachep, he);
+   return ERR_PTR(ret);
+   }
+
+   spin_lock(root-lock);
+   ret = radix_tree_insert(root-hot_inode_tree, ino, he);
+   if (ret == -EEXIST) {
+   kmem_cache_free(hot_inode_item_cachep, he);
+   spin_unlock(root-lock);
+   radix_tree_preload_end();
+   goto again;
+   }
+   spin_unlock(root-lock);
+   radix_tree_preload_end();
+
+   kref_get(he-hot_inode.refs);
+   return he;
+}
+EXPORT_SYMBOL_GPL(hot_inode_item_find);
+
+static struct hot_range_item
+*hot_range_item_find(struct hot_inode_item *he,
+   u32 start)
+{
+   struct hot_range_item *hr;
+   int ret;
+
+again:
+   spin_lock(he-lock);
+   hr = radix_tree_lookup(he-hot_range_tree, start);
+   if (hr) {
+   kref_get(hr-hot_range.refs);
+   spin_unlock(he-lock);
+   return hr;
+   }
+   spin_unlock(he-lock);
+
+   hr = kmem_cache_zalloc(hot_range_item_cachep,
+   GFP_KERNEL | GFP_NOFS);
+   if (!hr)
+   return ERR_PTR(-ENOMEM);
+
+   hot_range_item_init(hr, start, he);
+
+   ret = radix_tree_preload(GFP_NOFS  ~__GFP_HIGHMEM);
+   if (ret) {
+   kmem_cache_free(hot_range_item_cachep, hr);
+   return ERR_PTR(ret);
+   }
+
+   spin_lock(he-lock);
+   ret = radix_tree_insert(he-hot_range_tree, start, hr);
+   if (ret == -EEXIST) {
+   kmem_cache_free(hot_range_item_cachep, hr);
+   spin_unlock(he-lock);
+   radix_tree_preload_end();
+   goto again;
+   }
+   spin_unlock(he-lock);
+   radix_tree_preload_end();
+
+   kref_get(hr-hot_range.refs);
+   return hr;
+}
+
+/*
+ * This function does the actual work of updating
+ * the frequency numbers, whatever they turn out to be.
+ */
+static u64 hot_average_update(struct timespec old_atime,
+   struct timespec cur_time, u64 old_avg)
+{
+   struct timespec delta_ts;
+   u64 new_avg;
+   u64 new_delta;
+
+   delta_ts = timespec_sub(cur_time, old_atime);
+   new_delta = timespec_to_ns(delta_ts)  FREQ_POWER;
+
+   new_avg = (old_avg  FREQ_POWER) - old_avg + new_delta;
+   new_avg = new_avg  FREQ_POWER;
+
+   return new_avg;
+}
+
+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;
+   freq_data-avg_delta_writes = hot_average_update(
+   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;
+   freq_data-avg_delta_reads = hot_average_update(
+   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.
  */
@@ -199,6 +330,54 @@ 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, u64 start,
+   u64 len, int rw)
+{
+   struct hot_info *root = inode-i_sb-s_hot_root;
+   struct hot_inode_item *he;
+   struct