nilfs2: add cache framework for persistent object allocator
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Sat, 14 Nov 2009 06:54:27 +0000 (15:54 +0900)
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Fri, 20 Nov 2009 01:05:50 +0000 (10:05 +0900)
This adds setup and cleanup routines of the persistent object
allocator cache.

According to ftrace analyses, accessing buffers of the DAT file
suffers indispensable overhead many times.  To mitigate the overhead,
This introduce cache framework for the persistent object allocator
(palloc) which the DAT file and ifile are using.

struct nilfs_palloc_cache represents the cache object per metadata
file using palloc.

The cache is initialized through nilfs_palloc_setup_cache() and
destroyed by nilfs_palloc_destroy_cache(); callers of the former
function will be added to individual allocators of DAT and ifile on
successive patches.

nilfs_palloc_destroy_cache() will be called from nilfs_mdt_destroy()
if the cache is attached to a metadata file.  A companion function
nilfs_palloc_clear_cache() is provided to allow releasing buffer head
references independently with the cleanup task.  This adjunctive
function will be used before invalidating pages of metadata file with
the cache.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
fs/nilfs2/alloc.c
fs/nilfs2/alloc.h
fs/nilfs2/mdt.c
fs/nilfs2/mdt.h

index 7e2b3ce57aa9b690e394b8b5f51ac60695633d0f..c56300d8d177776db633c6a6e96180dcf74aef3a 100644 (file)
@@ -491,3 +491,30 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
        }
        return 0;
 }
+
+void nilfs_palloc_setup_cache(struct inode *inode,
+                             struct nilfs_palloc_cache *cache)
+{
+       NILFS_MDT(inode)->mi_palloc_cache = cache;
+       spin_lock_init(&cache->lock);
+}
+
+void nilfs_palloc_clear_cache(struct inode *inode)
+{
+       struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;
+
+       spin_lock(&cache->lock);
+       brelse(cache->prev_desc.bh);
+       brelse(cache->prev_bitmap.bh);
+       brelse(cache->prev_entry.bh);
+       cache->prev_desc.bh = NULL;
+       cache->prev_bitmap.bh = NULL;
+       cache->prev_entry.bh = NULL;
+       spin_unlock(&cache->lock);
+}
+
+void nilfs_palloc_destroy_cache(struct inode *inode)
+{
+       nilfs_palloc_clear_cache(inode);
+       NILFS_MDT(inode)->mi_palloc_cache = NULL;
+}
index 4ace5475c2c7a10b61bd90aa1ba3fd2985aa2454..f4543ac4f56068d539b80b156e4096acd3c5e5ca 100644 (file)
@@ -69,4 +69,25 @@ int nilfs_palloc_freev(struct inode *, __u64 *, size_t);
 #define nilfs_clear_bit_atomic         ext2_clear_bit_atomic
 #define nilfs_find_next_zero_bit       ext2_find_next_zero_bit
 
+/*
+ * persistent object allocator cache
+ */
+
+struct nilfs_bh_assoc {
+       unsigned long blkoff;
+       struct buffer_head *bh;
+};
+
+struct nilfs_palloc_cache {
+       spinlock_t lock;
+       struct nilfs_bh_assoc prev_desc;
+       struct nilfs_bh_assoc prev_bitmap;
+       struct nilfs_bh_assoc prev_entry;
+};
+
+void nilfs_palloc_setup_cache(struct inode *inode,
+                             struct nilfs_palloc_cache *cache);
+void nilfs_palloc_clear_cache(struct inode *inode);
+void nilfs_palloc_destroy_cache(struct inode *inode);
+
 #endif /* _NILFS_ALLOC_H */
index 948b1f8bc505699fad5cb6936f54969045df21ac..06713ffcc7f2dc2f6a668e35c46e97e64be15884 100644 (file)
@@ -571,6 +571,8 @@ void nilfs_mdt_destroy(struct inode *inode)
 {
        struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
 
+       if (mdi->mi_palloc_cache)
+               nilfs_palloc_destroy_cache(inode);
        nilfs_mdt_clear(inode);
 
        kfree(mdi->mi_bgl); /* kfree(NULL) is safe */
index c396b6c03931bf091054174452bb9a1dd80eca8d..6c4bbb0470fc10d71206f27c3f7181a80960e7de 100644 (file)
@@ -36,6 +36,7 @@
  * @mi_entry_size: size of an entry
  * @mi_first_entry_offset: offset to the first entry
  * @mi_entries_per_block: number of entries in a block
+ * @mi_palloc_cache: persistent object allocator cache
  * @mi_blocks_per_group: number of blocks in a group
  * @mi_blocks_per_desc_block: number of blocks per descriptor block
  */
@@ -46,6 +47,7 @@ struct nilfs_mdt_info {
        unsigned                mi_entry_size;
        unsigned                mi_first_entry_offset;
        unsigned long           mi_entries_per_block;
+       struct nilfs_palloc_cache *mi_palloc_cache;
        unsigned long           mi_blocks_per_group;
        unsigned long           mi_blocks_per_desc_block;
 };