Whamcloud - gitweb
* Added ior-survey (still being developed)
[fs/lustre-release.git] / lustre / smfs / cache_space.c
index a2f3133..674a264 100644 (file)
@@ -2,10 +2,10 @@
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
  *  lustre/smfs/cache_space.c
- *  A library of functions to manage cache space based on ARC 
+ *  A library of functions to manage cache space based on ARC
  *  (modified LRU) replacement algorithm.
- *  
- *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
+ *
+ *  Copyright (c) 2004 Cluster File Systems, Inc.
  *
  *   This file is part of Lustre, http://www.lustre.org.
  *
@@ -25,6 +25,7 @@
 #define DEBUG_SUBSYSTEM S_SM
 
 #include <linux/lustre_log.h>
+#include <linux/lustre_fsfilt.h>
 #include <linux/lustre_smfs.h>
 
 #include "smfs_internal.h"
@@ -34,7 +35,7 @@ struct cache_purge_param {
         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 
+        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};
@@ -42,35 +43,81 @@ struct cache_purge_param {
 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_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;
+
+        RETURN(0);
 }
-int cache_space_hook_exit(struct super_block *sb)
+
+int cache_space_hook_exit(struct smfs_super_info *smfs_info)
 {
-        struct smfs_super_info  *smfs_info = S2SMI(sb);
+        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;
 }
-int smfs_cache_hook(struct inode *inode)
-{
-        struct smfs_super_info  *smfs_info = I2CSB(inode);
-                                                                                                                             
-        if (SMFS_CACHE_HOOK(smfs_info) && SMFS_INIT_REC(smfs_info)
-            && SMFS_INODE_CACHE_HOOK(inode))
-                        return 1;
-        else
-                return 0;
-}
 
 static int cache_leaf_node(struct dentry *dentry, __u64 *active_entry)
 {
         struct inode *inode = dentry->d_inode;
 
+        if (!dentry->d_inode)
+                return 0;
         if (S_ISDIR(inode->i_mode)) {
                 if (inode->i_nlink != 2)
                         return 0;
@@ -133,13 +180,13 @@ static int try2purge_from_cache(struct ll_fid cfid, struct ll_fid pfid)
 
         inode = iget(sb, cfid.id);
         if (IS_ERR(inode)) {
-                CERROR("not existent inode: "LPX64"/%u\n", 
+                CERROR("not existent inode: "LPX64"/%u\n",
                        cfid.id, cfid.generation);
                 RETURN(-ENOENT);
         }
         parent = iget(sb, pfid.id);
         if (IS_ERR(parent)) {
-                CERROR("not existent inode: "LPX64"/%u\n", 
+                CERROR("not existent inode: "LPX64"/%u\n",
                        pfid.id, pfid.generation);
                 iput(inode);
                 RETURN(-ENOENT);
@@ -218,13 +265,13 @@ static int cache_balance_state(void)
         rc = fsops->fs_statfs(cpq->cpq_sb, &osfs);
         LASSERT(rc == 0);
 
-        free = (osfs.os_blocks - osfs.os_bfree) * 100; 
+        free = (osfs.os_blocks - osfs.os_bfree) * 100;
         if (free > cf_prm.nfract * osfs.os_blocks) {
                 if (free < cf_prm.nfract_sync)
                         return 1;
                 return 0;
         }
-        return -1; 
+        return -1;
 }
 
 void wakeup_cpurge(void)
@@ -272,12 +319,12 @@ void cache_space_pre(struct inode *inode, int op)
         check_cache_space();
 }
 
-static int cache_space_hook_lru(struct inode *inode, struct inode *parent, 
+static int cache_space_hook_lru(struct inode *inode, struct inode *parent,
                      void *handle, 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_lru_rec *llr = NULL;
         struct llog_cookie *logcookie = NULL;
         int cookie_size = sizeof(struct llog_cookie);
         int rc = 0, err;
@@ -294,13 +341,13 @@ static int cache_space_hook_lru(struct inode *inode, struct inode *parent,
 
         if (op & CACHE_SPACE_DELETE) {
                 rc = get_lru_logcookie(inode, logcookie);
-                if (rc < 0) 
+                if (rc < 0)
                         GOTO(out, rc);
 
                 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); 
+                        GOTO(insert, rc = -ENOENT);
                 }
                 if (flags && llog_cat_half_bottom(logcookie, ctxt->loc_handle))
                         GOTO(out, rc = 0);
@@ -322,7 +369,7 @@ insert:
                 LASSERT(parent != NULL);
                 OBD_ALLOC(llr, sizeof(*llr));
                 if (llr == NULL)
-                        GOTO(out, rc = -ENOMEM); 
+                        GOTO(out, rc = -ENOMEM);
 
                 llr->llr_hdr.lrh_len = llr->llr_tail.lrt_len = sizeof(*llr);
                 llr->llr_hdr.lrh_type = CACHE_LRU_REC;
@@ -333,7 +380,8 @@ insert:
                 llr->llr_pfid.generation = parent->i_generation;
                 llr->llr_pfid.f_type = parent->i_mode & S_IFMT;
 
-                rc = llog_add(ctxt, &llr->llr_hdr, NULL, logcookie, 1, NULL);
+                rc = llog_add(ctxt, &llr->llr_hdr, NULL, logcookie, 1,
+                              NULL, NULL, NULL);
                 if (rc != 1) {
                         CERROR("failed at llog_add: %d\n", rc);
                         GOTO(out, rc);
@@ -343,7 +391,7 @@ insert:
 
         if (op & CACHE_SPACE_COMMIT) {
                 if (handle) {
-                        err = fsops->fs_commit(inode, handle, 0);
+                        err = fsops->fs_commit(inode->i_sb, inode, handle, 0);
                         if (err) {
                                 CERROR("error committing transaction: %d\n", err);
                                 if (!rc)
@@ -351,7 +399,7 @@ insert:
                         }
                 }
         }
-out: 
+out:
         if (logcookie)
                 OBD_FREE(logcookie, cookie_size);
         if (llr)
@@ -381,11 +429,11 @@ static int cache_purge_thread(void *args)
 
                 purge_some_cache(&ndirty);
                 if (ndirty > 0 || cpurge_stop())
-                        l_wait_event(cpq->cpq_waitq, 
+                        l_wait_event(cpq->cpq_waitq,
                                      cpq->cpq_flags & SVC_STOPPING,
                                      &lwi);
                 if (cpq->cpq_flags & SVC_STOPPING) {
-                        cpq->cpq_flags &= ~SVC_STOPPING; 
+                        cpq->cpq_flags &= ~SVC_STOPPING;
                         EXIT;
                         break;
                 }
@@ -403,6 +451,7 @@ int cache_space_hook_setup(struct super_block *sb)
 
         /* 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,
@@ -412,7 +461,7 @@ int cache_space_hook_setup(struct super_block *sb)
                 RETURN(rc);
         }
         cpq->cpq_sb = sb;
-        cpq->cpq_loghandle = ctxt->loc_handle; 
+        cpq->cpq_loghandle = ctxt->loc_handle;
 
         /* start cache purge daemon, only one daemon now */
         init_waitqueue_head(&cpq->cpq_waitq);
@@ -429,11 +478,13 @@ int cache_space_hook_setup(struct super_block *sb)
         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;
 
@@ -441,9 +492,11 @@ int cache_space_hook_cleanup(void)
         cpq->cpq_flags = SVC_STOPPING;
         wake_up(&cpq->cpq_waitq);
         wait_for_completion(&cpq->cpq_comp);
-
-        rc = llog_catalog_cleanup(cpq->cpq_loghandle->lgh_ctxt);
-        if (rc) 
+        
+        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);
@@ -470,7 +523,7 @@ 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, handle);
         RETURN(rc);
 }
 static int cache_space_hook_lookup(void *handle, struct inode *dir,
@@ -480,7 +533,7 @@ static int cache_space_hook_lookup(void *handle, struct inode *dir,
         __u64 active_entry;
         int rc = 0;
 
-        if (cache_leaf_node(dentry, &active_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);
         RETURN(rc);
@@ -494,7 +547,7 @@ static int cache_space_hook_link(void *handle, struct inode *dir,
 
         if (cache_pre_leaf_node(dentry, NULL, 1)) {
                 rc = cache_space_hook_lru(dentry->d_inode, NULL,
-                                          handle, CACHE_SPACE_DELETE, 0); 
+                                          handle, CACHE_SPACE_DELETE, 0);
                 if (rc)
                         RETURN(rc);
         }
@@ -509,7 +562,7 @@ 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, handle);
         RETURN(rc);
 }
 static int cache_space_hook_unlink(void *handle, struct inode *dir,
@@ -520,7 +573,7 @@ static int cache_space_hook_unlink(void *handle, struct inode *dir,
         int rc = 0;
 
         if (cache_pre_leaf_node(dentry, NULL, 0))
-                rc = cache_space_hook_lru(dentry->d_inode, NULL, 
+                rc = cache_space_hook_lru(dentry->d_inode, NULL,
                                           handle, CACHE_SPACE_DELETE, 0);
         else if (cache_leaf_node(dentry, NULL))
                         rc = cache_space_hook_lru(dentry->d_inode, dir,
@@ -532,13 +585,13 @@ static int cache_space_hook_unlink(void *handle, struct inode *dir,
         active_entry --;
         if (!rc)
                 rc = set_active_entry(dir, &active_entry, handle);
-        if (!rc && cache_leaf_node(dentry->d_parent, &active_entry)) 
+        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);
         RETURN(rc);
 }
-static int cache_space_hook_mkdir(void *handle, struct inode *dir, 
+static int cache_space_hook_mkdir(void *handle, struct inode *dir,
                                   struct dentry *dentry, struct inode *new_dir,
                                   struct dentry *new_dentry)
 {
@@ -553,7 +606,7 @@ static int cache_space_hook_mkdir(void *handle, struct inode *dir,
                 rc = cache_space_hook_lru(dir,NULL,handle,CACHE_SPACE_DELETE,0);
         RETURN(rc);
 }
-static int cache_space_hook_rmdir(void *handle, struct inode *dir, 
+static int cache_space_hook_rmdir(void *handle, struct inode *dir,
                                   struct dentry *dentry, struct inode *new_dir,
                                   struct dentry *new_dentry)
 {
@@ -570,7 +623,7 @@ static int cache_space_hook_rmdir(void *handle, struct inode *dir,
                                           handle, CACHE_SPACE_INSERT, 0);
         RETURN(rc);
 }
-static int cache_space_hook_rename(void *handle, struct inode *old_dir, 
+static int cache_space_hook_rename(void *handle, struct inode *old_dir,
                         struct dentry *old_dentry, struct inode *new_dir,
                         struct dentry *new_dentry)
 {
@@ -622,28 +675,33 @@ static int cache_space_hook_rename(void *handle, struct inode *old_dir,
 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[CACHE_HOOK_MAX + 1] = {
-        [CACHE_HOOK_CREATE]     cache_space_hook_create,
-        [CACHE_HOOK_LOOKUP]     cache_space_hook_lookup,
-        [CACHE_HOOK_LINK]       cache_space_hook_link,
-        [CACHE_HOOK_UNLINK]     cache_space_hook_unlink,
-        [CACHE_HOOK_SYMLINK]    cache_space_hook_create,
-        [CACHE_HOOK_MKDIR]      cache_space_hook_mkdir,
-        [CACHE_HOOK_RMDIR]      cache_space_hook_rmdir,
-        [CACHE_HOOK_MKNOD]      cache_space_hook_create,
-        [CACHE_HOOK_RENAME]     cache_space_hook_rename,
+
+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,
+        [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)
 {
-        int rc;
+        int rc = 0;
         ENTRY;
 
-        LASSERT(op <= CACHE_HOOK_MAX && cache_space_hook_ops[op] != NULL);
+        LASSERT(op <= HOOK_MAX + 1);
 
-        rc = cache_space_hook_ops[op](handle, old_dir, old_dentry,
-                                      new_dir, new_dentry);
+        if (cache_space_hook_ops[op]) 
+                rc = cache_space_hook_ops[op](handle, old_dir, old_dentry,
+                                              new_dir, new_dentry);
         RETURN(rc);
 }