Whamcloud - gitweb
Update smfs: 1)unlock cache inode after we call bottom fs methods 2)minor fix in...
[fs/lustre-release.git] / lustre / smfs / dir.c
index c5f0554..d194bb8 100644 (file)
@@ -9,76 +9,15 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/unistd.h>
+#include <linux/lustre_idl.h> 
+#include <linux/smp_lock.h>
 
 #include "smfs_internal.h" 
+#include "kml_idl.h" 
 
 #define NAME_ALLOC_LEN(len)     ((len+16) & ~15)
-
-void smfs_clear_dentry(struct dentry *dentry)
-{
-       struct qstr *name = NULL; 
-
-       if (dentry) {   
-               if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
-                       return;
-               list_del(&dentry->d_hash);
-                       INIT_LIST_HEAD(&dentry->d_hash);
-               list_del(&dentry->d_child);
-                if (dentry->d_inode) {
-                       dentry->d_inode = NULL;
-                       list_del_init(&dentry->d_alias);
-               }
-       
-               name = &(dentry->d_name);
-               if (name->len > DNAME_INLINE_LEN-1) {
-                       SM_FREE((char *)name->name, NAME_ALLOC_LEN(name->len));
-               }
-       }
-}
-
-int smfs_prepare_dentry(struct dentry *dentry, 
-                       struct dentry *parent,
-                       struct qstr *name)
-{
-       char *str = NULL;
-
-       if (name->len > DNAME_INLINE_LEN-1) {
-               SM_ALLOC(str, NAME_ALLOC_LEN(name->len));
-               if (!str) 
-                       return (-ENOMEM);
-       } else
-               str = dentry->d_iname; 
-
-       memcpy(str, name->name, name->len);
-       str[name->len] = 0;
-       
-       atomic_set(&dentry->d_count, 1);
-       dentry->d_vfs_flags = 0;
-       dentry->d_flags = 0;
-       dentry->d_inode = NULL;
-       dentry->d_parent = NULL;
-       dentry->d_sb = NULL;
-       dentry->d_name.name = str;
-       dentry->d_name.len = name->len;
-       dentry->d_name.hash = name->hash;
-       dentry->d_op = NULL;
-       dentry->d_fsdata = NULL;
-       dentry->d_mounted = 0;
-       INIT_LIST_HEAD(&dentry->d_hash);
-       INIT_LIST_HEAD(&dentry->d_lru);
-       INIT_LIST_HEAD(&dentry->d_subdirs);
-       INIT_LIST_HEAD(&dentry->d_alias);
-       
-       if (parent) {
-               dentry->d_parent = dget(parent);
-               dentry->d_sb = parent->d_sb;
-               list_add(&dentry->d_child, &parent->d_subdirs);
-       } else
-               INIT_LIST_HEAD(&dentry->d_child);
-
-       return 0;
-}                                                                                                                                                                                                     
-static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
+                                                                                                                                                                                        
+void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
 {
         atomic_set(&dentry->d_count, 1);
         dentry->d_vfs_flags = 0;
@@ -93,6 +32,14 @@ static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
         INIT_LIST_HEAD(&dentry->d_alias);
 }
 
+void d_unalloc(struct dentry *dentry)
+{
+
+       list_del(&dentry->d_hash);
+       INIT_LIST_HEAD(&dentry->d_hash);
+       dput(dentry); /* this will free the dentry memory */
+}
+
 static int smfs_create(struct inode *dir, 
                       struct dentry *dentry, 
                       int mode)
@@ -100,7 +47,7 @@ static int smfs_create(struct inode *dir,
        struct  inode *cache_dir; 
        struct  inode *cache_inode = NULL, *inode;
        struct  dentry parent; 
-       struct  dentry cache_dentry;
+       struct  dentry *cache_dentry = NULL;
        int     rc;
        
        ENTRY;
@@ -110,14 +57,19 @@ static int smfs_create(struct inode *dir,
                 RETURN(-ENOENT);
        
        prepare_parent_dentry(&parent, cache_dir);      
-       smfs_prepare_dentry(&cache_dentry, &parent, &dentry->d_name);
-                
+       cache_dentry = d_alloc(&parent, &dentry->d_name);
+       
+       if (!cache_dentry) {
+               RETURN(-ENOMEM);
+       }
+                
        if (cache_dir && cache_dir->i_op->create)
-               rc = cache_dir->i_op->create(cache_dir, &cache_dentry, mode);
+               rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode);
+       
        if (rc)
                GOTO(exit, rc);
-       cache_inode = cache_dentry.d_inode;
+
+       cache_inode = igrab(cache_dentry->d_inode);
        
        inode = iget(dir->i_sb, cache_inode->i_ino);    
 
@@ -128,7 +80,7 @@ static int smfs_create(struct inode *dir,
        
        sm_set_inode_ops(cache_inode, inode);
 exit:
-       smfs_clear_dentry(&cache_dentry);       
+       d_unalloc(cache_dentry);
        RETURN(rc);
 }
 
@@ -137,8 +89,8 @@ static struct dentry *smfs_lookup(struct inode *dir,
 {
        struct  inode *cache_dir; 
        struct  inode *cache_inode = NULL, *inode;
-       struct  dentry tmp
-       struct  dentry cache_dentry;
+       struct  dentry parent
+       struct  dentry *cache_dentry = NULL;
        struct  dentry *rc = NULL;
        
        ENTRY;
@@ -146,25 +98,25 @@ static struct dentry *smfs_lookup(struct inode *dir,
        cache_dir = I2CI(dir);
         if (!cache_dir)
                 RETURN(ERR_PTR(-ENOENT));
-       prepare_parent_dentry(&tmp, cache_dir);      
-       smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
+       prepare_parent_dentry(&parent, cache_dir);      
+       cache_dentry = d_alloc(&parent, &dentry->d_name);
       
        if(cache_dir && cache_dir->i_op->lookup)
-               rc = cache_dir->i_op->lookup(cache_dir, &cache_dentry);
+               rc = cache_dir->i_op->lookup(cache_dir, cache_dentry);
 
-       if (rc || !cache_dentry.d_inode || 
-            is_bad_inode(cache_dentry.d_inode) ||
-           IS_ERR(cache_dentry.d_inode)) {
+       if (rc || !cache_dentry->d_inode || 
+            is_bad_inode(cache_dentry->d_inode) ||
+           IS_ERR(cache_dentry->d_inode)) {
                GOTO(exit, rc); 
        }
 
-       cache_inode = cache_dentry.d_inode;
+       cache_inode = igrab(cache_dentry->d_inode);
        
        inode = iget(dir->i_sb, cache_inode->i_ino);    
                
        d_add(dentry, inode);   
 exit:
-       smfs_clear_dentry(&cache_dentry);       
+       d_unalloc(cache_dentry);
        RETURN(rc);
 }                     
 
@@ -191,10 +143,10 @@ static int smfs_link(struct dentry * old_dentry,
        struct  inode *cache_old_inode = NULL; 
        struct  inode *cache_dir = I2CI(dir); 
        struct  inode *inode = NULL; 
-       struct  dentry cache_dentry;
-       struct  dentry cache_old_dentry;
-       struct  dentry tmp
-       struct  dentry tmp_old; 
+       struct  dentry *cache_dentry;
+       struct  dentry *cache_old_dentry;
+       struct  dentry parent
+       struct  dentry parent_old; 
        int     rc = 0;
 
        inode = old_dentry->d_inode;
@@ -204,22 +156,32 @@ static int smfs_link(struct dentry * old_dentry,
        if (!cache_old_inode || !cache_dir) 
                 RETURN(-ENOENT);
        
-       prepare_parent_dentry(&tmp, cache_dir);
-       smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
+       prepare_parent_dentry(&parent, cache_dir);
+       cache_dentry = d_alloc(&parent, &dentry->d_name);
        
-       prepare_parent_dentry(&tmp_old, cache_dir);
-       smfs_prepare_dentry(&cache_old_dentry, &tmp_old, &dentry->d_name);
-       d_add(&cache_old_dentry, cache_old_inode); 
+       prepare_parent_dentry(&parent_old, cache_dir);
+       cache_old_dentry = d_alloc(&parent_old, &dentry->d_name);
+       d_add(cache_old_dentry, cache_old_inode); 
        
        if (cache_dir->i_op->link)
-               rc = cache_dir->i_op->link(&cache_old_dentry, cache_dir, &cache_dentry);                
+               rc = cache_dir->i_op->link(cache_old_dentry, cache_dir, cache_dentry);          
        
-       if (rc == 0) {
-               d_instantiate(dentry, inode);
-       }       
+       if (rc)
+               GOTO(exit, rc); 
+       
+       atomic_inc(&inode->i_count);
+       post_smfs_inode(inode, cache_old_dentry->d_inode);
+       d_instantiate(dentry, inode);
+
+exit:
+       if (cache_dentry->d_inode)      
+               igrab(cache_dentry->d_inode);
+       if (cache_old_dentry->d_inode)
+               igrab(cache_old_dentry->d_inode);
        
-       smfs_clear_dentry(&cache_dentry);
-       smfs_clear_dentry(&cache_old_dentry);
+       d_unalloc(cache_dentry);
+       d_unalloc(cache_old_dentry);
+
        RETURN(rc);
 }
 
@@ -228,24 +190,27 @@ static int smfs_unlink(struct inode * dir,
 {
        struct inode *cache_dir = I2CI(dir);
        struct inode *cache_inode = I2CI(dentry->d_inode);
-       struct dentry cache_dentry;
-       struct dentry tmp
+       struct dentry *cache_dentry;
+       struct dentry parent
        int    rc = 0;
 
        if (!cache_dir || !cache_inode)
                RETURN(-ENOENT);
        
-       prepare_parent_dentry(&tmp, cache_dir);
-       smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
-       d_add(&cache_dentry, cache_inode);
+       prepare_parent_dentry(&parent, cache_dir);
+       cache_dentry = d_alloc(&parent, &dentry->d_name);
+       d_add(cache_dentry, cache_inode);
 
        if (cache_dir->i_op->unlink)
-               rc = cache_dir->i_op->unlink(cache_dir, &cache_dentry);
+               rc = cache_dir->i_op->unlink(cache_dir, cache_dentry);
+
        
-       duplicate_inode(cache_dentry.d_inode, dentry->d_inode);
-       duplicate_inode(cache_dir, dir);
+       post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
+       post_smfs_inode(dir, cache_dir);
        
-       smfs_clear_dentry(&cache_dentry);
+       igrab(cache_dentry->d_inode);
+
+       d_unalloc(cache_dentry);        
        RETURN(rc);     
 }
 
@@ -256,20 +221,20 @@ static int smfs_symlink (struct inode * dir,
        struct inode *cache_dir = I2CI(dir);
        struct inode *cache_inode = NULL;
        struct inode *inode = NULL;
-       struct dentry cache_dentry; 
-       struct dentry tmp
+       struct dentry *cache_dentry; 
+       struct dentry parent
        int    rc = 0;
 
        if (!cache_dir) 
                RETURN(-ENOENT);
        
-       prepare_parent_dentry(&tmp, cache_dir);
-       smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
+       prepare_parent_dentry(&parent, cache_dir);
+       cache_dentry = d_alloc(&parent, &dentry->d_name);
 
        if (cache_dir->i_op->symlink)
-               rc = cache_dir->i_op->symlink(cache_dir, &cache_dentry, symname);
+               rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
        
-       cache_inode = cache_dentry.d_inode;
+       cache_inode = igrab(cache_dentry->d_inode);
        
        inode = iget(dir->i_sb, cache_inode->i_ino);
 
@@ -278,7 +243,8 @@ static int smfs_symlink (struct inode * dir,
        else
                rc = -ENOENT;
        
-       smfs_clear_dentry(&cache_dentry);
+       d_unalloc(cache_dentry);        
+       
        RETURN(rc);                     
 }
 
@@ -289,20 +255,28 @@ static int smfs_mkdir(struct inode * dir,
        struct inode *cache_dir = I2CI(dir);
        struct inode *cache_inode = NULL;
        struct inode *inode = NULL;
-       struct dentry cache_dentry;
-       struct dentry tmp;
+       struct dentry *cache_dentry;
+       struct dentry parent;
+       void   *handle;
        int    rc = 0;
 
        if (!cache_dir) 
                RETURN(-ENOENT);
+
+       handle = smfs_trans_start(cache_dir, KML_OPCODE_MKDIR);
+       if (IS_ERR(handle) ) {
+                CERROR("smfs_do_mkdir: no space for transaction\n");
+               RETURN(-ENOSPC);
+       }
        
-       prepare_parent_dentry(&tmp, cache_dir);
-       smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
-       
+       prepare_parent_dentry(&parent, cache_dir);
+       cache_dentry = d_alloc(&parent, &dentry->d_name);
+
+       lock_kernel();  
        if (cache_dir->i_op->mkdir)
-               rc = cache_dir->i_op->mkdir(cache_dir, &cache_dentry, mode);
+               rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode);
 
-       cache_inode = cache_dentry.d_inode;
+       cache_inode = igrab(cache_dentry->d_inode);
 
        inode = iget(dir->i_sb, cache_inode->i_ino);
 
@@ -310,9 +284,16 @@ static int smfs_mkdir(struct inode * dir,
                GOTO(exit, rc = -ENOENT);
  
        d_instantiate(dentry, inode);   
-       duplicate_inode(cache_dir, dir);
+       /*Do KML post hook*/
+       if (smfs_do_kml(dir)) {
+               rc = post_kml_mkdir(dir, dentry);
+               GOTO(exit, rc);
+       }
+       post_smfs_inode(dir, cache_dir);
 exit:
-       smfs_clear_dentry(&cache_dentry);
+       unlock_kernel();        
+       smfs_trans_commit(handle);
+       d_unalloc(cache_dentry);
        RETURN(rc);             
 }
 
@@ -321,24 +302,25 @@ static int  smfs_rmdir(struct inode * dir,
 {
        struct inode *cache_dir = I2CI(dir);
        struct inode *cache_inode = I2CI(dentry->d_inode);
-       struct dentry cache_dentry;
-       struct dentry tmp;
+       struct dentry *cache_dentry;
+       struct dentry parent;
        int    rc = 0;
 
        if (!cache_dir) 
                RETURN(-ENOENT);
        
-       prepare_parent_dentry(&tmp, cache_dir);
-       smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
-       d_add(&cache_dentry, cache_inode);
+       prepare_parent_dentry(&parent, cache_dir);
+       cache_dentry = d_alloc(&parent, &dentry->d_name);
+       d_add(cache_dentry, cache_inode);
+       
+       igrab(cache_inode);
        
        if (cache_dir->i_op->rmdir)
-               rc = cache_dir->i_op->rmdir(cache_dir, &cache_dentry);
+               rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry);
 
-       duplicate_inode(cache_dir, dir);
-       duplicate_inode(cache_dentry.d_inode, dentry->d_inode);
-
-       smfs_clear_dentry(&cache_dentry);
+       post_smfs_inode(dir, cache_dir);
+       post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
+       d_unalloc(cache_dentry);
        RETURN(rc);             
 }
 
@@ -348,27 +330,30 @@ static int smfs_mknod(struct inode * dir, struct dentry *dentry,
        struct inode *cache_dir = I2CI(dir);
        struct inode *inode = NULL;
        struct inode *cache_inode = NULL;
-       struct dentry cache_dentry;
-       struct dentry tmp;
+       struct dentry *cache_dentry;
+       struct dentry parent;
        int    rc = 0;
 
        if (!cache_dir) 
                RETURN(-ENOENT);
 
-       prepare_parent_dentry(&tmp, cache_dir);
-       smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
-               
+       prepare_parent_dentry(&parent, cache_dir);
+       cache_dentry = d_alloc(&parent, &dentry->d_name);
+       
        if (cache_dir->i_op->mknod)
-               rc = cache_dir->i_op->mknod(cache_dir, &cache_dentry, mode, rdev);
+               rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, mode, rdev);
        
-       if (!rc) {
-               cache_inode = cache_dentry.d_inode;
-               inode = iget(dir->i_sb, cache_inode->i_ino);
-               d_instantiate(dentry, inode);
-               duplicate_inode(cache_dir, dir);
-               duplicate_inode(cache_dentry.d_inode, dentry->d_inode);
-       }
-       smfs_clear_dentry(&cache_dentry);
+       if (cache_dentry->d_inode)
+               cache_inode = igrab(cache_dentry->d_inode);
+       if (rc)
+               GOTO(exit, rc);
+       
+       inode = iget(dir->i_sb, cache_inode->i_ino);
+       d_instantiate(dentry, inode);
+       post_smfs_inode(dir, cache_dir);
+       post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
+exit:
+       d_unalloc(cache_dentry);
        RETURN(rc);             
 }
 static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry,
@@ -377,33 +362,34 @@ static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry,
        struct inode *cache_old_dir = I2CI(old_dir);
        struct inode *cache_new_dir = I2CI(new_dir);
        struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
-       struct inode *cache_new_inode = NULL;
-       struct inode *new_inode = NULL;
-       struct dentry cache_old_dentry;
-       struct dentry cache_new_dentry;
-       struct dentry tmp_new;
-       struct dentry tmp_old;
+       struct dentry *cache_old_dentry;
+       struct dentry *cache_new_dentry;
+       struct dentry parent_new;
+       struct dentry parent_old;
        int    rc = 0;
 
        if (!cache_old_dir || !cache_new_dir || !cache_old_inode) 
                RETURN(-ENOENT);
        
-       prepare_parent_dentry(&tmp_old, cache_old_dir);
-       smfs_prepare_dentry(&cache_old_dentry, &tmp_old, &old_dentry->d_name); 
-       d_add(&cache_old_dentry, cache_old_inode);
+       prepare_parent_dentry(&parent_old, cache_old_dir);
+       cache_old_dentry = d_alloc(&parent_old, &old_dentry->d_name);
+       d_add(cache_old_dentry, cache_old_inode);
+       igrab(cache_old_inode); 
 
-       prepare_parent_dentry(&tmp_new, cache_new_dir);
-       smfs_prepare_dentry(&cache_new_dentry, &tmp_new, &new_dentry->d_name); 
+       prepare_parent_dentry(&parent_new, cache_new_dir);
+       cache_new_dentry = d_alloc(&parent_new, &new_dentry->d_name);
        
        if (cache_old_dir->i_op->rename)
-               rc = cache_old_dir->i_op->rename(cache_old_dir, &cache_old_dentry,
-                                                cache_new_dir, &cache_new_dentry);
-
-       duplicate_inode(cache_old_dir, old_dir);
-       duplicate_inode(cache_new_dir, new_dir);
-       smfs_clear_dentry(&cache_old_dentry);
-       smfs_clear_dentry(&cache_new_dentry);
+               rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry,
+                                                cache_new_dir, cache_new_dentry);
 
+       post_smfs_inode(old_dir, cache_old_dir) ;
+       post_smfs_inode(new_dir, cache_new_dir);
+       if (cache_new_dentry->d_inode) {
+               igrab(cache_new_dentry->d_inode);       
+       }
+       d_unalloc(cache_old_dentry);
+       d_unalloc(cache_new_dentry);
        RETURN(rc);             
 }