Whamcloud - gitweb
b=6285
[fs/lustre-release.git] / lustre / smfs / dir.c
index 6be2ddd..296973b 100644 (file)
@@ -61,11 +61,14 @@ static int smfs_create(struct inode *dir, struct dentry *dentry,
         int rc = 0;
         
         ENTRY;
-
+        
+        CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n",
+               dentry->d_name.len, dentry->d_name.name, dentry,
+               dir->i_ino, dir->i_generation);
+        
         LASSERT(cache_dir);
         LASSERT(cache_dir->i_op->create);
-
-        //lock_kernel();
+        
         cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent);
         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
         if (!cache_dentry || !cache_parent) {
@@ -89,8 +92,8 @@ static int smfs_create(struct inode *dir, struct dentry *dentry,
         rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode, nd);
 #endif
         if (!rc) {
-                inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino,
-                                       dir, 0);
+                inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode,
+                                       I2SMI(dir), 0);
                 if (inode) {
                         d_instantiate(dentry, inode);
                 }
@@ -102,9 +105,8 @@ static int smfs_create(struct inode *dir, struct dentry *dentry,
 
         post_smfs_inode(dir, cache_dir);
         smfs_trans_commit(dir, handle, 0);
-
+        
 exit:
-        //unlock_kernel();
         post_smfs_dentry(cache_dentry);
         post_smfs_dentry(cache_parent);
         RETURN(rc);
@@ -182,7 +184,10 @@ static int smfs_do_lookup (struct inode * dir,
 
         ENTRY;
         
-        cache_dir = I2CI(dir);
+        CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n",
+               dentry->d_name.len, dentry->d_name.name, dentry,
+               dir->i_ino, dir->i_generation);
+
         if (!cache_dir)
                 RETURN(-ENOENT);
 
@@ -204,26 +209,43 @@ static int smfs_do_lookup (struct inode * dir,
                 if (IS_ERR(rdentry)) {
                         rc = PTR_ERR(rdentry);
                         rdentry = NULL;
-                }
-                else {
+                } else {
                         tmp = rdentry;
-                        //copy fields if DCACHE_CROSS_REF
-                        smfs_update_dentry(dentry, tmp);
                 }
-        } else 
+        } else {
                 tmp = cache_dentry;
-        
+        }
+
         SMFS_POST_HOOK(dir, HOOK_LOOKUP, &msg, rc);
      
-        if (tmp && tmp->d_inode) {
-                *inode = smfs_get_inode(dir->i_sb, tmp->d_inode->i_ino, 
-                                        dir, 0); 
-                if (!(*inode))
-                        rc = -ENOENT;
+        if (tmp) {
+                //copy fields if DCACHE_CROSS_REF
+                smfs_update_dentry(dentry, tmp);         
+                
+                if (tmp->d_inode) {
+                        *inode = smfs_get_inode(dir->i_sb, tmp->d_inode, 
+                                                I2SMI(dir), 0); 
+                        if (!(*inode))
+                                rc = -ENOENT;
+                        else {
+                                if (!tmp->d_inode->i_nlink) {
+                                        struct inode * ind = tmp->d_inode;
+                                
+                                        CWARN("inode #%lu (%*s) nlink is %i/%i\n",
+                                              ind->i_ino, tmp->d_name.len,
+                                              tmp->d_name.name, ind->i_nlink,
+                                              (*inode)->i_nlink);
+                                        CWARN("parent #%lu (%*s) nlink is %i\n",
+                                              dir->i_ino, tmp->d_parent->d_name.len,
+                                              tmp->d_parent->d_name.name,
+                                              cache_dir->i_nlink);
+                                        LBUG();
+                                }
+                        }
+                }
         }
         
         if (rdentry) {
-                LASSERT(atomic_read(&rdentry->d_count) > 0);
                 dput(rdentry);
         }
         
@@ -286,6 +308,8 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry,
         struct dentry * rdentry = NULL;
         struct inode * inode = NULL;
         int rc;
+
+        ENTRY;
         
         rc = smfs_do_lookup(dir, dentry, nd, &inode);
         if (rc)
@@ -302,6 +326,26 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry,
         RETURN(rdentry);
 }
 
+#if HAVE_LOOKUP_RAW
+static int smfs_lookup_raw(struct inode *dir, const char *name,
+                           int len, ino_t *data)
+{
+        struct inode *cache_dir = I2CI(dir);
+        int rc = 0;
+
+        if (!cache_dir)
+                RETURN(-ENOENT);
+        
+        if (cache_dir->i_op->lookup_raw) {
+                rc = cache_dir->i_op->lookup_raw(cache_dir, name, len, data);
+        } else {
+                CWARN("do not have raw lookup ops in bottom fs\n");
+        }
+
+        RETURN(rc);
+}
+#endif
+
 static int smfs_link(struct dentry *old_dentry,
                      struct inode *dir, struct dentry *dentry)
 {
@@ -350,6 +394,7 @@ static int smfs_link(struct dentry *old_dentry,
         rc = cache_dir->i_op->link(cache_old_dentry, cache_dir, cache_dentry);
         if (!rc) {
                 atomic_inc(&old_inode->i_count);
+                old_inode->i_nlink++;
                 dput(iopen_connect_dentry(dentry, old_inode, 0));
         }
 
@@ -381,7 +426,7 @@ static int smfs_unlink(struct inode * dir, struct dentry *dentry)
         //int    mode = 0;
         struct hook_unlink_msg msg = {
                 .dentry = dentry,
-                .mode = 0
+                .mode = dentry->d_inode->i_mode
         };
 
         ENTRY;
@@ -391,6 +436,10 @@ static int smfs_unlink(struct inode * dir, struct dentry *dentry)
         LASSERT(cache_dir->i_op->unlink);
         LASSERT(parent);
         
+        CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n",
+               dentry->d_name.len, dentry->d_name.name, dentry,
+               dir->i_ino, dir->i_generation);
+
         cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent);
         cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
         if (!cache_dentry || !cache_parent) {
@@ -398,13 +447,12 @@ static int smfs_unlink(struct inode * dir, struct dentry *dentry)
                 goto exit;
         }
                 
-        //lock_kernel();
         handle = smfs_trans_start(dir, FSFILT_OP_UNLINK, NULL);
         if (IS_ERR(handle)) {
                 rc = -ENOSPC;
                 goto exit;
         }
-
+        
         pre_smfs_inode(dir, cache_dir);
         pre_smfs_inode(dentry->d_inode, cache_inode);
 
@@ -413,10 +461,11 @@ static int smfs_unlink(struct inode * dir, struct dentry *dentry)
         rc = cache_dir->i_op->unlink(cache_dir, cache_dentry);
                 
         SMFS_POST_HOOK(dir, HOOK_UNLINK, &msg, rc); 
-
-        post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
-        post_smfs_inode(dir, cache_dir);
-        //unlock_kernel();
+        if (!rc) {
+                post_smfs_inode(dentry->d_inode, cache_inode);
+                dentry->d_inode->i_nlink--;
+                post_smfs_inode(dir, cache_dir);
+        }
         
         smfs_trans_commit(dir, handle, 0);
 exit:
@@ -460,17 +509,15 @@ static int smfs_symlink(struct inode *dir, struct dentry *dentry,
                 goto exit;
         }
         
-        //lock_kernel();
         pre_smfs_inode(dir, cache_dir);
 
         SMFS_PRE_HOOK(dir, HOOK_SYMLINK, &msg); 
         
         rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
         if (!rc) {        
-                inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino,
-                                       dir, 0);
+                inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode,
+                                       I2SMI(dir), 0);
                 if (inode) {
-                        //smfs_update_dentry(dentry, cache_dentry);
                         d_instantiate(dentry, inode);
                 }
                 else
@@ -483,7 +530,6 @@ static int smfs_symlink(struct inode *dir, struct dentry *dentry,
         smfs_trans_commit(dir, handle, 0);
 
 exit:
-        //unlock_kernel();
         post_smfs_dentry(cache_dentry);
         post_smfs_dentry(cache_parent);
         RETURN(rc);
@@ -507,6 +553,11 @@ static int smfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
         LASSERT(cache_dir);
         LASSERT(parent);
         
+        CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n",
+               dentry->d_name.len, dentry->d_name.name, dentry,
+               dir->i_ino, dir->i_generation);
+
+        
         cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent);
         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
         if (!cache_parent || !cache_dentry) {
@@ -525,10 +576,10 @@ static int smfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
         
         rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode);
         if (!rc) {
-                inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino,
-                                       dir, 0);
+                inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode,
+                                       I2SMI(dir), 0);
                 if (inode) {
-                        //smsf_update_dentry(dentry, cache_dentry);
+                        dir->i_nlink++;
                         d_instantiate(dentry, inode);
                 }
                 else
@@ -552,6 +603,7 @@ static int smfs_rmdir(struct inode *dir, struct dentry *dentry)
         struct inode *parent = I2CI(dentry->d_parent->d_inode);
         struct dentry *cache_dentry = NULL;
         struct dentry *cache_parent = NULL;
+        struct inode * inode = dentry->d_inode;
         void *handle = NULL;
         int    rc = 0;
         struct hook_unlink_msg msg = {
@@ -561,6 +613,10 @@ static int smfs_rmdir(struct inode *dir, struct dentry *dentry)
 
         ENTRY;
         
+        CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n",
+               dentry->d_name.len, dentry->d_name.name, dentry,
+               dir->i_ino, dir->i_generation);
+
         LASSERT(cache_dir);
         LASSERT(cache_dir->i_op->rmdir);
         LASSERT(parent);
@@ -571,30 +627,36 @@ static int smfs_rmdir(struct inode *dir, struct dentry *dentry)
                 rc = -ENOMEM;
                 goto exit;
         }
-
+        
         handle = smfs_trans_start(dir, FSFILT_OP_RMDIR, NULL);
         if (IS_ERR(handle) ) {
                 rc = -ENOSPC;
                 goto exit;
         }
 
+        dentry_unhash(cache_dentry);
+
         pre_smfs_inode(dir, cache_dir);
-        pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
+        pre_smfs_inode(inode, cache_inode);
         
         SMFS_PRE_HOOK(dir, HOOK_RMDIR, &msg); 
         
         rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry);
               
         SMFS_POST_HOOK(dir, HOOK_RMDIR, &msg, rc); 
-        
-        post_smfs_inode(dir, cache_dir);
-        post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
-        //like vfs_rmdir is doing with inode
-        if (!rc)
-                cache_dentry->d_inode->i_flags |= S_DEAD;
-        
+        if (!rc) {
+                if (inode->i_nlink != 2)
+                        CWARN("Directory #%lu under rmdir has %i nlinks\n",
+                                inode->i_ino, inode->i_nlink);
+                inode->i_nlink = 0;
+                dir->i_nlink--;
+                post_smfs_inode(dir, cache_dir);
+                post_smfs_inode(inode, cache_inode);
+                //like vfs_rmdir is doing with inode
+                cache_inode->i_flags |= S_DEAD;
+        }
         smfs_trans_commit(dir, handle, 0);
-
+        dput(cache_dentry);
 exit:
         post_smfs_dentry(cache_dentry);
         post_smfs_dentry(cache_parent);
@@ -645,8 +707,8 @@ static int smfs_mknod(struct inode *dir, struct dentry *dentry,
         
         rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, mode, rdev);
         if (!rc) {
-                inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino,
-                                       dir, 0);
+                inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode,
+                                       I2SMI(dir), 0);
                 if (inode) {
                         //smsf_update_dentry(dentry, cache_dentry);
                         d_instantiate(dentry, inode);
@@ -672,6 +734,7 @@ 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 *new_inode = new_dentry->d_inode;
         struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
         struct inode *old_parent = I2CI(old_dentry->d_parent->d_inode);
         struct inode *new_parent = I2CI(new_dentry->d_parent->d_inode);
@@ -693,8 +756,8 @@ static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry,
         if (!cache_old_dir || !cache_new_dir || !cache_old_inode)
                 RETURN(-ENOENT);
 
-        if (new_dentry->d_inode) {
-                cache_new_inode = I2CI(new_dentry->d_inode);
+        if (new_inode) {
+                cache_new_inode = I2CI(new_inode);
                 if (!cache_new_inode)
                         RETURN(-ENOENT);
         }
@@ -723,8 +786,9 @@ static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry,
         
         pre_smfs_inode(old_dir, cache_old_dir);
         pre_smfs_inode(new_dir, cache_new_dir);
-        if (new_dentry->d_inode)
-                pre_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode);
+        pre_smfs_inode(old_dentry->d_inode, cache_old_inode);
+        if (new_inode)
+                pre_smfs_inode(new_inode, cache_new_inode);
 
         SMFS_PRE_HOOK(old_dir, HOOK_RENAME, &msg); 
         
@@ -732,12 +796,24 @@ static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                          cache_new_dir, cache_new_dentry);
         
         SMFS_POST_HOOK(old_dir, HOOK_RENAME, &msg, rc); 
-
-        post_smfs_inode(old_dir, cache_old_dir);
-        post_smfs_inode(new_dir, cache_new_dir);
-        if (new_dentry->d_inode)
-                post_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode);
-        
+        if (!rc) {
+                post_smfs_inode(old_dir, cache_old_dir);
+                post_smfs_inode(new_dir, cache_new_dir);
+                post_smfs_inode(old_dentry->d_inode, cache_old_inode);
+                if (new_inode) {
+                        post_smfs_inode(new_inode, cache_new_inode);
+                        new_inode->i_nlink--;
+                }
+                //directory is renamed
+                if (S_ISDIR(old_dentry->d_inode->i_mode)) {
+                        old_dir->i_nlink--;
+                        if (new_inode) {
+                                new_inode->i_nlink--;
+                        } else {
+                                new_dir->i_nlink++;
+                        }
+                }
+        }
         smfs_trans_commit(old_dir, handle, 0);
         
 exit:
@@ -749,23 +825,27 @@ exit:
 }
 
 struct inode_operations smfs_dir_iops = {
-        create:         smfs_create,
-        lookup:         smfs_lookup,
-        link:           smfs_link,              /* BKL held */
-        unlink:         smfs_unlink,            /* BKL held */
-        symlink:        smfs_symlink,           /* BKL held */
-        mkdir:          smfs_mkdir,             /* BKL held */
-        rmdir:          smfs_rmdir,             /* BKL held */
-        mknod:          smfs_mknod,             /* BKL held */
-        rename:         smfs_rename,            /* BKL held */
-        setxattr:       smfs_setxattr,          /* BKL held */
-        getxattr:       smfs_getxattr,          /* BKL held */
-        listxattr:      smfs_listxattr,         /* BKL held */
-        removexattr:    smfs_removexattr,       /* BKL held */
+        .create         = smfs_create,
+        .lookup         = smfs_lookup,
+#if HAVE_LOOKUP_RAW
+        .lookup_raw     = smfs_lookup_raw,
+#endif
+        .link           = smfs_link,              
+        .unlink         = smfs_unlink,            
+        .symlink        = smfs_symlink,           
+        .mkdir          = smfs_mkdir,             
+        .rmdir          = smfs_rmdir,             
+        .mknod          = smfs_mknod,             
+        .rename         = smfs_rename,            
+        .setxattr       = smfs_setxattr,
+        .getxattr       = smfs_getxattr,
+        .listxattr      = smfs_listxattr,
+        .removexattr    = smfs_removexattr,
+        .permission     = smfs_permission,
 };
 
 struct inode_operations smfs_iopen_iops = {
-        lookup:         smfs_iopen_lookup,
+        .lookup         = smfs_iopen_lookup,
 };
 
 static ssize_t smfs_read_dir(struct file *filp, char *buf,