Whamcloud - gitweb
- b_hd_audit landing
[fs/lustre-release.git] / lustre / smfs / cache_space.c
index 31fcd56..bbbdf0b 100644 (file)
 #include "smfs_internal.h"
 
 struct cache_purge_param {
-        int nfract;     /* Percentage of cache dirty to activate cpurge */
-        int ndirty;     /* Maximum number of objects to write out per
-                           wake-cycle */
-        int interval;   /* jiffies delay between cache purge */
-        int nfract_sync;/* Percentage of cache dirty to activate
-                           cpurge synchronously */
-        int nfract_stop_cpurge; /* Percentage of cache dirty to stop cpurge */
+        int nfract;             /* percentage of cache dirty to activate
+                                 * cpurge */
+        int ndirty;             /* maximum number of objects to write out per
+                                   wake-cycle */
+        int interval;           /* jiffies delay between cache purge */
+        int nfract_sync;        /* percentage of cache dirty to activate cpurge
+                                   synchronously */
+        int nfract_stop_cpurge; /* percentage of cache dirty to stop cpurge */
 } cf_prm = {30, 512, 600 * HZ, 60, 20};
 
 static struct cache_purge_queue smfs_cpq;
 static struct cache_purge_queue *cpq = &smfs_cpq;
 
-#define CACHE_HOOK "cache_hook"
-int cache_space_pre_hook(struct inode *inode, void *dentry,
-                         void *data1, void *data2, int op, void *handle)
-{
-        int rc = 0;
-        ENTRY;
-
-        if (smfs_cache_hook(inode)) {                                          
-               if (!handle) {                                                  
-                        handle = smfs_trans_start(inode, KML_CACHE_NOOP, NULL);   
-                        if (IS_ERR(handle)) {                                   
-                                RETURN(PTR_ERR(handle));
-                        }                                                       
-                }                                                               
-                cache_space_pre(inode, op);                                       
-        }                                                                       
-        RETURN(rc); 
-}
-
-int cache_space_post_hook(struct inode *inode, void *de, void *data1, 
-                          void *data2, int op, void *handle)
-{
-        int rc = 0;
-        ENTRY;
-        if (smfs_cache_hook(inode)) {      
-                struct inode *new_inode = (struct inode*)data1;
-                struct dentry *new_dentry = (struct dentry*)data2;        
-                struct dentry *dentry = (struct dentry *)de;
-            
-                LASSERT(handle != NULL);                                
-                rc = cache_space_post(op, handle, inode, dentry, new_inode, 
-                                      new_dentry);
-        }
-        RETURN(rc);                                                               
-}
-
-int cache_space_hook_init(struct super_block *sb)
-{
-        struct smfs_super_info *smfs_info = S2SMI(sb);
-        struct smfs_hook_ops    *cache_hops;
-        int    rc = 0;
-        ENTRY;
-
-        cache_hops = smfs_alloc_hook_ops(CACHE_HOOK, cache_space_pre_hook, 
-                                         cache_space_post_hook);
-        if (!cache_hops) {
-                RETURN(-ENOMEM);
-        }
-        rc = smfs_register_hook_ops(smfs_info, cache_hops); 
-        if (rc) {
-                smfs_free_hook_ops(cache_hops);
-                RETURN(rc);
-        }
-        SMFS_SET_CACHE_HOOK(smfs_info);
-
-        RETURN(0);
-}
-
-int cache_space_hook_exit(struct smfs_super_info *smfs_info)
-{
-        struct smfs_hook_ops *cache_hops; 
-
-        cache_hops = smfs_unregister_hook_ops(smfs_info, CACHE_HOOK);
-        smfs_free_hook_ops(cache_hops);
-
-        SMFS_CLEAN_CACHE_HOOK(smfs_info);
-        return 0;
-}
-
 static int cache_leaf_node(struct dentry *dentry, __u64 *active_entry)
 {
         struct inode *inode = dentry->d_inode;
 
+        if (!inode)
+                return 0;
+        
         if (S_ISDIR(inode->i_mode)) {
                 if (inode->i_nlink != 2)
                         return 0;
-                if (!strncmp(dentry->d_name.name, "lost+found", dentry->d_name.len))
+                if (!strncmp((char *)dentry->d_name.name,
+                             "lost+found", dentry->d_name.len))
                         return 0;
                 LASSERT(active_entry != NULL);
                 get_active_entry(inode, active_entry);
@@ -127,18 +63,19 @@ static int cache_leaf_node(struct dentry *dentry, __u64 *active_entry)
         } else {
                 if (inode->i_nlink != 1)
                         return 0;
-                if (!strncmp(dentry->d_name.name, KML_LOG_NAME, dentry->d_name.len) ||
-                    !strncmp(dentry->d_name.name, CACHE_LRU_LOG, dentry->d_name.len))
+                if (!strncmp((char *)dentry->d_name.name, KML_LOG_NAME, dentry->d_name.len) ||
+                    !strncmp((char *)dentry->d_name.name, CACHE_LRU_LOG, dentry->d_name.len))
                         return 0;
                 return 1;
         }
 }
+
 static int cache_pre_leaf_node(struct dentry *dentry, __u64 *active_entry, int op)
 {
         if (((op == 0 && dentry->d_inode->i_nlink == 0) ||
             (op == 1 && dentry->d_inode->i_nlink == 2)) &&
-            strncmp(dentry->d_name.name, KML_LOG_NAME, dentry->d_name.len) &&
-            strncmp(dentry->d_name.name, CACHE_LRU_LOG, dentry->d_name.len))
+            strncmp((char *)dentry->d_name.name, KML_LOG_NAME, dentry->d_name.len) &&
+            strncmp((char *)dentry->d_name.name, CACHE_LRU_LOG, dentry->d_name.len))
                 return 1;
         else if ((op == 2 && dentry->d_inode->i_nlink == 0) ||
                  (op == 3 && dentry->d_inode->i_nlink == 3)) {
@@ -154,38 +91,45 @@ static int set_lru_logcookie(struct inode *inode, void *handle,
 {
         struct fsfilt_operations *fsops = I2CSB(inode)->sm_fsfilt;
         int rc;
+        ENTRY;
+
         rc = fsops->fs_set_xattr(inode, handle, XATTR_SMFS_CACHE_LOGCOOKIE,
                                  logcookie, sizeof(*logcookie));
         RETURN(rc);
 }
+
 static int get_lru_logcookie(struct inode *inode, struct llog_cookie *logcookie)
 {
         struct fsfilt_operations *fsops = I2CSB(inode)->sm_fsfilt;
         int rc;
+        
+        ENTRY;
         rc = fsops->fs_get_xattr(inode, XATTR_SMFS_CACHE_LOGCOOKIE,
                                  logcookie, sizeof(*logcookie));
         RETURN(rc);
 }
 
-static int try2purge_from_cache(struct ll_fid cfid, struct ll_fid pfid)
+static int try2purge_from_cache(struct lustre_id cid,
+                                struct lustre_id pid)
 {
         struct inode *inode, *parent;
         struct super_block *sb = cpq->cpq_sb;
-        //struct llog_cookie logcookie;
         __u32 hoard_priority = 0;
         int rc = 0;
         ENTRY;
 
-        inode = iget(sb, cfid.id);
+        inode = iget(sb, cid.li_stc.u.e3s.l3s_ino);
         if (IS_ERR(inode)) {
                 CERROR("not existent inode: "LPX64"/%u\n",
-                       cfid.id, cfid.generation);
+                       cid.li_stc.u.e3s.l3s_ino,
+                       cid.li_stc.u.e3s.l3s_gen);
                 RETURN(-ENOENT);
         }
-        parent = iget(sb, pfid.id);
+        parent = iget(sb, pid.li_stc.u.e3s.l3s_ino);
         if (IS_ERR(parent)) {
                 CERROR("not existent inode: "LPX64"/%u\n",
-                       pfid.id, pfid.generation);
+                       pid.li_stc.u.e3s.l3s_ino,
+                       pid.li_stc.u.e3s.l3s_gen);
                 iput(inode);
                 RETURN(-ENOENT);
         }
@@ -227,9 +171,10 @@ static int cache_lru_get_rec_cb(struct llog_handle *llh,
 
         llr = (struct llog_lru_rec *)rec;
 
-        if (try2purge_from_cache(llr->llr_cfid, llr->llr_pfid)==1){
+        if (try2purge_from_cache(llr->llr_cid, llr->llr_pid)==1){
                 CDEBUG(D_INODE, "purge ino/gen "LPX64"/%u from cache\n",
-                       llr->llr_cfid.id, llr->llr_cfid.generation);
+                       llr->llr_cid.li_stc.u.e3s.l3s_ino,
+                       llr->llr_cid.li_stc.u.e3s.l3s_gen);
                 count --;
                 if (count == 0)
                         rc = LLOG_PROC_BREAK;
@@ -293,13 +238,16 @@ static int purge_some_cache(int *count)
 }
 
 #define CFLUSH_NR 512
+
 static void check_cache_space(void)
 {
         int state = cache_balance_state();
         ENTRY;
 
-        if (state < 0)
+        if (state < 0) {
+                EXIT;
                 return;
+        }
 
         wakeup_cpurge();
 
@@ -307,23 +255,17 @@ static void check_cache_space(void)
                 int count = CFLUSH_NR;
                 purge_some_cache(&count);
         }
-}
-
-void cache_space_pre(struct inode *inode, int op)
-{
-        ENTRY;
-
-        /* FIXME have not used op */
-        check_cache_space();
+        EXIT;
 }
 
 static int cache_space_hook_lru(struct inode *inode, struct inode *parent,
-                     void *handle, int op, int flags)
+                                int op, int flags)
 {
         struct fsfilt_operations *fsops = S2SMI(cpq->cpq_sb)->sm_fsfilt;
         struct llog_ctxt *ctxt = cpq->cpq_loghandle->lgh_ctxt;
         struct llog_lru_rec *llr = NULL;
         struct llog_cookie *logcookie = NULL;
+        void * handle = NULL;
         int cookie_size = sizeof(struct llog_cookie);
         int rc = 0, err;
         ENTRY;
@@ -337,33 +279,32 @@ static int cache_space_hook_lru(struct inode *inode, struct inode *parent,
         if (!logcookie)
                 GOTO(out, rc = -ENOMEM);
 
-        if (op & CACHE_SPACE_DELETE) {
+         if (op & CACHE_SPACE_DELETE) {
                 rc = get_lru_logcookie(inode, logcookie);
                 if (rc < 0)
-                        GOTO(out, rc);
+                        goto out;
 
                 if (logcookie->lgc_lgl.lgl_oid == 0) {
                         CWARN("inode %lu/%u is not in lru list\n",
                               inode->i_ino, inode->i_generation);
-                        GOTO(insert, rc = -ENOENT);
+                        rc = -ENOENT;
                 }
-                if (flags && llog_cat_half_bottom(logcookie, ctxt->loc_handle))
-                        GOTO(out, rc = 0);
-
-                rc = llog_cancel(ctxt, 1, logcookie, 0, NULL);
-                if (!rc) {
-                        memset(logcookie, 0, cookie_size);
-                        rc = set_lru_logcookie(inode, handle, logcookie);
+                else {
+                        rc = 0;
+                        if (flags && llog_cat_half_bottom(logcookie, ctxt->loc_handle))
+                               goto out;
+
+                        rc = llog_cancel(ctxt, 1, logcookie, 0, NULL);
+                        if (!rc) {
+                                memset(logcookie, 0, cookie_size);
+                                rc = set_lru_logcookie(inode, handle, logcookie);
+                        }
                         if (rc)
-                                GOTO(out, rc);
-                } else {
-                        CERROR("failed at llog_cancel: %d\n", rc);
-                        GOTO(out, rc);
+                                        goto out;
                 }
         }
 
-insert:
-        if (op & CACHE_SPACE_INSERT) {
+         if (op & CACHE_SPACE_INSERT) {
                 LASSERT(parent != NULL);
                 OBD_ALLOC(llr, sizeof(*llr));
                 if (llr == NULL)
@@ -371,12 +312,15 @@ insert:
 
                 llr->llr_hdr.lrh_len = llr->llr_tail.lrt_len = sizeof(*llr);
                 llr->llr_hdr.lrh_type = CACHE_LRU_REC;
-                llr->llr_cfid.id = inode->i_ino;
-                llr->llr_cfid.generation = inode->i_generation;
-                llr->llr_cfid.f_type = inode->i_mode & S_IFMT;
-                llr->llr_pfid.id = parent->i_ino;
-                llr->llr_pfid.generation = parent->i_generation;
-                llr->llr_pfid.f_type = parent->i_mode & S_IFMT;
+
+                /* FIXME-UMKA: should we setup fid components here? */
+                id_ino(&llr->llr_cid) = inode->i_ino;
+                id_gen(&llr->llr_cid) = inode->i_generation;
+                id_type(&llr->llr_cid) = inode->i_mode & S_IFMT;
+
+                id_ino(&llr->llr_pid) = parent->i_ino;
+                id_gen(&llr->llr_pid) = parent->i_generation;
+                id_type(&llr->llr_pid) = parent->i_mode & S_IFMT;
 
                 rc = llog_add(ctxt, &llr->llr_hdr, NULL, logcookie, 1,
                               NULL, NULL, NULL);
@@ -438,82 +382,22 @@ static int cache_purge_thread(void *args)
         }
         cpq->cpq_flags = SVC_STOPPED;
         complete(&cpq->cpq_comp);
-        return 0;
-}
-
-int cache_space_hook_setup(struct super_block *sb)
-{
-        struct llog_ctxt *ctxt;
-        int rc;
-        ENTRY;
-
-        /* first to initialize the cache lru catalog on local fs */
-        rc = llog_catalog_setup(&ctxt, CACHE_LRU_LOG,
-                                S2SMI(sb)->smsi_exp,
-                                S2SMI(sb)->smsi_ctxt,
-                                S2SMI(sb)->sm_fsfilt,
-                                S2SMI(sb)->smsi_logs_dir,
-                                S2SMI(sb)->smsi_objects_dir);
-        if (rc) {
-                CERROR("failed to initialize cache lru list catalog %d\n", rc);
-                RETURN(rc);
-        }
-        cpq->cpq_sb = sb;
-        cpq->cpq_loghandle = ctxt->loc_handle;
-
-        /* start cache purge daemon, only one daemon now */
-        init_waitqueue_head(&cpq->cpq_waitq);
-        init_completion(&cpq->cpq_comp);
-        cpq->cpq_flags = 0;
-
-        rc = kernel_thread(cache_purge_thread, NULL, CLONE_VM | CLONE_FILES);
-        if (rc < 0) {
-                CERROR("cannot start thread: %d\n", rc);
-                GOTO(err_out, rc);
-        }
-        wait_for_completion(&cpq->cpq_comp);
-
         RETURN(0);
-err_out:
-        llog_catalog_cleanup(ctxt);
-        OBD_FREE(ctxt, sizeof(*ctxt));
-        RETURN(rc);
-}
-
-int cache_space_hook_cleanup(void)
-{
-        struct llog_ctxt *ctxt;
-        int rc;
-        ENTRY;
-
-        init_completion(&cpq->cpq_comp);
-        cpq->cpq_flags = SVC_STOPPING;
-        wake_up(&cpq->cpq_waitq);
-        wait_for_completion(&cpq->cpq_comp);
-        
-        ctxt = cpq->cpq_loghandle->lgh_ctxt;
-        rc = llog_catalog_cleanup(ctxt);
-        OBD_FREE(ctxt, sizeof(*ctxt));
-        if (rc)
-                CERROR("failed to clean up cache lru list catalog %d\n", rc);
-
-        RETURN(rc);
 }
 
-static int cache_space_hook_create(void *handle, struct inode *dir,
-                                   struct dentry *dentry, struct inode *new_dir,
-                                   struct dentry *new_dentry)
+/* Hooks */
+static int cache_space_hook_create (struct inode *dir, struct dentry * dentry)
 {
         __u64 active_entry = 0;
         int rc;
+        ENTRY;
 
         LASSERT(cache_leaf_node(dentry, NULL));
-        rc = cache_space_hook_lru(dentry->d_inode, dir, handle,
-                                  CACHE_SPACE_INSERT, 0);
+        rc = cache_space_hook_lru(dentry->d_inode, dir, CACHE_SPACE_INSERT, 0);
         if (rc)
                 RETURN(rc);
         if (cache_leaf_node(dentry->d_parent, &active_entry)) {
-                rc = cache_space_hook_lru(dir,NULL,handle,CACHE_SPACE_DELETE,0);
+                rc = cache_space_hook_lru(dir, NULL, CACHE_SPACE_DELETE, 0);
                 if (rc)
                         RETURN(rc);
         }
@@ -521,37 +405,37 @@ static int cache_space_hook_create(void *handle, struct inode *dir,
                 rc = get_active_entry(dir, &active_entry);
         active_entry ++;
         if (!rc)
-                rc = set_active_entry(dir, &active_entry, handle);
+                rc = set_active_entry(dir, &active_entry, NULL);
         RETURN(rc);
 }
-static int cache_space_hook_lookup(void *handle, struct inode *dir,
-                                   struct dentry *dentry, struct inode *new_dir,
-                                   struct dentry *new_dentry)
+
+static int cache_space_hook_lookup(struct inode *dir, struct dentry *dentry)
 {
         __u64 active_entry;
         int rc = 0;
+        ENTRY;
 
         if (cache_leaf_node(dentry, &active_entry))
-                rc = cache_space_hook_lru(dentry->d_inode, dir, handle,
-                                CACHE_SPACE_DELETE | CACHE_SPACE_INSERT,1);
+                rc = cache_space_hook_lru(dentry->d_inode, dir, 
+                                          CACHE_SPACE_DELETE | CACHE_SPACE_INSERT, 1);
         RETURN(rc);
 }
-static int cache_space_hook_link(void *handle, struct inode *dir,
-                                 struct dentry *dentry, struct inode *new_dir,
-                                 struct dentry *new_dentry)
+
+static int cache_space_hook_link(struct inode *dir, struct dentry *dentry)
 {
         __u64 active_entry = 0;
         int rc = 0;
+        ENTRY;
 
         if (cache_pre_leaf_node(dentry, NULL, 1)) {
-                rc = cache_space_hook_lru(dentry->d_inode, NULL,
-                                          handle, CACHE_SPACE_DELETE, 0);
+                rc = cache_space_hook_lru(dentry->d_inode, NULL, 
+                                          CACHE_SPACE_DELETE, 0);
                 if (rc)
                         RETURN(rc);
         }
 
         if (cache_leaf_node(dentry->d_parent, &active_entry)) {
-                rc = cache_space_hook_lru(dir,NULL,handle,CACHE_SPACE_DELETE,0);
+                rc = cache_space_hook_lru(dir, NULL, CACHE_SPACE_DELETE, 0);
                 if (rc)
                         RETURN(rc);
         }
@@ -560,81 +444,81 @@ static int cache_space_hook_link(void *handle, struct inode *dir,
                 rc = get_active_entry(dir, &active_entry);
         active_entry ++;
         if (!rc)
-                rc = set_active_entry(dir, &active_entry, handle);
+                rc = set_active_entry(dir, &active_entry, NULL);
         RETURN(rc);
 }
-static int cache_space_hook_unlink(void *handle, struct inode *dir,
-                                   struct dentry *dentry, struct inode *new_dir,
-                                   struct dentry *new_dentry)
+
+static int cache_space_hook_unlink(struct inode *dir, struct dentry *dentry)
 {
         __u64 active_entry;
         int rc = 0;
+        ENTRY;
 
         if (cache_pre_leaf_node(dentry, NULL, 0))
                 rc = cache_space_hook_lru(dentry->d_inode, NULL,
-                                          handle, CACHE_SPACE_DELETE, 0);
+                                          CACHE_SPACE_DELETE, 0);
         else if (cache_leaf_node(dentry, NULL))
                         rc = cache_space_hook_lru(dentry->d_inode, dir,
-                                                  handle, CACHE_SPACE_INSERT,0);
+                                                  CACHE_SPACE_INSERT,0);
         if (rc)
                 RETURN(rc);
 
         rc = get_active_entry(dir, &active_entry);
         active_entry --;
         if (!rc)
-                rc = set_active_entry(dir, &active_entry, handle);
+                rc = set_active_entry(dir, &active_entry, NULL);
         if (!rc && cache_leaf_node(dentry->d_parent, &active_entry))
                 rc = cache_space_hook_lru(dir,
                                           dentry->d_parent->d_parent->d_inode,
-                                          handle, CACHE_SPACE_INSERT, 0);
+                                          CACHE_SPACE_INSERT, 0);
         RETURN(rc);
 }
-static int cache_space_hook_mkdir(void *handle, struct inode *dir,
-                                  struct dentry *dentry, struct inode *new_dir,
-                                  struct dentry *new_dentry)
+
+static int cache_space_hook_mkdir(struct inode *dir, struct dentry *dentry)
 {
         __u64 active_entry;
         int rc;
+        ENTRY;
 
         LASSERT(cache_leaf_node(dentry, &active_entry));
-        rc = cache_space_hook_lru(dentry->d_inode, dir, handle,
-                                  CACHE_SPACE_INSERT,0);
+        rc = cache_space_hook_lru(dentry->d_inode, dir, CACHE_SPACE_INSERT, 0);
 
         if (!rc && cache_pre_leaf_node(dentry->d_parent, &active_entry, 3))
-                rc = cache_space_hook_lru(dir,NULL,handle,CACHE_SPACE_DELETE,0);
+                rc = cache_space_hook_lru(dir, NULL, CACHE_SPACE_DELETE, 0);
         RETURN(rc);
 }
-static int cache_space_hook_rmdir(void *handle, struct inode *dir,
-                                  struct dentry *dentry, struct inode *new_dir,
-                                  struct dentry *new_dentry)
+
+static int cache_space_hook_rmdir(struct inode *dir, struct dentry *dentry)
 {
         __u64 active_entry;
         int rc;
+        ENTRY;
 
         LASSERT(cache_pre_leaf_node(dentry, &active_entry, 2));
-        rc = cache_space_hook_lru(dentry->d_inode, NULL, handle,
+        rc = cache_space_hook_lru(dentry->d_inode, NULL, 
                                   CACHE_SPACE_DELETE, 0);
 
         if (!rc && cache_leaf_node(dentry->d_parent, &active_entry))
                 rc = cache_space_hook_lru(dir,
                                           dentry->d_parent->d_parent->d_inode,
-                                          handle, CACHE_SPACE_INSERT, 0);
+                                          CACHE_SPACE_INSERT, 0);
         RETURN(rc);
 }
-static int cache_space_hook_rename(void *handle, struct inode *old_dir,
-                        struct dentry *old_dentry, struct inode *new_dir,
-                        struct dentry *new_dentry)
+
+static int cache_space_hook_rename(struct inode *old_dir, struct dentry *old_dentry,
+                                   struct inode *new_dir, struct dentry *new_dentry)
 {
         __u64 active_entry;
         int rc = 0;
+        ENTRY;
 
         if (new_dentry->d_inode) {
                 if (cache_pre_leaf_node(new_dentry, NULL, 0))
                         rc = cache_space_hook_lru(new_dentry->d_inode, NULL,
-                                                  handle, CACHE_SPACE_DELETE,0);
+                                                  CACHE_SPACE_DELETE,0);
                 else if (cache_leaf_node(new_dentry, NULL))
                         rc = cache_space_hook_lru(new_dentry->d_inode,
-                                                  new_dir, handle,
+                                                  new_dir,
                                                   CACHE_SPACE_INSERT,0);
         }
 
@@ -643,7 +527,7 @@ static int cache_space_hook_rename(void *handle, struct inode *old_dir,
 
         if (!S_ISDIR(old_dentry->d_inode->i_mode)) {
                 if (cache_leaf_node(new_dentry->d_parent, &active_entry)) {
-                        rc = cache_space_hook_lru(new_dir, NULL, handle,
+                        rc = cache_space_hook_lru(new_dir, NULL,
                                                   CACHE_SPACE_DELETE, 0);
                         if (rc)
                                 RETURN(rc);
@@ -652,53 +536,253 @@ static int cache_space_hook_rename(void *handle, struct inode *old_dir,
                         rc = get_active_entry(new_dir, &active_entry);
                 active_entry ++;
                 if (!rc)
-                        rc = set_active_entry(new_dir, &active_entry, handle);
+                        rc = set_active_entry(new_dir, &active_entry, NULL);
                 if (rc)
                         RETURN(rc);
                 rc = get_active_entry(old_dir, &active_entry);
                 active_entry --;
                 if (!rc)
-                        rc = set_active_entry(old_dir, &active_entry, handle);
-        } else if (cache_pre_leaf_node(new_dentry->d_parent, &active_entry, 3))
-                rc = cache_space_hook_lru(new_dir, NULL, handle,
+                        rc = set_active_entry(old_dir, &active_entry, NULL);
+        } else if (cache_pre_leaf_node(new_dentry->d_parent, &active_entry, 3)) {
+                rc = cache_space_hook_lru(new_dir, NULL,
                                           CACHE_SPACE_DELETE, 0);
+        }
 
-        if (!rc && cache_leaf_node(old_dentry->d_parent, &active_entry))
+        if (!rc && cache_leaf_node(old_dentry->d_parent, &active_entry)) {
                 rc = cache_space_hook_lru(old_dir,
-                                        old_dentry->d_parent->d_parent->d_inode,
-                                        handle, CACHE_SPACE_INSERT, 0);
+                                          old_dentry->d_parent->d_parent->d_inode,
+                                          CACHE_SPACE_INSERT, 0);
+        }
+        
         RETURN(rc);
 }
 
-typedef int (*cache_hook_op)(void *handle, struct inode *old_dir,
-                             struct dentry *old_dentry, struct inode *new_dir,
-                             struct dentry *new_dentry);
-
-static  cache_hook_op cache_space_hook_ops[HOOK_MAX + 1] = {
-        [HOOK_CREATE]     cache_space_hook_create,
-        [HOOK_LOOKUP]     cache_space_hook_lookup,
-        [HOOK_LINK]       cache_space_hook_link,
-        [HOOK_UNLINK]     cache_space_hook_unlink,
-        [HOOK_SYMLINK]    cache_space_hook_create,
-        [HOOK_MKDIR]      cache_space_hook_mkdir,
-        [HOOK_RMDIR]      cache_space_hook_rmdir,
-        [HOOK_MKNOD]      cache_space_hook_create,
-        [HOOK_RENAME]     cache_space_hook_rename,
+static int lru_create (struct inode * inode, void * arg)
+{
+        struct hook_msg * msg = arg;
+        return cache_space_hook_create(inode, msg->dentry);
+}
+static int lru_lookup (struct inode * inode, void * arg)
+{
+        struct hook_msg * msg = arg;
+        return cache_space_hook_lookup(inode, msg->dentry);
+}
+static int lru_link (struct inode * inode, void * arg)
+{
+        struct hook_link_msg * msg = arg;
+        return cache_space_hook_link(inode, msg->dentry);
+}
+static int lru_unlink (struct inode * inode, void * arg)
+{
+        struct hook_unlink_msg * msg = arg;
+        return cache_space_hook_unlink(inode, msg->dentry);
+}
+static int lru_symlink (struct inode * inode, void * arg)
+{
+        struct hook_symlink_msg * msg = arg;
+        return cache_space_hook_create(inode, msg->dentry);
+}
+static int lru_mkdir (struct inode * inode, void * arg)
+{
+        struct hook_msg * msg = arg;
+        return cache_space_hook_mkdir(inode, msg->dentry);
+}
+static int lru_rmdir (struct inode * inode, void * arg)
+{
+        struct hook_unlink_msg * msg = arg;
+        return cache_space_hook_rmdir(inode, msg->dentry);
+}
+static int lru_rename (struct inode * inode, void * arg)
+{
+        struct hook_rename_msg * msg = arg;
+        return cache_space_hook_rename(inode, msg->dentry,
+                                       msg->new_dir, msg->new_dentry);
+}
+
+
+typedef int (*post_lru_op)(struct inode *inode, void * msg);
+static  post_lru_op smfs_lru_post[HOOK_MAX] = {
+        [HOOK_CREATE]     lru_create,
+        [HOOK_LOOKUP]     lru_lookup,
+        [HOOK_LINK]       lru_link,
+        [HOOK_UNLINK]     lru_unlink,
+        [HOOK_SYMLINK]    lru_symlink,
+        [HOOK_MKDIR]      lru_mkdir,
+        [HOOK_RMDIR]      lru_rmdir,
+        [HOOK_MKNOD]      lru_create,
+        [HOOK_RENAME]     lru_rename,
         [HOOK_SETATTR]    NULL,
         [HOOK_WRITE]      NULL,
+        [HOOK_READDIR]    NULL,
 };
 
-int cache_space_post(int op, void *handle, struct inode *old_dir,
-               struct dentry *old_dentry, struct inode *new_dir,
-               struct dentry *new_dentry)
+static int smfs_lru_pre_op(hook_op op, struct inode *inode, void * msg, int ret, 
+                           void *priv)
 {
         int rc = 0;
         ENTRY;
+        
+        /* FIXME have not used op */
+        check_cache_space();                                       
+                                                                               
+        RETURN(rc); 
+}
 
-        LASSERT(op <= HOOK_MAX + 1);
+static int smfs_lru_post_op(hook_op op, struct inode *inode, void *msg, int ret,
+                            void *priv)
+{
+        int rc = 0;
+        
+        ENTRY;
+        if (ret)
+                RETURN(0);
+        
+        if (smfs_lru_post[op])
+                rc = smfs_lru_post[op](inode, msg);
+        
+        RETURN(rc);                                                             
+}
 
-        if (cache_space_hook_ops[op]) 
-                rc = cache_space_hook_ops[op](handle, old_dir, old_dentry,
-                                              new_dir, new_dentry);
+/* Helpers */
+static int smfs_trans_lru (struct super_block *sb, void *arg, void * priv)
+{
+        int size;
+        
+        ENTRY;
+        
+        size = 20;//LDISKFS_INDEX_EXTRA_TRANS_BLOCKS+LDISKFS_DATA_TRANS_BLOCKS;
+        
+        RETURN(size);
+}
+
+static int smfs_start_lru(struct super_block *sb, void *arg, void * priv)
+{
+        int rc = 0;
+        struct smfs_super_info * smb = S2SMI(sb);
+        struct llog_ctxt *ctxt;
+        
+        ENTRY;
+        
+        if (SMFS_IS(smb->plg_flags, SMFS_PLG_LRU))
+                RETURN(0);
+
+        /* first to initialize the cache lru catalog on local fs */
+        rc = llog_catalog_setup(&ctxt, CACHE_LRU_LOG, smb->smsi_exp,
+                                smb->smsi_ctxt, smb->sm_fsfilt,
+                                smb->smsi_logs_dir,
+                                smb->smsi_objects_dir);
+        if (rc) {
+                CERROR("failed to initialize cache lru list catalog %d\n", rc);
+                RETURN(rc);
+        }
+        cpq->cpq_sb = sb;
+        cpq->cpq_loghandle = ctxt->loc_handle;
+
+        /* start cache purge daemon, only one daemon now */
+        init_waitqueue_head(&cpq->cpq_waitq);
+        init_completion(&cpq->cpq_comp);
+        cpq->cpq_flags = 0;
+
+        rc = kernel_thread(cache_purge_thread, NULL, CLONE_VM | CLONE_FILES);
+        if (rc < 0) {
+                CERROR("cannot start thread: %d\n", rc);
+                goto err_out;
+        }
+        wait_for_completion(&cpq->cpq_comp);
+
+        SMFS_SET(smb->plg_flags, SMFS_PLG_LRU);
+
+        RETURN(0);
+err_out:
+        llog_catalog_cleanup(ctxt);
+        OBD_FREE(ctxt, sizeof(*ctxt));
+        RETURN(rc);
+}
+
+static int smfs_stop_lru(struct super_block *sb, void *arg, void * priv)
+{
+        struct smfs_super_info * smb = S2SMI(sb);
+        struct llog_ctxt *ctxt;
+        int rc;
+        ENTRY;
+        
+        if (!SMFS_IS(smb->plg_flags, SMFS_PLG_LRU))
+                RETURN(0);
+
+        SMFS_CLEAR(smb->plg_flags, SMFS_PLG_LRU);
+
+        init_completion(&cpq->cpq_comp);
+        cpq->cpq_flags = SVC_STOPPING;
+        wake_up(&cpq->cpq_waitq);
+        wait_for_completion(&cpq->cpq_comp);
+        
+        ctxt = cpq->cpq_loghandle->lgh_ctxt;
+        rc = llog_catalog_cleanup(ctxt);
+        OBD_FREE(ctxt, sizeof(*ctxt));
+        RETURN(0);        
+}
+
+typedef int (*lru_helper)(struct super_block * sb, void *msg, void *);
+static lru_helper smfs_lru_helpers[PLG_HELPER_MAX] = {
+        [PLG_START]      smfs_start_lru,
+        [PLG_STOP]       smfs_stop_lru,
+        [PLG_TRANS_SIZE] smfs_trans_lru,
+        [PLG_TEST_INODE] NULL,
+        [PLG_SET_INODE]  NULL,
+};
+
+static int smfs_lru_help_op(int code, struct super_block * sb,
+                            void * arg, void * priv)
+{
+        ENTRY;
+        if (smfs_lru_helpers[code])
+                smfs_lru_helpers[code](sb, arg, priv);
+        RETURN(0);
+}
+
+static int smfs_exit_lru(struct super_block *sb, void * arg)
+{
+        struct smfs_plugin * plg;
+
+        ENTRY;
+
+        plg = smfs_deregister_plugin(sb, SMFS_PLG_LRU);
+        if (plg)
+                OBD_FREE(plg, sizeof(*plg));
+        else
+                CERROR("Cannot find LRU plugin while unregistering\n");
+  
+        EXIT;
+        return 0;
+}
+
+int smfs_init_lru(struct super_block *sb)
+{
+        struct smfs_plugin * plg = NULL;
+        int rc = 0;
+        
+        ENTRY;
+        
+        OBD_ALLOC(plg, sizeof(*plg));
+        if (!plg) {
+                rc = -ENOMEM;
+                goto exit;
+        }
+        
+        plg->plg_type = SMFS_PLG_LRU;
+        plg->plg_pre_op = &smfs_lru_pre_op;
+        plg->plg_post_op = &smfs_lru_post_op;
+        plg->plg_helper = &smfs_lru_help_op;
+        plg->plg_exit = &smfs_exit_lru;
+        
+        rc = smfs_register_plugin(sb, plg);
+        if (!rc)
+                RETURN(0);
+exit:
+        if (plg)
+                OBD_FREE(plg, sizeof(*plg));
+        
         RETURN(rc);
 }
+
+