From: "Luiz Fernando N. Capitulino" <[EMAIL PROTECTED]>

[PATCH]: VM tail statistics support

This patch is a hack which introduces initial statistics support
for the VM tail functionality.

It uses debugfs and does accouting of:

1. Number of times vm_file_tail_pack() have been called
2. Number of times vm_file_tail_unpack() have been called
3. Total size of file tails allocations
4. Number of file tail allocations
5. Bytes saved

Signed-off-by: Luiz Fernando N. Capitulino <[EMAIL PROTECTED]>
Signed-off-by: Dave Kleikamp <[EMAIL PROTECTED]>

---

 mm/file_tail.c |  127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 126 insertions(+), 1 deletion(-)

diff -Nurp linux008/mm/file_tail.c linux009/mm/file_tail.c
--- linux008/mm/file_tail.c     2007-11-08 10:49:46.000000000 -0600
+++ linux009/mm/file_tail.c     2007-11-08 10:49:46.000000000 -0600
@@ -12,10 +12,51 @@
 
 #include <linux/buffer_head.h>
 #include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
 #include <linux/hardirq.h>
 #include <linux/module.h>
+#include <linux/spinlock.h>
 #include <linux/vm_file_tail.h>
 
+struct {
+       struct dentry *root_dir;
+       struct dentry *nr_tails;
+       struct dentry *tail_size;
+       struct dentry *saved_bytes;
+       struct dentry *pack_called;
+       struct dentry *unpack_called;
+       struct dentry *read_called;
+} vm_tail_debugfs;
+
+struct {
+       u32 nr_tails;
+       u32 tail_size;
+       u32 saved_bytes;
+       u32 pack_called;
+       u32 unpack_called;
+       u32 read_called;
+       spinlock_t lock;
+} vm_tail_stats = { .lock = __SPIN_LOCK_UNLOCKED(lock) };
+
+static void vm_file_tail_stats_inc(int length)
+{
+       spin_lock(&vm_tail_stats.lock);
+       vm_tail_stats.nr_tails++;
+       vm_tail_stats.tail_size += length;
+       vm_tail_stats.saved_bytes += (PAGE_SIZE - length);
+       spin_unlock(&vm_tail_stats.lock);
+}
+
+static void vm_file_tail_stats_dec(int length)
+{
+       spin_lock(&vm_tail_stats.lock);
+       vm_tail_stats.nr_tails--;
+       vm_tail_stats.tail_size -= length;
+       vm_tail_stats.saved_bytes -= (PAGE_SIZE - length);
+       spin_unlock(&vm_tail_stats.lock);
+}
+
 /*
  * Free the file tail
  *
@@ -29,7 +70,10 @@ void __vm_file_tail_free(struct address_
 
        spin_lock_irqsave(&mapping->tail_lock, flags);
        tail = mapping->tail;
-       mapping->tail = NULL;
+       if (tail) {
+               vm_file_tail_stats_dec(vm_file_tail_length(mapping));
+               mapping->tail = NULL;
+       }
        spin_unlock_irqrestore(&mapping->tail_lock, flags);
        kfree(tail);
 }
@@ -49,6 +93,8 @@ void vm_file_tail_unpack(struct address_
        struct page *page;
        void *tail;
 
+       vm_tail_stats.unpack_called++;
+
        if (!mapping->tail)
                return;
 
@@ -85,6 +131,7 @@ void vm_file_tail_unpack(struct address_
                add_to_page_cache_lru(page, mapping, index, gfp_mask);
                unlock_page(page);
                page_cache_release(page);
+               vm_file_tail_stats_dec(length);
        } else
                /* Free the tail */
                __vm_file_tail_free(mapping);
@@ -120,6 +167,8 @@ int vm_file_tail_pack(struct page *page)
        struct address_space *mapping;
        void *tail;
 
+       vm_tail_stats.pack_called++;
+
        if (TestSetPageLocked(page))
                return 0;
 
@@ -163,12 +212,86 @@ int vm_file_tail_pack(struct page *page)
        remove_from_page_cache(page);
        page_cache_release(page);       /* pagecache ref */
        ret = 1;
+       vm_file_tail_stats_inc(length);
 
 out:
        unlock_page(page);
        return ret;
 }
 
+static int __init create_debugfs_file(const char *name, struct dentry **dir,
+                                     u32 *var)
+{
+       *dir = debugfs_create_u32(name, S_IFREG|S_IRUGO,
+                                 vm_tail_debugfs.root_dir, var);
+       if (!*dir) {
+               printk(KERN_ERR "ERROR: vm_tail: could not create %s\n", name);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static int __init vm_file_tail_init(void)
+{
+       int err;
+
+       vm_tail_debugfs.root_dir = debugfs_create_dir("vm_tail", NULL);
+       if (!vm_tail_debugfs.root_dir) {
+               printk(KERN_ERR "ERROR: %s Could not create root directory\n",
+                      __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       err = create_debugfs_file("nr_tails", &vm_tail_debugfs.nr_tails,
+                                 &vm_tail_stats.nr_tails);
+       if (err)
+               goto out_err;
+
+       err = create_debugfs_file("tail_size", &vm_tail_debugfs.tail_size,
+                                 &vm_tail_stats.tail_size);
+       if (err)
+               goto out_err1;
+
+       err = create_debugfs_file("saved_bytes", &vm_tail_debugfs.saved_bytes,
+                                 &vm_tail_stats.saved_bytes);
+       if (err)
+               goto out_err2;
+
+       err = create_debugfs_file("unpack_called",
+                                 &vm_tail_debugfs.unpack_called,
+                                 &vm_tail_stats.unpack_called);
+       if (err)
+               goto out_err3;
+
+       err = create_debugfs_file("pack_called", &vm_tail_debugfs.pack_called,
+                                 &vm_tail_stats.pack_called);
+       if (err)
+               goto out_err4;
+
+       err = create_debugfs_file("read_called", &vm_tail_debugfs.read_called,
+                                 &vm_tail_stats.read_called);
+       if (err)
+               goto out_err5;
+
+       return 0;
+
+out_err5:
+       debugfs_remove(vm_tail_debugfs.pack_called);
+out_err4:
+       debugfs_remove(vm_tail_debugfs.unpack_called);
+out_err3:
+       debugfs_remove(vm_tail_debugfs.saved_bytes);
+out_err2:
+       debugfs_remove(vm_tail_debugfs.tail_size);
+out_err1:
+       debugfs_remove(vm_tail_debugfs.nr_tails);
+out_err:
+       debugfs_remove(vm_tail_debugfs.root_dir);
+       return err;
+}
+
+postcore_initcall(vm_file_tail_init);
+
 void __vm_file_tail_unpack_on_resize(struct inode *inode, loff_t new_size)
 {
        loff_t old_size = i_size_read(inode);
@@ -211,6 +334,8 @@ int __vm_file_tail_read(struct file *fil
                return 0;
        }
 
+       vm_tail_stats.read_called++;
+
        size = vm_file_tail_length(mapping) - offset;
        if (size > count)
                size = count;
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to