Whamcloud - gitweb
b=3550
[fs/lustre-release.git] / lustre / smfs / smfs_cow.c
index 5b4f579..a041bf9 100644 (file)
@@ -46,7 +46,8 @@ static int smfs_init_snaptabe(struct super_block *sb)
         struct snap_info         *snap_info = S2SNAPI(sb);     
         struct snap_table        *snap_table = NULL;       
        struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
-        int                      rc = 0, size, table_size, vallen;
+        struct dentry            *d_root = snap_info->snap_root;
+        int                      rc = 0, size, table_size, vallen, i;
  
         ENTRY;
 
@@ -54,7 +55,7 @@ static int smfs_init_snaptabe(struct super_block *sb)
         /*Initialized table */
         /*get the maxsize of snaptable*/
         vallen = sizeof(int);
-        rc = snapops->fs_get_snap_info(sb, NULL, MAX_SNAPTABLE_COUNT,
+        rc = snapops->fs_get_snap_info(d_root->d_inode, MAX_SNAPTABLE_COUNT,
                                        strlen(MAX_SNAPTABLE_COUNT), &size, 
                                        &vallen);
         if (size == 0) {
@@ -74,9 +75,12 @@ static int smfs_init_snaptabe(struct super_block *sb)
          
         snap_table->sntbl_magic = cpu_to_le32((__u32)SNAPTABLE_MAGIC); 
         snap_table->sntbl_max_count = size;
+        for (i = 0; i < snap_table->sntbl_max_count; i++) {
+                /*init sn_index to -1*/ 
+                snap_table->sntbl_items[i].sn_index = -1;
+        }
         /*get snaptable info*/
-
-        rc = snapops->fs_get_snap_info(sb, NULL, SNAPTABLE_INFO, 
+        rc = snapops->fs_get_snap_info(d_root->d_inode, SNAPTABLE_INFO, 
                                        strlen(SNAPTABLE_INFO), 
                                        snap_table, &table_size);       
         if (rc < 0) {
@@ -121,14 +125,9 @@ static int smfs_init_cowed_dir(struct super_block *sb, struct dentry* cowed_dir)
 }
 int smfs_start_cow(struct super_block *sb)
 {
-        struct smfs_super_info *smfs_info = S2SMI(sb);
         int rc = 0;
 
         ENTRY;
-        OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
-     
-        if (!smfs_info->smsi_snap_info) 
-                RETURN(-ENOMEM);
         
         /*init snap fsfilt operations*/
         if (!S2SNAPI(sb)->snap_cache_fsfilt) {
@@ -189,8 +188,6 @@ int smfs_stop_cow(struct super_block *sb)
                 table_size =  SNAPTABLE_SIZE(snap_table->sntbl_max_count);
                 OBD_FREE(snap_info->sntbl, table_size);
         }
-        if (snap_info) 
-               OBD_FREE(snap_info, sizeof(*snap_info)); 
         
         RETURN(rc);
 }
@@ -203,13 +200,23 @@ int smfs_cow_init(struct super_block *sb)
 
         SMFS_SET_COW(smfs_info);
       
+        OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
+        
+        if (!smfs_info->smsi_snap_info) 
+                RETURN(-ENOMEM);
+        
         RETURN(rc);
 }
 
 int smfs_cow_cleanup(struct super_block *sb)
 {
+        
+        struct snap_info       *snap_info = S2SNAPI(sb);       
+        
         ENTRY;
         SMFS_CLEAN_COW(S2SMI(sb));
+        if (snap_info) 
+               OBD_FREE(snap_info, sizeof(*snap_info)); 
         RETURN(0);
 }
 
@@ -228,7 +235,7 @@ int smfs_init_snap_inode_info(struct inode *inode, int flags)
                 sni_info->sn_flags = flags;
                 vallen = sizeof(sni_info->sn_gen);
 
-                rc = snapops->fs_get_snap_info(NULL, inode, SNAP_GENERATION,
+                rc = snapops->fs_get_snap_info(inode, SNAP_GENERATION,
                                                strlen(SNAP_GENERATION),
                                                &sni_info->sn_gen, &vallen);               
         } 
@@ -296,6 +303,7 @@ int smfs_add_snap_item(struct super_block *sb, char *name)
        struct snap_info *snap_info = S2SNAPI(sb);
         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
         struct snap_table *snap_table = snap_info->sntbl;
+        struct dentry            *d_root = snap_info->snap_root;
         struct snap      *snap_item;
         int    table_size, count = 0, index = 0, rc = 0;
 
@@ -318,7 +326,7 @@ int smfs_add_snap_item(struct super_block *sb, char *name)
        /* Wrote the whole snap_table to disk */
         table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); 
         
-        rc = snapops->fs_set_snap_info(sb, NULL, SNAPTABLE_INFO, 
+        rc = snapops->fs_set_snap_info(d_root->d_inode, SNAPTABLE_INFO, 
                                        strlen(SNAPTABLE_INFO),
                                       snap_table, &table_size);
        if (rc) {
@@ -429,18 +437,24 @@ int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
        snap_last(inode->i_sb, &snap);
        ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen, 
                                           dparent->d_inode, del);
-       if(!ind)
-               RETURN(-EINVAL);
-        if (!SMFS_DO_INODE_COWED(inode)) {
-                /*insert the inode to cowed inode*/
-                SMFS_SET_INODE_COWED(inode); 
-                link_cowed_inode(inode); 
+       if(ind && IS_ERR(ind)) {
+                CERROR("Create ind inode %lu index %d gen %d del %d\n rc%d\n",
+                        inode->i_ino, snap.sn_index, snap.sn_gen, del,
+                        PTR_ERR(ind));
+               RETURN(PTR_ERR(ind));
+        }
+        if (ind) { 
+                if (!SMFS_DO_INODE_COWED(inode)) {
+                        /*insert the inode to cowed inode*/
+                        SMFS_SET_INODE_COWED(inode); 
+                        link_cowed_inode(inode); 
+                }
+                
+                I2SMI(ind)->sm_sninfo.sn_flags = 0;
+                I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen;
+                
+                iput(ind);
         }
-        
-        I2SMI(ind)->sm_sninfo.sn_flags = 0;
-        I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen;
-        
-        iput(ind);
         RETURN(0);
 }
 /*Dir inode will do cow*/
@@ -455,8 +469,8 @@ int smfs_cow_create(struct inode *dir, struct dentry *dentry,
                CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
                 dparent = dentry->d_parent->d_parent;
-               if ((snap_do_cow(dir, dparent, 0))) {
-                       CERROR("Do cow error\n");
+               if ((rc = snap_do_cow(dir, dparent, 0))) {
+                       CERROR("Do cow error %d\n", rc);
                        RETURN(-EINVAL);
                }
        }
@@ -575,13 +589,16 @@ int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1,
         struct snap_table *table = snap_info->sntbl; 
        long   blocks[2]={-1,-1};
                int  index = 0, i, rc = 0;
-        size_t count = *(size_t *)data1;
-       loff_t pos = *(loff_t*)data2;
+        size_t count;
+       loff_t pos;
 
         ENTRY;
 
-        LASSERT(count);
-        LASSERT(pos);
+        LASSERT(data1);
+        LASSERT(data2);
+        
+        count = *(size_t *)data1;
+       pos = *(loff_t*)data2;
  
        down(&inode->i_sem);
         
@@ -640,16 +657,100 @@ exit:
 }
 EXPORT_SYMBOL(smfs_cow_write);
 
+int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1,
+                    void *data2)
+{
+        struct snap_info *snap_info = S2SNAPI(inode->i_sb);
+        struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
+        struct dentry *dparent = dentry->d_parent;
+        struct clonefs_info *clone_info=(struct clonefs_info*)dparent->d_fsdata;
+        int rc = 0;
+        if (clone_info && clone_info->clone_flags && SM_CLONE_FS) {
+                struct inode *ind_inode = NULL;
+                struct inode *cache_ind = NULL;
+                struct dentry *cache_dentry = NULL;
+                struct dentry *cache_parent = NULL;
+                struct inode *cache_inode;
+                struct dentry *tmp;
+                rc = 1;
+                ind_inode = snapops->fs_get_indirect(inode, NULL, clone_info->clone_index);
+                if (!ind_inode) 
+                        RETURN(-ENOENT);
+                
+                if (!(cache_ind = I2CI(ind_inode)))
+                        GOTO(exit, rc = -ENOENT);
+
+                cache_parent=pre_smfs_dentry(NULL, cache_ind, dentry->d_parent);
+                cache_dentry=pre_smfs_dentry(cache_parent, NULL, dentry);
+
+                tmp = cache_ind->i_op->lookup(cache_ind, cache_dentry);
+        
+                if (IS_ERR(tmp))
+                        GOTO(exit, rc = -ENOENT);
+
+                if ((cache_inode = tmp ? tmp->d_inode : cache_dentry->d_inode)) {
+                        if (IS_ERR(cache_inode)) {
+                                dentry->d_inode = cache_inode;
+                                GOTO(exit, rc = -ENOENT);
+                        }
+                        inode = iget4(inode->i_sb, cache_inode->i_ino, NULL,
+                                      &I2SMI(inode)->smi_flags);
+                } else {
+                        d_add(dentry, NULL);
+                        GOTO(exit, rc = -ENOENT);
+                }
+                d_add(dentry, inode);
+exit:
+                iput(ind_inode);
+                post_smfs_dentry(cache_dentry);
+                post_smfs_dentry(cache_parent);
+                RETURN(rc);
+        } 
+        RETURN(rc);         
+}
+
+struct inode *smfs_cow_get_ind(struct inode *inode, int index)
+{
+        struct snap_info *snap_info = S2SNAPI(inode->i_sb);
+        struct fsfilt_operations *snapops = snap_info->snap_fsfilt; 
+        struct snap_table *table = snap_info->sntbl;
+        long block=(index << PAGE_CACHE_SHIFT) >> inode->i_sb->s_blocksize_bits;
+        int slot;
+
+        ENTRY; 
+        for (slot = table->sntbl_count - 1; slot >= 0; slot--) {
+                struct address_space_operations *aops = inode->i_mapping->a_ops;
+                struct inode *cache_inode = NULL;
+                int index = 0;
+
+                index = table->sntbl_items[slot].sn_index;
+                cache_inode = snapops->fs_get_indirect(inode, NULL, index);
+                                                                                                                                                                                                     
+                if (!cache_inode )  continue;
+                                                                                                                                                                                                     
+                if (aops->bmap(cache_inode->i_mapping, block))
+                       RETURN(cache_inode); 
+                iput(cache_inode);
+        }
+
+        RETURN(NULL);
+}
+EXPORT_SYMBOL(smfs_cow_get_ind);
+
 typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry, 
                          void *new_dir, void *new_dentry);
 
-static cow_funcs smfs_cow_funcs[REINT_MAX + 1] = {
+
+static cow_funcs smfs_cow_funcs[REINT_MAX + 2] = {
         [REINT_SETATTR] smfs_cow_setattr,
         [REINT_CREATE]  smfs_cow_create,
         [REINT_LINK]    smfs_cow_link,
         [REINT_UNLINK]  smfs_cow_unlink,
         [REINT_RENAME]  smfs_cow_rename,
         [REINT_WRITE]   smfs_cow_write,
+        [SNAP_LOOKUP]   smfs_cow_lookup,
 };
 
 int smfs_cow(struct inode *dir, struct dentry *dentry, void *new_dir,