Whamcloud - gitweb
1)cleanup smfs code for 2.6 and snapfs
authorwangdi <wangdi>
Wed, 18 Aug 2004 18:09:51 +0000 (18:09 +0000)
committerwangdi <wangdi>
Wed, 18 Aug 2004 18:09:51 +0000 (18:09 +0000)
2)update snapfs on smfs
3)add snap_utils on lctl.c
4)some minor fix on smfs

24 files changed:
lnet/include/lnet/lnetctl.h
lnet/include/lnet/ptlctl.h
lustre/include/linux/lustre_lib.h
lustre/include/linux/lustre_smfs.h
lustre/include/linux/lustre_snap.h
lustre/llite/dir.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/lvfs/fsfilt_smfs.c
lustre/lvfs/fsfilt_snap_ext3.c
lustre/lvfs/fsfilt_snap_smfs.c
lustre/mds/mds_lov.c
lustre/obdfilter/filter.c
lustre/portals/include/portals/ptlctl.h
lustre/smfs/cache_space.c
lustre/smfs/dir.c
lustre/smfs/inode.c
lustre/smfs/ioctl.c
lustre/smfs/smfs_cow.c
lustre/smfs/smfs_internal.h
lustre/smfs/smfs_lib.c
lustre/smfs/super.c
lustre/utils/lctl.c
lustre/utils/obd.c

index 2af336e..e0140ce 100644 (file)
@@ -31,6 +31,8 @@
 #define PORTALS_DEV_PATH "/dev/portals"
 #define OBD_DEV_ID 1
 #define OBD_DEV_PATH "/dev/obd"
+#define SMFS_DEV_ID  2
+#define SMFS_DEV_PATH "/dev/snapdev"
 
 int ptl_name2nal(char *str);
 int ptl_parse_ipaddr (__u32 *ipaddrp, char *str);
index 2af336e..e0140ce 100644 (file)
@@ -31,6 +31,8 @@
 #define PORTALS_DEV_PATH "/dev/portals"
 #define OBD_DEV_ID 1
 #define OBD_DEV_PATH "/dev/obd"
+#define SMFS_DEV_ID  2
+#define SMFS_DEV_PATH "/dev/snapdev"
 
 int ptl_name2nal(char *str);
 int ptl_parse_ipaddr (__u32 *ipaddrp, char *str);
index 070f51a..04de0a5 100644 (file)
@@ -474,7 +474,7 @@ static inline void obd_ioctl_freedata(char *buf, int len)
 #define OBD_IOC_COBD_COFF              _IOWR('f', 221, long)
 #define OBD_IOC_COBD_CFLUSH            _IOWR('f', 222, long)
 
-#define OBD_IOC_SNAP_ADD               _IOWR('f', 230, long)
+#define OBD_IOC_SMFS_SNAP_ADD          _IOWR('f', 230, long)
 
 /* XXX _IOWR('f', 250, long) has been defined in
  * portals/include/linux/kp30.h for debug, don't use it
index a534162..710569c 100644 (file)
@@ -30,6 +30,7 @@ struct snap_inode_info {
        int sn_flags;           /*the flags indicated inode type */
        int sn_gen;             /*the inode generation*/
         int sn_index;           /*the inode snap_index*/
+        ino_t sn_root_ino;        /*the root ino of this snap*/
 };
 struct smfs_inode_info {
         struct inode *smi_inode;
@@ -93,11 +94,12 @@ struct smfs_super_info {
         char                     *smsi_cache_ftype; /* cache file system type */
         char                     *smsi_ftype;       /* file system type */
        struct obd_export        *smsi_exp;         /* file system obd exp */
-       struct snap_info         *smsi_snap_info;   /* snap table cow */
+       struct snap_super_info   *smsi_snap_info;   /* snap table cow */
         smfs_pack_rec_func      smsi_pack_rec[PACK_MAX]; /* sm_pack_rec type ops */
         __u32                    smsi_flags;        /* flags */
         __u32                    smsi_ops_check;
         struct list_head         smsi_hook_list;
+        kmem_cache_t *           smsi_inode_cachep;  /*inode_cachep*/
 };
 
 
@@ -121,26 +123,27 @@ struct fs_extent{
         __u32   e_num;          /* number of blocks covered by extent */
 };
 
-#define I2SMI(inode)  ((struct smfs_inode_info *) (&(inode->u.generic_ip)))
+#define I2SMI(inode)  ((struct smfs_inode_info *) ((inode->u.generic_ip)))
+
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#define S2SMI(sb)   ((struct smfs_super_info *) (&(sb->u.generic_sbp)))
-#define S2CSB(sb)   (((struct smfs_super_info *) (&(sb->u.generic_sbp)))->smsi_sb)
+#define S2SMI(sb)   ((struct smfs_super_info *) ((sb->u.generic_sbp)))
+#define S2CSB(sb)   (((struct smfs_super_info *)((sb->u.generic_sbp)))->smsi_sb)
 #else
 #define S2SMI(sb)   ((struct smfs_super_info *) (sb->s_fs_info))
 #define S2CSB(sb)   (((struct smfs_super_info *) (sb->s_fs_info))->smsi_sb)
 #endif
 
-#define I2CI(inode) (((struct smfs_inode_info*) (&(inode->u.generic_ip)))->smi_inode)
+#define I2CI(inode) (((struct smfs_inode_info*) ((inode->u.generic_ip)))->smi_inode)
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#define I2CSB(inode) ((struct smfs_super_info *) (&(inode->i_sb->u.generic_sbp)))
+#define I2CSB(inode) ((struct smfs_super_info *) ((inode->i_sb->u.generic_sbp)))
 #else
 #define I2CSB(inode) ((struct smfs_super_info *) (inode->i_sb->s_fs_info))
 #endif
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
 #define I2FOPS(inode) (((struct smfs_super_info *) \
-                        (&(inode->i_sb->u.generic_sbp)))->sm_cache_fsfilt)
+                        ((inode->i_sb->u.generic_sbp)))->sm_cache_fsfilt)
 #else
 #define I2FOPS(inode) (((struct smfs_super_info *) \
                         (inode->i_sb->s_fs_info))->sm_cache_fsfilt)
@@ -364,6 +367,7 @@ static inline void d_unalloc(struct dentry *dentry)
         INIT_LIST_HEAD(&dentry->d_hash);
 #else
         hlist_del_init(&dentry->d_hash);
+        dentry->d_flags |= DCACHE_UNHASHED;
 #endif
         dput(dentry); /* this will free the dentry memory */
 }
index 22169a7..e605da6 100644 (file)
@@ -141,11 +141,12 @@ struct snap_ea{
 #define SNAP_MAX_TABLES        32      
 #define SNAP_MAX_NAMELEN       64
 
-#define MAX_SNAPTABLE_COUNT     "MAXSnapCount"
-#define SNAPTABLE_MAGIC                0x19760218
-#define SNAPTABLE_INFO          "snaptable"
-#define SNAP_GENERATION         "snap_generation"
-
+#define MAX_SNAPTABLE_COUNT  "MAXSnapCount"
+#define SNAPTABLE_MAGIC             0x19760218
+#define SNAPTABLE_INFO       "snaptable"
+#define SNAP_GENERATION      "snap_generation"
+#define SNAP_COUNT           "snapcount"
+#define SNAP_ROOT_INO        "snap_root_ino"
 
 #define SNAP_LOOKUP     (REINT_MAX + 1)
 
@@ -173,17 +174,24 @@ struct snap_dot_info {
 };
 
 struct snap_info {
+       struct list_head         sni_list;
+        ino_t                    sni_root_ino;
+        struct semaphore         sni_sema;
+       spinlock_t               sni_lock;
+        struct snap_table        *sni_table;
+        struct dentry            *sni_cowed_dentry;
+        struct snap_dot_info     *sni_dot_info;
+};
+
+struct snap_super_info {
         struct fsfilt_operations *snap_fsfilt;  
         struct fsfilt_operations *snap_cache_fsfilt; 
-        struct dentry            *snap_root; 
-       struct semaphore         sntbl_sema;
-       spinlock_t               sntbl_lock;
-        struct snap_table        *sntbl;
-        struct dentry            *sn_cowed_dentry;
-        struct snap_dot_info     *sn_dot_info;
+        struct list_head          snap_list;
+        int                       snap_table_size;
 };
 
-extern int smfs_add_snap_item(struct super_block *sb, char *name);
+extern int smfs_add_snap_item(struct super_block *sb, char *path_name, 
+                              char *name);
 extern int smfs_start_cow(struct super_block *sb);
 extern int smfs_stop_cow(struct super_block *sb);
 
@@ -224,7 +232,7 @@ static inline int smfs_under_dotsnap_inode(struct inode *inode)
                 return 1;
         return 0; 
 }
-
-
+#define SNAP_MINOR 242
+#define SNAP_MAJOR 10
 
 #endif /*_LUSTRE_SNAP_H*/
index 2afe0a6..822110f 100644 (file)
@@ -50,8 +50,6 @@
 #include <linux/lustre_mds.h>
 #include <linux/lustre_lite.h>
 #include <linux/lustre_dlm.h>
-#include <linux/lustre_smfs.h>
-#include <linux/lustre_snap.h>
 #include "llite_internal.h"
 
 typedef struct ext2_dir_entry_2 ext2_dirent;
@@ -356,20 +354,6 @@ int ll_readdir(struct file * filp, void * dirent, filldir_t filldir)
                                         d_type = types[de->file_type];
 
                                 offset = (char *)de - kaddr;
-#ifdef CONFIG_SNAPFS                               
-                                /*FIXME-WANGDI will get dot info from MDS*/ 
-                                if ((n << PAGE_CACHE_SHIFT | offset)  == 0) {
-                                        int off =n << PAGE_CACHE_SHIFT | offset;
-                                        over = filldir(dirent, DOT_SNAP_NAME,
-                                                       strlen(DOT_SNAP_NAME), 
-                                                       off, -1, 0); 
-                                        if (over) {
-                                                ext2_put_page(page);
-                                                GOTO(done, rc);        
-                                        }
-                                }  
-                                offset+=EXT2_DIR_REC_LEN(strlen(DOT_SNAP_NAME));     
-#endif                   
                                 over = filldir(dirent, de->name, de->name_len,
                                                (n<<PAGE_CACHE_SHIFT) | offset,
                                                le32_to_cpu(de->inode), d_type);
index dc21e21..da6bb98 100644 (file)
@@ -52,7 +52,6 @@ struct ll_sb_info {
         int                       ll_gns_state;
         struct timer_list         ll_gns_timer;
         struct list_head          ll_gns_sbi_head;
-        void                     *ll_dot_snap_info; 
 };
 
 #define LL_GNS_STATE_IDLE     1100
index 6891035..b4ba72d 100644 (file)
@@ -32,8 +32,6 @@
 #include <linux/lustre_ha.h>
 #include <linux/lustre_dlm.h>
 #include <linux/lprocfs_status.h>
-#include <linux/lustre_smfs.h>
-#include <linux/lustre_snap.h>
 #include "llite_internal.h"
 
 kmem_cache_t *ll_file_data_slab;
index 23267a8..9661a6a 100644 (file)
@@ -406,7 +406,6 @@ static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf,
                 
                 rc = snapops->fs_read_dotsnap_dir_page(sfi->c_file, buf, count, 
                                                        cache_ppos); 
-                
         } else {
                 if (cache_fsfilt->fs_readpage)
                         rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
@@ -631,12 +630,6 @@ static int fsfilt_smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt,
                 smfs_post_setup(sb, mnt);
                 if (SMFS_DO_REC(S2SMI(sb)))
                         rc = smfs_start_rec(sb, mnt);
-#if CONFIG_SNAPFS
-                if (SMFS_DO_COW(S2SMI(sb))) {
-                       S2SNAPI(sb)->snap_root = root_dentry;  
-                       rc = smfs_start_cow(sb);
-                }
-#endif
                 if (rc)
                         GOTO(exit, rc);
                 if (obd)
@@ -661,10 +654,6 @@ static int fsfilt_smfs_post_cleanup(struct obd_device *obd,
                 sb = mnt->mnt_sb;
                 if (SMFS_DO_REC(S2SMI(sb)))
                         rc = smfs_stop_rec(sb);
-#if CONFIG_SNAPFS
-                if (SMFS_DO_COW(S2SMI(sb)))
-                        rc = smfs_stop_cow(sb);
-#endif
                 smfs_post_cleanup(sb);
         }
         RETURN(rc);
@@ -985,7 +974,7 @@ static int fsfilt_smfs_set_snap_item(struct super_block *sb, char *name)
 
         ENTRY;
 #if CONFIG_SNAPFS
-        rc = smfs_add_snap_item(sb, name);
+#warning "still not implement for add snap item -wangdi"         
 #endif
         RETURN(rc);        
 }
index cbecc3d..546b44e 100644 (file)
 
 #define EXT3_SNAP_ATTR "@snap"
 #define EXT3_SNAP_GENERATION "@snap_generation"
-#define EXT3_MAX_SNAPS 20
+#define EXT3_MAX_SNAPS 10
 #define EXT3_MAX_SNAP_DATA (sizeof(struct snap_ea))
 #define EXT3_SNAP_INDEX EXT3_XATTR_INDEX_LUSTRE
+#define EXT3_SNAP_COUNT "@snapcount"
+
 
-#define SB_SNAPTABLE_INO(sb)   (EXT3_SB(sb)->s_es->s_snaptable_ino)
 #define SB_FEATURE_COMPAT(sb)  (EXT3_SB(sb)->s_es->s_feature_compat)
                                                                                                                                                                                                      
 #define SNAP_HAS_COMPAT_FEATURE(sb,mask)        \
@@ -83,7 +84,7 @@ do {                                                            \
         journal_t *journal;                                     \
         journal = EXT3_SB(sb)->s_journal;                       \
         lock_kernel();                                          \
-        handle = journal_start(journal, 1);                     \
+        handle = journal_start(journal, blocks);                \
         unlock_kernel();                                        \
         if(IS_ERR(handle)) {                                    \
                 CERROR("can't start transaction\n");            \
@@ -1565,15 +1566,26 @@ static int fsfilt_ext3_get_snap_info(struct inode *inode, void *key,
         } else if (keylen >= strlen(SNAP_GENERATION) 
                    && strcmp(key, SNAP_GENERATION) == 0) {
                 
-                rc = ext3_xattr_get(inode, EXT3_SNAP_INDEX,EXT3_SNAP_GENERATION,
-                                    (char *)val, *vallen);
+                rc = ext3_xattr_get(inode, EXT3_SNAP_INDEX,
+                                    EXT3_SNAP_GENERATION, (char *)val, *vallen);
+                if (rc == -ENODATA) {
+                        *((__u32 *)val) = 0; 
+                        *vallen = sizeof(int);
+                        rc = 0;
+                }
+                RETURN(rc);
+        } else if (keylen >= strlen(SNAP_COUNT) && 
+                   strcmp(key, SNAP_COUNT) == 0) {
+                rc = ext3_xattr_get(inode, EXT3_SNAP_INDEX,
+                                    EXT3_SNAP_COUNT, val, *vallen);
                 if (rc == -ENODATA) {
                         *((__u32 *)val) = 0; 
                         *vallen = sizeof(int);
                         rc = 0;
                 }
                 RETURN(rc);
-        } 
+        }
         RETURN(-EINVAL);
 } 
 
@@ -1592,8 +1604,8 @@ static int fsfilt_ext3_set_snap_info(struct inode *inode, void *key,
         if (keylen >= strlen(SNAPTABLE_INFO) 
             && strcmp(key, SNAPTABLE_INFO) == 0) {
                 handle_t *handle;
-                EXT3_JOURNAL_START(inode->i_sb, handle, 
-                                   EXT3_XATTR_TRANS_BLOCKS, rc); 
+                EXT3_JOURNAL_START(inode->i_sb, handle, EXT3_XATTR_TRANS_BLOCKS,
+                                    rc); 
                 if(rc)
                         RETURN(rc);
                 rc = ext3_xattr_set_handle(handle, inode, EXT3_SNAP_INDEX, 
@@ -1607,7 +1619,26 @@ static int fsfilt_ext3_set_snap_info(struct inode *inode, void *key,
                 rc = ext3_set_generation(inode, *(int*)val);
                 
                 RETURN(rc); 
-        }
+        } else if (keylen >= strlen(SNAP_COUNT) && 
+                   (strcmp(key, SNAP_COUNT) == 0)) {
+                handle_t *handle;
+                EXT3_JOURNAL_START(inode->i_sb, handle, 
+                                   EXT3_XATTR_TRANS_BLOCKS, rc); 
+                if(rc)
+                        RETURN(rc);
+                rc = ext3_xattr_set_handle(handle, inode, EXT3_SNAP_INDEX, 
+                                           EXT3_SNAP_COUNT, val, *vallen, 0); 
+               journal_stop(handle);
+                
+                RETURN(rc);
+        } else if (keylen >= strlen(SNAP_ROOT_INO) && 
+                   (strcmp(key, SNAP_ROOT_INO) == 0)) {
+        
+
+
+
+        }       
         RETURN(-EINVAL);
 }
 static int fsfilt_ext3_dir_ent_size(char *name)
index f59f55f..ac32239 100644 (file)
@@ -72,12 +72,13 @@ static struct inode* fsfilt_smfs_create_indirect(struct inode *inode,
                                                index, gen, cache_parent, del);
         post_smfs_inode(inode, cache_inode);
         post_smfs_inode(inode, cache_parent);
-        
+       #if 0 
         if (cache_ind_inode && !IS_ERR(cache_ind_inode)){ 
                 /*FIXME: get indirect inode set_cow flags*/ 
                 ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino, 
                                            inode, 0);
-        }    
+        }   
+        #endif 
         RETURN(ind_inode);
 }
 
@@ -103,12 +104,13 @@ static struct inode*  fsfilt_smfs_get_indirect(struct inode *inode,
                 cache_ind_inode = snap_fsfilt->fs_get_indirect(cache_inode, 
                                                                table, slot);
         post_smfs_inode(inode, cache_inode);
-      
+#if 0      
         if (cache_ind_inode && !IS_ERR(cache_ind_inode)){ 
                 /*FIXME: get indirect inode set_cow flags*/ 
                 ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino,
                                            inode, slot);
         }    
+#endif
         RETURN(ind_inode);
 }
 
@@ -371,11 +373,11 @@ static int fsfilt_smfs_read_dotsnap_dir_page(struct file *file, char *buf,
 {
         struct inode *inode = file->f_dentry->d_inode;
         struct fsfilt_operations *snap_cops = I2SNAPCOPS(inode);
-        struct snap_table *stbl = S2SNAPI(inode->i_sb)->sntbl;
         int    i = 0, size = 0, off_count = 0, buf_off = 0, rc = 0;
         ENTRY;
-
+#if 0
         /*Get the offset of dir ent*/
+        //struct snap_table *stbl = S2SNAPI(inode->i_sb)->sni_table;
         while (size < *off && off_count < stbl->sntbl_count) {
                 char *name = stbl->sntbl_items[i].sn_name;
                 size +=snap_cops->fs_dir_ent_size(name);
@@ -395,7 +397,9 @@ static int fsfilt_smfs_read_dotsnap_dir_page(struct file *file, char *buf,
         }
         if (rc > 0) 
                 rc = 0; 
-
+#else
+#warning "still not implement read .snap dir page for fsfilt Wangdi"
+#endif
         RETURN(rc); 
 }
 
index 7747ff3..f935f42 100644 (file)
@@ -450,13 +450,6 @@ int mds_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                 OBD_FREE(cfg_buf, data->ioc_plen1);
                 RETURN(rc);
         }
-        case OBD_IOC_SNAP_ADD: {
-                char *name = data->ioc_inlbuf1;
-                if (name) {
-                        rc = fsfilt_set_snap_item(obd, mds->mds_sb, name);
-                }
-                RETURN(rc);
-        }
         case OBD_IOC_PARSE: {
                 struct llog_ctxt *ctxt =
                         llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
@@ -468,7 +461,6 @@ int mds_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
                 RETURN(rc);
         }
-
         case OBD_IOC_DUMP_LOG: {
                 struct llog_ctxt *ctxt =
                         llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
@@ -478,7 +470,6 @@ int mds_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
                 RETURN(rc);
         }
-
         case OBD_IOC_SET_READONLY: {
                 void *handle;
                 struct inode *inode = obd->u.mds.mds_sb->s_root->d_inode;
index 830d209..649e6fe 100644 (file)
@@ -66,8 +66,8 @@ static struct lvfs_callback_ops filter_lvfs_ops;
 
 static int filter_destroy(struct obd_export *exp, struct obdo *oa,
                           struct lov_stripe_md *ea, struct obd_trans_info *);
-static struct obd_llogs *filter_grab_llog_for_group(struct obd_device *,
-                                                    int, struct obd_export *);
+struct obd_llogs *filter_grab_llog_for_group(struct obd_device *,
+                                             int, struct obd_export *);
 
 static void filter_commit_cb(struct obd_device *obd, __u64 transno,
                              void *cb_data, int error)
@@ -2837,14 +2837,6 @@ int filter_iocontrol(unsigned int cmd, struct obd_export *exp,
                 rc = llog_catalog_list(obd, 1, data);
                 RETURN(rc);
         }
-
-        case OBD_IOC_SNAP_ADD: {
-                char *name = data->ioc_inlbuf1;
-                if (name) {
-                        rc = fsfilt_set_snap_item(obd, obd->u.filter.fo_sb, name);
-                }
-                RETURN(rc);
-        }
         case OBD_IOC_LLOG_CANCEL:
         case OBD_IOC_LLOG_REMOVE:
         case OBD_IOC_LLOG_INFO:
index 2af336e..e0140ce 100644 (file)
@@ -31,6 +31,8 @@
 #define PORTALS_DEV_PATH "/dev/portals"
 #define OBD_DEV_ID 1
 #define OBD_DEV_PATH "/dev/obd"
+#define SMFS_DEV_ID  2
+#define SMFS_DEV_PATH "/dev/snapdev"
 
 int ptl_name2nal(char *str);
 int ptl_parse_ipaddr (__u32 *ipaddrp, char *str);
index 3f88fc7..9d3bd96 100644 (file)
@@ -79,7 +79,7 @@ int cache_space_post_hook(struct inode *inode, struct dentry *dentry,
 
 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;
@@ -89,7 +89,7 @@ int cache_space_hook_init(struct super_block *sb)
         if (!cache_hops) {
                 RETURN(-ENOMEM);
         }
-        rc = smfs_register_hook_ops(sb, cache_hops);      
+        rc = smfs_register_hook_ops(smfs_info, cache_hops); 
         if (rc) {
                 smfs_free_hook_ops(cache_hops);
                 RETURN(rc);
@@ -99,12 +99,11 @@ int cache_space_hook_init(struct super_block *sb)
         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(sb, CACHE_HOOK);
+        cache_hops = smfs_unregister_hook_ops(smfs_info, CACHE_HOOK);
         smfs_free_hook_ops(cache_hops);
 
         SMFS_CLEAN_CACHE_HOOK(smfs_info);
index f954063..d964ba2 100644 (file)
@@ -88,13 +88,12 @@ static int smfs_create(struct inode *dir, struct dentry *dentry,
         if (rc)
                 GOTO(exit, rc);
         
-        inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
-        if (!inode)
-                GOTO(exit, rc = -ENOMEM);
+        SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode, 
+                       rc, exit); 
 
         d_instantiate(dentry, inode);
-        sm_set_inode_ops(cache_dentry->d_inode, inode);
         post_smfs_inode(dir, cache_dir);
+        
         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, POST_HOOK, rc, 
                   exit); 
 exit:
@@ -153,7 +152,8 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry,
                         dentry->d_inode = cache_inode;
                         GOTO(exit, rc = NULL);
                 }
-                inode = smfs_get_inode(dir->i_sb, cache_inode->i_ino, dir, index);
+                SMFS_GET_INODE(dir->i_sb, cache_inode, dir, index, inode, rc2,
+                               exit);
         } else {
                 d_add(dentry, NULL);
                 GOTO(exit, rc);
@@ -224,7 +224,6 @@ static int smfs_link(struct dentry * old_dentry,
 
         SMFS_HOOK(dir, old_dentry, dentry, NULL, HOOK_LINK, handle, POST_HOOK, 
                   rc, exit); 
-        
 exit:
         unlock_kernel();
         post_smfs_dentry(cache_dentry);
@@ -310,9 +309,10 @@ static int smfs_symlink(struct inode *dir, struct dentry *dentry,
         if (cache_dir->i_op->symlink)
                 rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
 
-
-        inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
         post_smfs_inode(dir, cache_dir);
+        
+        SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode, 
+                       rc, exit); 
         if (inode)
                 d_instantiate(dentry, inode);
         else
@@ -366,11 +366,8 @@ static int smfs_mkdir(struct inode *dir, struct dentry *dentry,
         if (rc)
                 GOTO(exit, rc);
   
-        inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
-
-        if (!inode)
-                GOTO(exit, rc = -ENOENT);
-
+        SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode, 
+                       rc, exit); 
         d_instantiate(dentry, inode);
         post_smfs_inode(dir, cache_dir);
 
@@ -474,7 +471,8 @@ static int smfs_mknod(struct inode *dir, struct dentry *dentry,
                                          mode, rdev)))
                 GOTO(exit, rc);
 
-        inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
+        SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode, 
+                       rc, exit); 
 
         d_instantiate(dentry, inode);
 
@@ -603,7 +601,6 @@ static ssize_t smfs_read_dir(struct file *filp, char *buf,
         if (cache_inode->i_fop->read)
                 rc = cache_inode->i_fop->read(sfi->c_file, buf, size,
                                               cache_ppos);
-
         *ppos = *cache_ppos;
         duplicate_file(filp, sfi->c_file);
         RETURN(rc);
index bd45cfb..8ed305c 100644 (file)
 #include <linux/lustre_fsfilt.h>
 #include <linux/lustre_smfs.h>
 #include "smfs_internal.h"
-static void smfs_init_cache_inode (struct inode *inode, void *opaque)
+
+static void smfs_init_inode_info (struct inode *inode, void *opaque)
 {
-        struct smfs_inode_info *sm_info = (struct smfs_inode_info *)opaque;
+        struct smfs_iget_args *sargs = (struct smfs_iget_args*)opaque;
         struct inode *cache_inode = NULL;
-        cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino);
-        
-        if (sm_info) 
-                memcpy(I2SMI(inode), sm_info, sizeof(struct smfs_inode_info)); 
         
+        if (sargs) 
+                cache_inode = iget(S2CSB(inode->i_sb), sargs->s_ino);
+        else
+                cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino);
+                 
+        OBD_ALLOC(I2SMI(inode), sizeof(struct smfs_inode_info));
+        LASSERT(I2SMI(inode));
         I2CI(inode) = cache_inode;
+        CDEBUG(D_INODE, "cache_inode i_count ino %lu i_count %d\n",
+               cache_inode->i_ino, atomic_read(&cache_inode->i_count));
         post_smfs_inode(inode, cache_inode);
         sm_set_inode_ops(cache_inode, inode);
+       
+        if (sargs) { 
+                struct inode *dir = sargs->s_inode; 
+               
+                if (dir)
+                        I2SMI(inode)->smi_flags = I2SMI(dir)->smi_flags;
 #if CONFIG_SNAPFS
-        if (sm_info) {
-                smfs_init_snap_inode_info(inode, &sm_info->sm_sninfo);
-        }
+                if (SMFS_DO_COW(S2SMI(inode->i_sb))) {
+                        smfs_init_snap_inode_info(inode, sargs);
+                }
 #endif
+          }
+}
+
+static void smfs_clear_inode_info(struct inode *inode)
+{
+        struct inode *cache_inode = I2CI(inode);
+       
+        LASSERTF(atomic_read(&cache_inode->i_count) == 1, 
+                 "cache inode %lu i_count %d not 0\n", cache_inode->i_ino,
+                 atomic_read(&cache_inode->i_count));
+        iput(cache_inode);
+        OBD_FREE(I2SMI(inode), sizeof(struct smfs_inode_info));
 }
 
 static void smfs_read_inode2(struct inode *inode, void *opaque)
 {
         ENTRY;
+
         if (!inode)
                 return;
-
+        
         CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
-        smfs_init_cache_inode(inode, opaque);
+        smfs_init_inode_info(inode, opaque);
         CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
                inode->i_ino, atomic_read(&inode->i_count));
         EXIT;
@@ -77,18 +101,13 @@ static int smfs_test_inode(struct inode *inode, unsigned long ino,
 static int smfs_test_inode(struct inode *inode, void *opaque)
 #endif
 {
-        struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo;
-        struct snap_inode_info *test_info = (struct snap_inode_info *)opaque;
-       
-        if (!sn_info || !test_info)
-                return 0;
-        if (sn_info->sn_index != test_info->sn_index)
-                return 0;
-        if (sn_info->sn_gen != test_info->sn_gen)
-                return 0;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
-        smfs_init_cache_inode(inode, opaque);
-#endif
+        if (!opaque)
+                return 1;
+#ifdef CONFIG_SNAPFS        
+        if (SMFS_DO_COW(S2SMI(inode->i_sb)) && 
+            !smfs_snap_test_inode(inode, opaque))
+                return 0;  
+#endif        
         return 1;
 }
 
@@ -100,30 +119,31 @@ int smfs_set_inode(struct inode *inode, void *opaque)
 }
 
 struct inode *smfs_iget(struct super_block *sb, ino_t hash,
-                        struct smfs_inode_info *si_info)
+                        struct smfs_iget_args *sargs)
 {
         struct inode *inode;
 
         LASSERT(hash != 0);
-        inode = iget5_locked(sb, hash, smfs_test_inode, smfs_set_inode, 
-                             si_info);
 
+        inode = iget5_locked(sb, hash, smfs_test_inode, smfs_set_inode, sargs);
         if (inode) {
                 if (inode->i_state & I_NEW)
                         unlock_new_inode(inode);
                 CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
                        inode->i_generation, inode);
+                
+                inode->i_ino = hash;
         }
         return inode;
 }
 #else
 struct inode *smfs_iget(struct super_block *sb, ino_t hash,
-                        struct smfs_inode_info *si_info)
+                        struct smfs_iget_args *sargs)
 {
         struct inode *inode;
         LASSERT(hash != 0);
 
-        inode = iget4(sb, hash, smfs_test_inode, si_info);
+        inode = iget4(sb, hash, smfs_test_inode, sargs);
 
         if (inode)
                 CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
@@ -134,19 +154,18 @@ struct inode *smfs_iget(struct super_block *sb, ino_t hash,
 struct inode *smfs_get_inode (struct super_block *sb, ino_t hash,
                               struct inode *dir, int index)
 {
-        struct smfs_inode_info sm_info;
-        struct inode *inode = NULL;       
+        struct inode *inode = NULL;      
+        struct smfs_iget_args sargs; 
         ENTRY;
+       
+        sargs.s_index = index;
+        sargs.s_inode = inode; 
+        sargs.s_ino = hash; 
+        inode = smfs_iget(sb, hash, &sargs);
         
-        sm_info.smi_flags = I2SMI(dir)->smi_flags;
-        sm_info.sm_sninfo.sn_flags = I2SMI(dir)->sm_sninfo.sn_flags;
-        sm_info.sm_sninfo.sn_index = index;
-        sm_info.sm_sninfo.sn_gen = I2SMI(dir)->sm_sninfo.sn_gen;
-        inode = smfs_iget(sb, hash, &sm_info);
-
         RETURN(inode);
-} 
-EXPORT_SYMBOL(smfs_get_inode);
+}
 static void smfs_delete_inode(struct inode *inode)
 {
         struct inode *cache_inode;
@@ -184,7 +203,6 @@ static void smfs_delete_inode(struct inode *inode)
 #else
         hlist_del_init(&cache_inode->i_hash);
 #endif
-
         list_del(&cache_inode->i_list);
         INIT_LIST_HEAD(&cache_inode->i_list);
 
@@ -249,9 +267,15 @@ static void smfs_put_inode(struct inode *inode)
                 return;
         }
         
+        CDEBUG(D_INFO, "cache_inode i_count ino %lu i_count %d\n",
+               inode->i_ino, atomic_read(&inode->i_count));
         if (atomic_read(&cache_inode->i_count) > 1 && 
-            cache_inode != cache_inode->i_sb->s_root->d_inode)
+            cache_inode != cache_inode->i_sb->s_root->d_inode) {
+                CDEBUG(D_INFO, "cache_inode i_count ino %lu i_count %d\n",
+                       cache_inode->i_ino, 
+                       atomic_read(&cache_inode->i_count) - 1);
                 iput(cache_inode);
+        }
         
         if (S2CSB(inode->i_sb)->s_op->put_inode)
                 S2CSB(inode->i_sb)->s_op->put_inode(cache_inode);
@@ -276,18 +300,15 @@ static void smfs_write_super(struct super_block *sb)
 static void smfs_clear_inode(struct inode *inode)
 {
         struct inode *cache_inode;
-
+        
         ENTRY;
 
         if (!inode) return;
-
+        
         cache_inode = I2CI(inode);
 
-        if (cache_inode != cache_inode->i_sb->s_root->d_inode) {
-                iput(cache_inode);
-                SMFS_CLEAN_INODE_REC(inode);
-                I2CI(inode) = NULL;
-        }
+        if (cache_inode != cache_inode->i_sb->s_root->d_inode) 
+                smfs_clear_inode_info(inode);
         EXIT;
         return;
 }
index 52ac292..0a3019a 100644 (file)
 #include <linux/lustre_mds.h>
 #include <linux/lustre_debug.h>
 #include <linux/lustre_smfs.h>
+#include <linux/lustre_snap.h>
 
 #include "smfs_internal.h"
 
+static struct super_block *smfs_get_sb_by_path(char *path, int len)
+{
+        struct super_block *sb;
+        struct nameidata nd;
+        int error = 0;
+
+        ENTRY;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+        if (path_init(path, LOOKUP_FOLLOW, &nd)) {
+                error = path_walk(path, &nd);
+                if (error) {
+                        path_release(&nd);
+                        RETURN(NULL);
+                }
+        } else {
+                RETURN(NULL);
+        }
+#else
+        if (path_lookup(path, LOOKUP_FOLLOW, &nd))
+                RETURN(NULL); 
+        
+#endif
+        /* FIXME-WANGDI: add some check code here. */
+        sb = nd.dentry->d_sb;
+        path_release(&nd);
+        RETURN(sb);
+}
 
 struct smfs_control_device smfs_dev;
 
@@ -52,8 +80,8 @@ static int smfs_handle_ioctl(unsigned int cmd, unsigned long arg)
 {
         struct obd_ioctl_data *data = NULL;
          struct super_block *sb = NULL;
-        char *buf = NULL, *dir = NULL;
-        int err = 0, len = 0, count = 0, do_kml = 0;
+        char *buf = NULL;
+        int err = 0, len = 0;
 
         if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
                 CERROR("OBD ioctl: data error\n");
@@ -62,29 +90,26 @@ static int smfs_handle_ioctl(unsigned int cmd, unsigned long arg)
         data = (struct obd_ioctl_data *)buf;
 
         switch (cmd) {
-        case IOC_SMFS_START:
-        case IOC_SMFS_STOP:
-        case IOC_SMFS_REINT:
-        case IOC_SMFS_UNDO:{
-                char *name;
+        case OBD_IOC_SMFS_SNAP_ADD:{
+                char *name, *snapshot_name;
                 if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
                         CERROR("No mountpoint passed!\n");
                         GOTO(out, err = -EINVAL);
                 }
+                if (!data->ioc_inllen2 || !data->ioc_inlbuf2) {
+                        CERROR("No snapshotname passed!\n");
+                        GOTO(out, err = -EINVAL);
+                }
                 name = (char*) data->ioc_inlbuf1;
                 sb = smfs_get_sb_by_path(name,  data->ioc_inllen1);
                 if (!sb) {
                         CERROR("can not find superblock at %s\n", buf);
                         GOTO(out, err = -EINVAL);
                 }
-                /*get cmd count*/
-                if (data->ioc_inllen2 && data->ioc_inlbuf2) {
-                        dir = (char *)data->ioc_inlbuf2;
-                }
-                if (data->ioc_plen1)
-                        count = *((int*)data->ioc_pbuf1);
-                if (data->ioc_plen2)
-                        do_kml = *((int*)data->ioc_pbuf2);
+                snapshot_name = (char *)data->ioc_inlbuf2;
+#ifdef CONFIG_SNAPFS
+                err = smfs_add_snap_item(sb, name, snapshot_name);
+#endif         
                 break;
         }
         default: {
@@ -92,35 +117,12 @@ static int smfs_handle_ioctl(unsigned int cmd, unsigned long arg)
                 GOTO(out, err = -EINVAL);
         }
         }
-
-        switch (cmd) {
-        case IOC_SMFS_START:
-                err = smfs_start_rec(sb, NULL);
-                break;
-        case IOC_SMFS_STOP:
-                err = smfs_stop_rec(sb);
-                break;
-        case IOC_SMFS_REINT:
-        case IOC_SMFS_UNDO: {
-                int flags = 0;
-                if (cmd == IOC_SMFS_REINT)
-                        SET_REC_OP_FLAGS(flags, SMFS_REINT_REC);
-                else
-                        SET_REC_OP_FLAGS(flags, SMFS_UNDO_REC);
-                if (count == 0)
-                        SET_REC_COUNT_FLAGS(flags, SMFS_REC_ALL);
-                if (do_kml)
-                        SET_REC_WRITE_KML_FLAGS(flags, SMFS_WRITE_KML);
-                err = smfs_process_rec(sb, count, dir, flags);
-                break;
-        }
-        }
 out:
         if (buf)
                 obd_ioctl_freedata(buf, len);
         RETURN(err);
 }
-
+#define SMFS_MINOR 250
 static int smfs_psdev_ioctl(struct inode * inode, struct file * filp,
                             unsigned int cmd, unsigned long arg)
 {
@@ -138,7 +140,7 @@ static int smfs_psdev_open(struct inode * inode, struct file * file)
         if (!inode)
                 RETURN(-EINVAL);
         dev = MINOR(inode->i_rdev);
-        if (dev != SMFS_PSDEV_MINOR)
+        if (dev != SMFS_MINOR)
                 RETURN(-ENODEV);
 
         RETURN(0);
@@ -153,7 +155,7 @@ static int smfs_psdev_release(struct inode * inode, struct file * file)
         if (!inode)
                 RETURN(-EINVAL);
         dev = MINOR(inode->i_rdev);
-        if (dev != SMFS_PSDEV_MINOR)
+        if (dev != SMFS_MINOR)
                 RETURN(-ENODEV);
 
         RETURN(0);
@@ -161,12 +163,11 @@ static int smfs_psdev_release(struct inode * inode, struct file * file)
 
 /* declare character device */
 static struct file_operations smfscontrol_fops = {
-        ioctl:                smfs_psdev_ioctl,            /* ioctl */
-        open:                smfs_psdev_open,       /* open */
-        release:        smfs_psdev_release,    /* release */
+        .owner   = THIS_MODULE,
+        .ioctl   = smfs_psdev_ioctl,            /* ioctl */
+        .open    = smfs_psdev_open,       /* open */
+        .release = smfs_psdev_release,    /* release */
 };
-
-#define SMFS_MINOR 250
 static struct miscdevice smfscontrol_dev = {
         minor:        SMFS_MINOR,
         name:        "smfscontrol",
index 159dda5..84c30c0 100644 (file)
 #include <linux/lustre_snap.h>
 
 #include "smfs_internal.h"
-#define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + size * sizeof(struct snap)) 
-static int smfs_init_snaptabe(struct super_block *sb)
+
+#define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + \
+                              size * sizeof(struct snap)) 
+static int smfs_init_snap_super_info(struct smfs_super_info *smfs_info)
 {
-        struct snap_info         *snap_info = S2SNAPI(sb);     
-        struct snap_table        *snap_table = NULL;       
-       struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
-        struct dentry            *d_root = snap_info->snap_root;
-        int                      rc = 0, size, table_size, vallen, i;
-        ENTRY;
+        struct snap_super_info  *snap_sinfo;
+        int rc = 0;
 
-        init_MUTEX(&snap_info->sntbl_sema);
-        /*Initialized table */
-        /*get the maxsize of snaptable*/
-        vallen = sizeof(int);
-        rc = snapops->fs_get_snap_info(d_root->d_inode, MAX_SNAPTABLE_COUNT,
-                                       strlen(MAX_SNAPTABLE_COUNT), &size, 
-                                       &vallen);
-        if (size == 0) {
-                CERROR("the Max snaptable count should not be zero\n");
-                RETURN(-EINVAL);
-        }
+        ENTRY;
         
-        table_size = SNAPTABLE_SIZE(size);
+        OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_super_info));
+        if (!smfs_info->smsi_snap_info) 
+                GOTO(exit, rc = -ENOMEM);
 
-        OBD_ALLOC(snap_info->sntbl, table_size);
+        snap_sinfo = smfs_info->smsi_snap_info;
 
-        if (!snap_info->sntbl) {
-                CERROR("No MEM\n");
-                RETURN(-ENOMEM);
-        }
-        snap_table = snap_info->sntbl;
-         
-        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;
+        /*init snap fsfilt operations*/
+        if (!snap_sinfo->snap_cache_fsfilt) {
+                char *snap_cache_ftype = NULL;
+                int   tmp = strlen(smfs_info->smsi_cache_ftype) + strlen("_snap");
+                
+                OBD_ALLOC(snap_cache_ftype, tmp + 1);  
+                sprintf(snap_cache_ftype, "%s_snap", smfs_info->smsi_cache_ftype);
+                snap_sinfo->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
+                OBD_FREE(snap_cache_ftype, tmp + 1);
+                if (!snap_sinfo->snap_cache_fsfilt) {
+                        CERROR("Can not get %s fsfilt ops needed by snap\n",
+                               snap_cache_ftype);
+                        GOTO(exit, rc = -EINVAL);
+                }
         }
-        /*get snaptable info*/
-        rc = snapops->fs_get_snap_info(d_root->d_inode, SNAPTABLE_INFO, 
-                                       strlen(SNAPTABLE_INFO), 
-                                       snap_table, &table_size);       
-        if (rc < 0) {
-                if (rc == -ENODATA) {
-                        snap_table->sntbl_count = 0;
-                        CDEBUG(D_INFO, "No snaptable here\n");
-                        RETURN(0);
-                } else {
-                        CERROR("Can not retrive the snaptable from this filesystem\n");
-                        OBD_FREE(snap_table, table_size);
-                        RETURN(rc); 
+        if (!snap_sinfo->snap_fsfilt) {
+                char *snap_ftype = NULL;
+                int   tmp = strlen(smfs_info->smsi_ftype) + strlen("_snap");
+                
+                OBD_ALLOC(snap_ftype, tmp + 1);  
+                sprintf(snap_ftype, "%s_snap", smfs_info->smsi_ftype);
+                snap_sinfo->snap_fsfilt = fsfilt_get_ops(snap_ftype);
+                OBD_FREE(snap_ftype, tmp + 1);
+                if (!snap_sinfo->snap_fsfilt) {
+                        CERROR("Can not get %s fsfilt ops needed by snap\n",
+                               snap_ftype);
+                        GOTO(exit, rc = -EINVAL);
                 }
-        } 
-        if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) {
-                CERROR("On disk snaptable is not right \n");
-                OBD_FREE(snap_table, table_size);
-                RETURN(-EIO);
         }
+        INIT_LIST_HEAD(&snap_sinfo->snap_list);
+exit:
+        if (rc && smfs_info->smsi_snap_info)
+                OBD_FREE(snap_sinfo, sizeof(struct snap_super_info));
         RETURN(rc);
 }
+/*FIXME-wangdi Should remove it when integrated it with lustre*/
+static struct dentry *smfs_simple_mkdir(struct dentry *dir, char *name, 
+                                        int mode, int fix)
+{
+        struct dentry *dchild;
+        int err = 0;
+        
+        dchild = ll_lookup_one_len(name, dir, strlen(name));
+        if (IS_ERR(dchild))
+                GOTO(out_up, dchild);
+        
+        if (dchild->d_inode) {
+                int old_mode = dchild->d_inode->i_mode;
+                if (!S_ISDIR(old_mode))
+                        GOTO(out_err, err = -ENOTDIR);
+                                                                                                                                                                                                     
+                /* Fixup directory permissions if necessary */
+                if (fix && (old_mode & S_IALLUGO) != (mode & S_IALLUGO)) {
+                        CWARN("fixing permissions on %s from %o to %o\n",
+                              name, old_mode, mode);
+                        dchild->d_inode->i_mode = (mode & S_IALLUGO) |
+                                                  (old_mode & ~S_IALLUGO);
+                        mark_inode_dirty(dchild->d_inode);
+                }
+                GOTO(out_up, dchild);
+        }
+        err = vfs_mkdir(dir->d_inode, dchild, mode);
+        if (err)
+                GOTO(out_err, err);
+        RETURN(dchild);
+out_err:
+        dput(dchild);
+        dchild = ERR_PTR(err);
+out_up:
+        return dchild;
+
+}
 #define COWED_NAME_LEN       (7 + 8 + 1) 
-static int smfs_init_cowed_dir(struct super_block *sb, struct dentry* cowed_dir)  
+static int smfs_init_cowed_dir(struct snap_info *snap_info, struct dentry* dir)  
 {
-        struct snap_info *snap_info = S2SNAPI(sb);     
         struct dentry    *dentry = NULL;
-        struct lvfs_run_ctxt saved;
         char   name[COWED_NAME_LEN];
         int    rc = 0;
         ENTRY;
          
-        sprintf(name, ".cowed_%08x", (__u32)cowed_dir->d_inode->i_ino);
-        push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
-        dentry = simple_mkdir(cowed_dir, name, 0777, 1);
-        pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
+        sprintf(name, ".cowed_%08x", (__u32)dir->d_inode->i_ino);
+        /*FIXME-WANGDI: will use simple_mkdir, when integrating snap to lustre*/
+        dentry = smfs_simple_mkdir(dir, name, 0777, 1);
         if (IS_ERR(dentry)) {
                 rc = PTR_ERR(dentry);
                 CERROR("create cowed directory: rc = %d\n", rc);
                 RETURN(rc);
         }
-        snap_info->sn_cowed_dentry = dentry;
+        snap_info->sni_cowed_dentry = dentry;
         RETURN(rc);
 }
-static int smfs_init_dotinfo(struct super_block *sb)
+
+static int smfs_init_dotinfo(struct snap_info *snap_info)
 {
-        struct snap_info *snap_info = S2SNAPI(sb);
         struct snap_dot_info *dot_info = NULL;
         int rc = 0;
         ENTRY;
 
-        if (snap_info->sn_dot_info)
+        if (snap_info->sni_dot_info)
                 RETURN(-EEXIST);
        
-        OBD_ALLOC(snap_info->sn_dot_info, sizeof(struct snap_dot_info));
+        OBD_ALLOC(snap_info->sni_dot_info, sizeof(struct snap_dot_info));
         
-        if (!snap_info->sn_dot_info)
+        if (!snap_info->sni_dot_info)
                 RETURN(-ENOMEM); 
       
-        dot_info = snap_info->sn_dot_info;
+        dot_info = snap_info->sni_dot_info;
  
         OBD_ALLOC(dot_info->dot_name,  strlen(DOT_SNAP_NAME) + 1);
 
         if (!dot_info->dot_name) {
-                OBD_FREE(snap_info->sn_dot_info, sizeof(struct snap_dot_info));
+                OBD_FREE(snap_info->sni_dot_info, sizeof(struct snap_dot_info));
                 RETURN(-ENOMEM); 
         } 
         memcpy(dot_info->dot_name, DOT_SNAP_NAME, strlen(DOT_SNAP_NAME));
@@ -154,103 +178,99 @@ static int smfs_init_dotinfo(struct super_block *sb)
         RETURN(rc);
 }
 
-static int smfs_cleanup_dotinfo(struct super_block *sb)
-{       
-        struct snap_info *snap_info = S2SNAPI(sb);
-        struct snap_dot_info *dot_info = NULL;
-        int rc = 0;
+static int smfs_init_snap_info(struct smfs_super_info *smb, 
+                               struct snap_info *snap_info, struct dentry *de) 
+{
+        struct snap_table        *snap_table = NULL;       
+       struct fsfilt_operations *snapcops;
+        int                      rc = 0, size, table_size, vallen, i;
+        struct inode             *root_inode = NULL;
         ENTRY;
 
-        if (!snap_info->sn_dot_info)
-                RETURN(rc);
-       
-        dot_info = snap_info->sn_dot_info;
-
-        if (dot_info->dot_name) { 
-                OBD_FREE(dot_info->dot_name, dot_info->dot_name_len + 1);
+        root_inode = iget(smb->smsi_sb, de->d_inode->i_ino); 
+        if (!root_inode || is_bad_inode(root_inode))
+                RETURN(-EIO);
+        snapcops = smb->smsi_snap_info->snap_cache_fsfilt;
+        /*Initialized table */
+        /*get the maxsize of snaptable*/
+        vallen = sizeof(int);
+        rc = snapcops->fs_get_snap_info(root_inode, MAX_SNAPTABLE_COUNT,
+                                       strlen(MAX_SNAPTABLE_COUNT), &size, 
+                                       &vallen);
+        if (size == 0) {
+                CERROR("the Max snaptable count should not be zero\n");
+                GOTO(exit, rc);
         }
-        
-        OBD_FREE(dot_info, sizeof(struct snap_dot_info));
-
-        RETURN(rc);
-}
+        table_size = SNAPTABLE_SIZE(size);
 
-int smfs_start_cow(struct super_block *sb)
-{
-        int rc = 0;
+        OBD_ALLOC(snap_info->sni_table, table_size);
 
-        ENTRY;
-        
-        /*init snap fsfilt operations*/
-        if (!S2SNAPI(sb)->snap_cache_fsfilt) {
-                char *snap_cache_ftype = NULL;
-                int   tmp = strlen(S2SMI(sb)->smsi_cache_ftype) + strlen("_snap");
-                
-                OBD_ALLOC(snap_cache_ftype, tmp + 1);  
-                sprintf(snap_cache_ftype, "%s_snap", S2SMI(sb)->smsi_cache_ftype);
-                S2SNAPI(sb)->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
-                OBD_FREE(snap_cache_ftype, tmp + 1);
-                if (!S2SNAPI(sb)->snap_cache_fsfilt) {
-                        CERROR("Can not get %s fsfilt ops needed by snap\n",
-                               snap_cache_ftype);
-                        RETURN(-EINVAL);
-                }
+        if (!snap_info->sni_table) {
+                CERROR("No MEM\n");
+                RETURN(-ENOMEM);
         }
-        if (!S2SNAPI(sb)->snap_fsfilt) {
-                char *snap_ftype = NULL;
-                int   tmp = strlen(S2SMI(sb)->smsi_ftype) + strlen("_snap");
-                
-                OBD_ALLOC(snap_ftype, tmp + 1);  
-                sprintf(snap_ftype, "%s_snap", S2SMI(sb)->smsi_ftype);
-                S2SNAPI(sb)->snap_fsfilt = fsfilt_get_ops(snap_ftype);
-                OBD_FREE(snap_ftype, tmp + 1);
-                if (!S2SNAPI(sb)->snap_fsfilt) {
-                        CERROR("Can not get %s fsfilt ops needed by snap\n",
-                               snap_ftype);
-                        RETURN(-EINVAL);
+        snap_table = snap_info->sni_table;
+         
+        snap_table->sntbl_magic = cpu_to_le32((__u32)SNAPTABLE_MAGIC); 
+        snap_table->sntbl_max_count = size;
+        /*init sn_index to -1*/ 
+        for (i = 0; i < snap_table->sntbl_max_count; i++) 
+                snap_table->sntbl_items[i].sn_index = -1;
+        /*get snaptable info*/
+        rc = snapcops->fs_get_snap_info(root_inode, SNAPTABLE_INFO, 
+                                        strlen(SNAPTABLE_INFO), 
+                                        snap_table, &table_size);       
+        if (rc < 0) {
+                if (rc == -ENODATA) {
+                        snap_table->sntbl_count = 0;
+                } else {
+                        CERROR("Can not retrive the snaptable from this filesystem\n");
+                        GOTO(exit, rc);
+                }
+        } else { 
+                if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) {
+                        CERROR("On disk snaptable is not right \n");
+                        GOTO(exit, rc = -EIO);
                 }
         }
-        rc = smfs_init_snaptabe(sb); 
-        if (rc) {
-                CERROR("can not init snaptable rc=%d\n", rc);
-                RETURN(rc);
-        }
-        /*init dot snap info*/
-        rc = smfs_init_dotinfo(sb);
+        init_MUTEX(&snap_info->sni_sema);
+        snap_info->sni_root_ino = de->d_inode->i_ino;
+        rc = smfs_init_cowed_dir(snap_info, de);
         if (rc) {
-                CERROR("can not init dot snap info rc=%d\n", rc);
-                RETURN(rc);
+                CERROR("Init cowed dir error rc=%d\n", rc);
+                GOTO(exit, rc); 
         }
-        /*init cowed dir to put the primary cowed inode
-         *FIXME-WANGDI, later the s_root may not be the 
-         *snap dir, we can indicate any dir to be cowed*/
-        rc = smfs_init_cowed_dir(sb, sb->s_root);
+        rc = smfs_init_dotinfo(snap_info);
+exit:
+        if (root_inode) 
+                iput(root_inode);
+        if (rc && snap_table)
+                OBD_FREE(snap_table, table_size);
         RETURN(rc);
 }
-EXPORT_SYMBOL(smfs_start_cow);
-int smfs_stop_cow(struct super_block *sb)
+
+static struct snap_info *smfs_create_snap_info(struct smfs_super_info *sinfo, 
+                                               struct dentry *dentry)
 {
-        struct snap_info       *snap_info = S2SNAPI(sb);       
-        struct snap_table      *snap_table = snap_info->sntbl; 
-        int rc = 0, table_size;
+        struct snap_info *snap_info = NULL;
+        int rc = 0;
         ENTRY;
-
-        l_dput(snap_info->sn_cowed_dentry);
-         
-        if (snap_info->snap_fsfilt) 
-                fsfilt_put_ops(snap_info->snap_fsfilt);
-        if (snap_info->snap_cache_fsfilt)
-                fsfilt_put_ops(snap_info->snap_cache_fsfilt);
-
-        if (snap_table) {
-                table_size =  SNAPTABLE_SIZE(snap_table->sntbl_max_count);
-                OBD_FREE(snap_info->sntbl, table_size);
-        }
-        smfs_cleanup_dotinfo(sb);
-         
-        RETURN(rc);
+        OBD_ALLOC(snap_info, sizeof(struct snap_info)); 
+        if (!snap_info) 
+                RETURN(ERR_PTR(-ENOMEM));  
+        rc = smfs_init_snap_info(sinfo, snap_info, dentry);  
+        if (rc) 
+                GOTO(exit, snap_info = ERR_PTR(rc));
+       
+        /*set cow flags for the snap root inode*/ 
+        I2SMI(dentry->d_inode)->smi_flags |= SM_DO_COW; 
+exit:
+        if (rc)
+                OBD_FREE(snap_info, sizeof(struct snap_info));
+        RETURN(snap_info);
 }
-EXPORT_SYMBOL(smfs_stop_cow);
 
 #define COW_HOOK "cow_hook"
 static int smfs_cow_pre_hook(struct inode *inode, struct dentry *dentry, 
@@ -268,7 +288,9 @@ int smfs_cow_init(struct super_block *sb)
 {
         struct smfs_super_info *smfs_info = S2SMI(sb);
         struct smfs_hook_ops *cow_hops = NULL;
-        int rc = 0;
+        struct fsfilt_operations *sops;
+        struct inode *root_inode = smfs_info->smsi_sb->s_root->d_inode; 
+        int snap_count = 0, rc = 0, vallen;
 
         ENTRY;
 
@@ -279,52 +301,170 @@ int smfs_cow_init(struct super_block *sb)
                 RETURN(-ENOMEM);
         }
  
-        rc = smfs_register_hook_ops(sb, cow_hops);      
-
+        rc = smfs_register_hook_ops(smfs_info, cow_hops);
         if (rc) {
                 smfs_free_hook_ops(cow_hops);
                 RETURN(rc);
         }
-        OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
         
-        if (!smfs_info->smsi_snap_info) 
-                GOTO(exit, rc = -ENOMEM);
-exit:
+        rc = smfs_init_snap_super_info(smfs_info);
         if (rc && cow_hops) {
-                smfs_unregister_hook_ops(sb, cow_hops->smh_name);
+                smfs_unregister_hook_ops(smfs_info, cow_hops->smh_name);
                 smfs_free_hook_ops(cow_hops);
-        } 
+                RETURN(rc);
+        }
+        sops = smfs_info->smsi_snap_info->snap_cache_fsfilt; 
+        
+        vallen = sizeof(int); 
+        rc = sops->fs_get_snap_info(root_inode, SNAP_COUNT, strlen(SNAP_COUNT),
+                                    &snap_count, &vallen);
+        if (rc)
+                GOTO(exit, rc);       
+        if (snap_count > 0) {
+                int snap_root_size = snap_count * sizeof(ino_t);
+                ino_t *snap_root;
+                int i;
+                
+                OBD_ALLOC(snap_root, snap_root_size);
+                
+                if (!snap_root)
+                        GOTO(exit, rc = -ENOMEM); 
+                
+                rc = sops->fs_get_snap_info(root_inode, SNAP_ROOT_INO, 
+                                            strlen(SNAP_ROOT_INO), snap_root, 
+                                            &snap_root_size);
+                if (rc) {
+                        OBD_FREE(snap_root, sizeof(int) * snap_count);
+                        GOTO(exit, rc);
+                }
+                for (i = 0; i < snap_count; i++) {
+                        ino_t root_ino = le32_to_cpu(snap_root[i]);
+                        struct dentry *tmp = smfs_info->smsi_sb->s_root;
+                        struct snap_info *snap_info;                      
+                        struct dentry *dentry;                        
+                        root_inode = smfs_get_inode(sb, root_ino, NULL, 0);
+                        dentry = pre_smfs_dentry(NULL, root_inode, tmp, 
+                                                 NULL); 
+                        snap_info = smfs_create_snap_info(S2SMI(sb), dentry);
+                        post_smfs_dentry(dentry);
+                        if (IS_ERR(snap_info)) {
+                                OBD_FREE(snap_root, sizeof(int) * snap_count);
+                                GOTO(exit, rc = PTR_ERR(snap_info));
+                        }                
+                        list_add(&snap_info->sni_list, &(S2SNAPI(sb)->snap_list));        
+                }
+        }       
+exit:
+        if (rc) 
+                smfs_cow_cleanup(smfs_info);
+        
         RETURN(rc);
 }
 
-int smfs_cow_cleanup(struct super_block *sb)
-{
+static int smfs_cleanup_dotinfo(struct snap_info *snap_info)
+{       
+        struct snap_dot_info *dot_info = NULL;
+        int rc = 0;
+        ENTRY;
+
+        if (!snap_info->sni_dot_info)
+                RETURN(rc);
+       
+        dot_info = snap_info->sni_dot_info;
+
+        if (dot_info->dot_name) { 
+                OBD_FREE(dot_info->dot_name, dot_info->dot_name_len + 1);
+        }
         
-        struct snap_info   *snap_info = S2SNAPI(sb);   
-        struct smfs_hook_ops *cow_hops; 
+        OBD_FREE(dot_info, sizeof(struct snap_dot_info));
+
+        RETURN(rc);
+}
+
+int smfs_cleanup_snap_info(struct snap_info *snap_info)
+{
+        struct snap_table      *snap_table = snap_info->sni_table;
+        int rc = 0, table_size;
         ENTRY;
 
-        cow_hops = smfs_unregister_hook_ops(sb, COW_HOOK);
+        l_dput(snap_info->sni_cowed_dentry);
+        if (snap_table) {
+                table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count);
+                OBD_FREE(snap_info->sni_table, table_size);
+        }
+        smfs_cleanup_dotinfo(snap_info);
+        RETURN(rc);
+}
+
+int smfs_cow_cleanup(struct smfs_super_info *smb)
+{
+        struct snap_super_info   *snap_sinfo = smb->smsi_snap_info;
+        struct list_head        *snap_list = &snap_sinfo->snap_list; 
+        struct smfs_hook_ops     *cow_hops;
+        int                      rc = 0; 
+        ENTRY;
+
+        while (!list_empty(snap_list)) {
+                struct snap_info *snap_info;
+                
+                snap_info = list_entry(snap_list->next, struct snap_info,
+                                       sni_list); 
+                rc = smfs_cleanup_snap_info(snap_info); 
+                if (rc) 
+                        CERROR("cleanup snap_info error rc=%d\n", rc);
+                list_del(&snap_info->sni_list); 
+                OBD_FREE(snap_info, sizeof(struct snap_info));
+        } 
+         
+        if (snap_sinfo->snap_fsfilt) 
+                fsfilt_put_ops(snap_sinfo->snap_fsfilt);
+        if (snap_sinfo->snap_cache_fsfilt)
+                fsfilt_put_ops(snap_sinfo->snap_cache_fsfilt);
+
+        cow_hops = smfs_unregister_hook_ops(smb, COW_HOOK);
         smfs_free_hook_ops(cow_hops);
 
-        SMFS_CLEAN_COW(S2SMI(sb));
-        if (snap_info) 
-               OBD_FREE(snap_info, sizeof(*snap_info)); 
-        RETURN(0);
+        SMFS_CLEAN_COW(smb);
+        if (snap_sinfo) 
+               OBD_FREE(snap_sinfo, sizeof(struct snap_super_info));
+        RETURN(rc);
 }
 
+static struct snap_info *smfs_find_snap_info(struct inode *inode)
+{
+        struct snap_inode_info *snap_iinfo = I2SNAPI(inode);
+        struct snap_super_info *snap_sinfo = S2SNAPI(inode->i_sb);
+        struct snap_info *snap_info = NULL, *tmp; 
+
+        ENTRY;
+        list_for_each_entry_safe(snap_info, tmp, &snap_sinfo->snap_list, 
+                                 sni_list) {
+               if (snap_info->sni_root_ino == snap_iinfo->sn_root_ino)
+                        RETURN(snap_info); 
+        }
+        RETURN(NULL);
+}
 static int smfs_dotsnap_dir_size(struct inode *inode)
 {
-        struct snap_info *snap_info = S2SNAPI(inode->i_sb);
-        struct fsfilt_operations *snapops = snap_info->snap_cache_fsfilt; 
-        struct snap_table *stbl = snap_info->sntbl;
-        int size = 0, dir_size = 0, blocks;
-        int i = 0;
+        struct snap_super_info *snap_sinfo = S2SNAPI(inode->i_sb);
+        struct fsfilt_operations *snapops = snap_sinfo->snap_cache_fsfilt; 
+        int size = 0, dir_size = 0, blocks, i = 0;
+        struct snap_table *snap_table = NULL; 
+        struct snap_info *snap_info = NULL;
         ENTRY;
-
-        for (i = 0; i < stbl->sntbl_count; i++) {
-                size += snapops->fs_dir_ent_size(stbl->sntbl_items[i].sn_name);
+       
+        snap_info = smfs_find_snap_info(inode);
+        
+        if (!snap_info) {
+                CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+                RETURN(0);                
+        }
+        snap_table = snap_info->sni_table;
+        for (i = 0; i < snap_table->sntbl_count; i++) {
+                char *name = snap_table->sntbl_items[i].sn_name;
+                size += snapops->fs_dir_ent_size(name);
         }
         /*FIXME this is only for ext3 dir format, may need fix for other FS*/ 
         blocks = (size + inode->i_sb->s_blocksize - 1) >> 
@@ -334,40 +474,69 @@ static int smfs_dotsnap_dir_size(struct inode *inode)
         RETURN(dir_size); 
 
 } 
+int smfs_snap_test_inode(struct inode *inode, void *args)
+{ 
+        struct smfs_iget_args *sargs = (struct smfs_iget_args*)args;
+        struct inode *dir;
+
+        LASSERT(sargs);
+        
+        dir = sargs->s_inode;
+        
+        if (dir){
+                if (I2SNAPI(inode)->sn_index != I2SNAPI(dir)->sn_index)
+                        return 0;
+        } else { 
+                if (I2SNAPI(inode)->sn_index != sargs->s_index)
+                        return 0; 
+        }
+        return 1;
+}
+
 /*FIXME Note indirect and primary inode 
 * should be recorgnized here*/
-int smfs_init_snap_inode_info(struct inode *inode, 
-                              struct snap_inode_info *sn_info) 
+int smfs_init_snap_inode_info(struct inode *inode, struct smfs_iget_args *args) 
 {
-        struct smfs_inode_info *smi = I2SMI(inode);
+        struct inode *dir;
         int vallen, rc = 0;
         ENTRY;
 
-        LASSERT(sn_info && smi);
-        smi->sm_sninfo.sn_flags = sn_info->sn_flags;
-        smi->sm_sninfo.sn_gen = sn_info->sn_gen;
-        smi->sm_sninfo.sn_index = sn_info->sn_index; 
+        LASSERT(args);
 
+        I2SNAPI(inode)->sn_index = args->s_index; 
+        
+        dir = args->s_inode;
+        if (dir) {
+                I2SNAPI(inode)->sn_flags = I2SNAPI(dir)->sn_flags;
+                I2SNAPI(inode)->sn_gen = I2SNAPI(dir)->sn_gen;
+        } else {
+                I2SNAPI(inode)->sn_flags = 0;
+                I2SNAPI(inode)->sn_gen = 0;
+        }
+        
         if (smfs_dotsnap_inode(inode)) {
-                struct snap_table *stbl= S2SNAPI(inode->i_sb)->sntbl;
-                int size = 0;
+                struct snap_info *snap_info;
+
+                snap_info = smfs_find_snap_info(inode);
+                if (!snap_info) {
+                        RETURN(-EIO);
+                }
                 /*init dot_snap inode info*/
-                size = smfs_dotsnap_dir_size(inode); 
-                inode->i_size = (loff_t)size;                   
-                inode->i_nlink = stbl->sntbl_count + 2;
+                inode->i_size = (loff_t)smfs_dotsnap_dir_size(inode);
+                inode->i_nlink = snap_info->sni_table->sntbl_count + 2;
                 inode->i_uid = 0;
                 inode->i_gid = 0;
         } else if (SMFS_DO_COW(S2SMI(inode->i_sb)) && 
-                   (smi->smi_flags & SM_DO_COW) &&
+                   (I2SMI(inode)->smi_flags & SM_DO_COW) &&
                    smfs_primary_inode(inode)) {
                 struct snap_inode_info *sni_info = I2SNAPI(inode);
-                struct fsfilt_operations *snapops = I2SNAPOPS(inode);
+                struct fsfilt_operations *sops = I2SNAPCOPS(inode);
                 
                 vallen = sizeof(sni_info->sn_gen);
                 
-                rc = snapops->fs_get_snap_info(inode, SNAP_GENERATION,
-                                               strlen(SNAP_GENERATION),
-                                               &sni_info->sn_gen, &vallen);               
+                rc = sops->fs_get_snap_info(I2CI(inode), SNAP_GENERATION,
+                                            strlen(SNAP_GENERATION),
+                                            &sni_info->sn_gen, &vallen);               
         } 
         RETURN(rc);                                              
 }
@@ -376,22 +545,30 @@ int smfs_init_snap_inode_info(struct inode *inode,
    -  hence it returns 0 in case all the volume snapshots lie in the future
    -  this is the index where a COW will land (will be created) 
 */
-void snap_last(struct super_block *sb, struct snap *snap)
+void snap_last(struct inode *inode, struct snap *snap)
 {
-       struct snap_info *snap_info = S2SNAPI(sb);
-       struct snap_table *table = snap_info->sntbl;
         time_t now = LTIME_S(CURRENT_TIME);
+       struct snap_table *snap_table;
+        struct snap_info  *snap_info;
        int i ;
 
        ENTRY;
+
+        snap_info = smfs_find_snap_info(inode);
+        if (!snap_info) {
+                CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+                EXIT;
+                return;
+        }
+        snap_table = snap_info->sni_table;
        /* start at the highest index in the superblock snaptime array */ 
-       if (table->sntbl_count == 0) {
+       if (snap_table->sntbl_count == 0) {
                memset(snap, 0, sizeof(struct snap)); 
         } else {
-                i = table->sntbl_count - 1;
-                snap->sn_index = table->sntbl_items[i].sn_index;
-                snap->sn_time = table->sntbl_items[i].sn_time;
-                snap->sn_gen = table->sntbl_items[i].sn_gen;
+                i = snap_table->sntbl_count - 1;
+                snap->sn_index = snap_table->sntbl_items[i].sn_index;
+                snap->sn_time = snap_table->sntbl_items[i].sn_time;
+                snap->sn_gen = snap_table->sntbl_items[i].sn_gen;
         }
        CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
               snap->sn_index, snap->sn_time, now);
@@ -399,7 +576,7 @@ void snap_last(struct super_block *sb, struct snap *snap)
        return;
 }
 
-static int inline get_index_of_item(struct snap_table *table, char *name)
+static inline int get_index_of_item(struct snap_table *table, char *name)
 {
        int count = table->sntbl_count;
        int i, j;
@@ -427,20 +604,51 @@ static int inline get_index_of_item(struct snap_table *table, char *name)
        RETURN(-ENOSPC);
 }
 
-int smfs_add_snap_item(struct super_block *sb, char *name)
+static struct dentry *smfs_find_snap_root(struct super_block *sb, 
+                                          char *path_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;
+        struct dentry *dentry = NULL;
+        struct nameidata nd;
+        ENTRY;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+        if (path_init(path_name, LOOKUP_FOLLOW, &nd)) {
+                error = path_walk(path_name, &nd);
+                if (error) {
+                        path_release(&nd);
+                        RETURN(NULL);
+                }
+        } else {
+                RETURN(NULL);
+        }
+#else
+        if (path_lookup(path_name, LOOKUP_FOLLOW, &nd))
+                RETURN(NULL);
+                                                                                                                                                                                                     
+#endif
+        dentry = dget(nd.dentry); 
+        path_release(&nd);
+        RETURN(dentry); 
+}
+static int snap_add_item(struct smfs_super_info *smb, 
+                         struct snap_info *snap_info,
+                         char *name)
+{        
+        struct fsfilt_operations *snapops;
+        struct snap_table        *snap_table = snap_info->sni_table;
+        struct inode             *root_inode = NULL;
+        int                      table_size, count = 0, index = 0, rc = 0;
+               struct  snap             *snap_item;
+        ENTRY;
 
         count = snap_table->sntbl_count; 
+        root_inode = iget(smb->smsi_sb, snap_info->sni_root_ino);
+        if (!root_inode || is_bad_inode(root_inode)) 
+                RETURN(-EIO); 
        /* XXX Is down this sema necessary*/
-       down_interruptible(&snap_info->sntbl_sema);
+       down_interruptible(&snap_info->sni_sema);
         snap_item = &snap_table->sntbl_items[count];
-
+        snapops = smb->smsi_snap_info->snap_cache_fsfilt;
        /*add item in snap_table set generation*/
        snap_item->sn_time = LTIME_S(CURRENT_TIME);
        /* find table index */
@@ -454,8 +662,8 @@ int smfs_add_snap_item(struct super_block *sb, char *name)
        memcpy(snap_item->sn_name, name, SNAP_MAX_NAMELEN);
        /* Wrote the whole snap_table to disk */
         table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); 
-        
-        rc = snapops->fs_set_snap_info(d_root->d_inode, SNAPTABLE_INFO, 
+         
+        rc = snapops->fs_set_snap_info(root_inode, SNAPTABLE_INFO, 
                                        strlen(SNAPTABLE_INFO),
                                       snap_table, &table_size);
        if (rc) {
@@ -465,10 +673,71 @@ int smfs_add_snap_item(struct super_block *sb, char *name)
         snap_table->sntbl_count++;
        snap_table->sntbl_generation++;
 exit:
-       up(&snap_info->sntbl_sema);
+       up(&snap_info->sni_sema);
+        if (root_inode)
+                iput(root_inode);
        RETURN(rc);
 }
-EXPORT_SYMBOL(smfs_add_snap_item);
+
+static struct snap_info * smfs_find_create_snap_info(struct super_block *sb, 
+                                                     struct dentry *dentry) 
+{      
+        struct snap_super_info   *snap_sinfo = S2SNAPI(sb);
+        struct snap_info *snap_info, *tmp;
+        ENTRY;
+        
+        list_for_each_entry_safe(snap_info, tmp, &snap_sinfo->snap_list, 
+                                 sni_list) {
+                if (snap_info->sni_root_ino == dentry->d_inode->i_ino) {
+                        RETURN(snap_info);
+                }      
+        } 
+
+        CDEBUG(D_INFO, "create a new  snap info root ino %lu\n", 
+               dentry->d_inode->i_ino);
+
+        snap_info = smfs_create_snap_info(S2SMI(sb), dentry);  
+
+        if (IS_ERR(snap_info))
+                RETURN(snap_info);
+
+        list_add(&snap_info->sni_list, &snap_sinfo->snap_list);        
+        RETURN(snap_info);  
+}         
+
+int smfs_add_snap_item(struct super_block *sb, char *path_name, char *name)
+{
+        struct dentry  *dentry = NULL;
+        struct snap_info *snap_info;
+        int            rc = 0;        
+        ENTRY;
+                
+        if (!SMFS_DO_COW(S2SMI(sb))) {
+                RETURN(0);
+        }
+
+        if (!path_name || !name) {
+                CERROR("patch_name and snapshot_name is NULL");
+                RETURN(-EINVAL);
+        } 
+        dentry = smfs_find_snap_root(sb, path_name);
+        if (IS_ERR(dentry)) {
+                CERROR("can not find snap_shot root by %s\n", path_name);
+                RETURN(PTR_ERR(dentry)); 
+        }
+        snap_info = smfs_find_create_snap_info(sb, dentry);
+        if (IS_ERR(snap_info)) {
+                CERROR("can not find snap_info by %s rc=%lu\n", path_name,
+                        PTR_ERR(snap_info));
+                GOTO(exit, rc = PTR_ERR(snap_info)); 
+        }
+
+        rc = snap_add_item(S2SMI(sb), snap_info, name);
+exit:       
+        dput(dentry); 
+        RETURN(rc); 
+}        
+//EXPORT_SYMBOL(smfs_add_snap_item);
 /*
  * Note: this function should be differnet with snap_do_cow.
  * In smfs_do_cow, we check the EA for whether do cow for that inode.
@@ -484,7 +753,7 @@ int smfs_needs_cow(struct inode *inode)
 
        snap_info = &(smi_info->sm_sninfo);
        
-        snap_last(inode->i_sb, &snap);
+        snap_last(inode, &snap);
        /* decision .... if the snapshot is more recent than the object,
         * then any change to the object should cause a COW.
         */
@@ -499,15 +768,21 @@ int smfs_needs_cow(struct inode *inode)
 
 static int link_cowed_inode(struct inode *inode)
 {
-        struct snap_info *snap_info = S2SNAPI(inode->i_sb);    
         struct dentry *cowed_dir = NULL;
         char fidname[LL_FID_NAMELEN];
+        struct snap_info *snap_info;   
         int fidlen = 0, rc = 0;
         struct dentry *dchild = NULL;
         struct dentry *tmp = NULL;
         unsigned mode;
 
-        cowed_dir = snap_info->sn_cowed_dentry;
+        snap_info = smfs_find_snap_info(inode);
+        if (!snap_info) {
+                CERROR("can not find snap info for inode %p\n", inode);
+                RETURN(-EINVAL);                
+        }
+
+        cowed_dir = snap_info->sni_cowed_dentry;
         
         fidlen = ll_fid2str(fidname, inode->i_ino, inode->i_generation);
 
@@ -553,25 +828,29 @@ out_lock:
  */
 int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
 {
-        struct snap_info *snap_info = S2SNAPI(inode->i_sb);    
-       struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
+       struct fsfilt_operations *snapops = I2SNAPCOPS(inode);
         struct snap snap;
-       struct inode *ind = NULL;
-
-       ENTRY;
+       struct inode *ind = NULL, *cache_ind = NULL;
+       ino_t  ind_ino;
+        ENTRY;
 
        if (!snapops || !snapops->fs_create_indirect) 
                RETURN(-EINVAL);
 
-       snap_last(inode->i_sb, &snap);
-       ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen, 
-                                          dparent->d_inode, del);
-       if(ind && IS_ERR(ind)) {
+       snap_last(inode, &snap);
+       cache_ind = snapops->fs_create_indirect(I2CI(inode), snap.sn_index, 
+                                          snap.sn_gen, I2CI(dparent->d_inode), 
+                                          del);
+       if(cache_ind && IS_ERR(cache_ind)) {
                 CERROR("Create ind inode %lu index %d gen %d del %d rc%lu\n",
                         inode->i_ino, snap.sn_index, snap.sn_gen, del,
-                        PTR_ERR(ind));
+                        PTR_ERR(cache_ind));
                RETURN(PTR_ERR(ind));
         }
+        ind_ino = cache_ind->i_ino;
+        iput(cache_ind);
+        /*FIXME: get indirect inode set_cow flags*/ 
+        ind = smfs_get_inode(inode->i_sb, ind_ino, inode, 0);
         if (ind) { 
                 if (!SMFS_DO_INODE_COWED(inode)) {
                         /*insert the inode to cowed inode*/
@@ -715,8 +994,8 @@ int smfs_cow_rename(struct inode *dir, struct dentry *dentry,
 int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1,
                    void *data2)
 {
-        struct snap_info *snap_info = S2SNAPI(inode->i_sb)
-        struct snap_table *table = snap_info->sntbl
+        struct snap_info *snap_info = NULL
+        struct snap_table *table; 
        long   blocks[2]={-1,-1};
                int  index = 0, i, rc = 0;
         size_t count;
@@ -724,6 +1003,13 @@ int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1,
 
         ENTRY;
 
+        snap_info = smfs_find_snap_info(inode);
+        if (!snap_info) {
+                CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+                RETURN(0);                
+        }
+        table = snap_info->sni_table;
+
         LASSERT(data1);
         LASSERT(data2);
         
@@ -756,29 +1042,29 @@ int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1,
                        continue;
                /*Find the nearest page in snaptable and copy back it*/
                for (slot = table->sntbl_count - 1; slot >= 0; slot--) {
-                        struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
-                       struct inode *cache_inode = NULL;
+                        struct fsfilt_operations *sops = I2SNAPCOPS(inode);
+                       struct inode *cind = NULL;
                                int result = 0;
 
                         index = table->sntbl_items[slot].sn_index;
-                       cache_inode = snapops->fs_get_indirect(inode, NULL, index);
-
-                       if (!cache_inode)  continue;
+                       cind = sops->fs_get_indirect(I2CI(inode), NULL, index);
+                       if (!cind)  continue;
 
-                       CDEBUG(D_INFO, "find cache_ino %lu\n", cache_inode->i_ino);
+                       CDEBUG(D_INFO, "find cache_ino %lu\n", cind->i_ino);
                
-                       result = snapops->fs_copy_block(inode, cache_inode, blocks[i]);
+                       result = sops->fs_copy_block(I2CI(inode), cind, 
+                                                     blocks[i]);
                        if (result == 1) {
-                                       iput(cache_inode);
+                                       iput(cind);
                                result = 0;
                                break;
                        }
                        if (result < 0) {
-                               iput(cache_inode);
+                               iput(cind);
                                up(&inode->i_sem);
                                GOTO(exit, rc = result);
                        }
-                               iput(cache_inode);
+                               iput(cind);
                }
        }
 exit:
@@ -787,7 +1073,8 @@ exit:
 }
 EXPORT_SYMBOL(smfs_cow_write);
 /*lookup inode in dotsnap inode */
-static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry)
+static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry,
+                               struct snap_info *snap_info)
 { 
         if (dentry->d_name.len == 1 && 
             !strcmp(dentry->d_name.name, ".")) {
@@ -807,10 +1094,14 @@ static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry)
                 }
         } else {
                 /*find the name from the snaptable*/
-                struct fsfilt_operations *snapops = I2SNAPOPS(dir);
-                struct snap_table *table = S2SNAPI(dir->i_sb)->sntbl
+                struct fsfilt_operations *sops = I2SNAPCOPS(dir);
+                struct snap_table *table; 
                 struct inode *inode;
+                ino_t  cino;
                 int i = 0, index = -1;
+
+                table = snap_info->sni_table;
+                
                 for (i = 0; i < table->sntbl_count; i++) {
                         char *name = table->sntbl_items[i].sn_name;
                         if ((dentry->d_name.len == strlen(name)) &&
@@ -825,7 +1116,13 @@ static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry)
                                dentry->d_name.name);
                        RETURN(-ENOENT);
                 }
-                inode = snapops->fs_get_indirect(dir, NULL, index);
+                cino = sops->fs_get_indirect_ino(S2CSB(dir->i_sb), dir->i_ino,
+                                                 index);
+                inode = smfs_get_inode(dir->i_sb, cino, dir, index);
+                if (!inode || is_bad_inode(inode)) {
+                        CERROR("Can not find cino %lu inode\n", cino);
+                        RETURN(-ENOENT); 
+                } 
                 d_add(dentry, inode);
         } 
         RETURN(0);
@@ -833,11 +1130,19 @@ static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry)
 int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1,
                     void *data2)
 {
-        struct snap_info *snap_info = S2SNAPI(inode->i_sb);
-        struct snap_dot_info *dot_info = snap_info->sn_dot_info;
+        struct snap_info *snap_info;
+        struct snap_dot_info *dot_info;
         int rc = 0, index = 0;
         ENTRY;
 
+        snap_info = smfs_find_snap_info(inode);
+        if (!snap_info) {
+                CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+                RETURN(0);                
+        }
+        
+        dot_info = snap_info->sni_dot_info;
+
         LASSERT(dot_info != NULL); 
         LASSERT(data1 != NULL); 
         
@@ -856,7 +1161,7 @@ int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1,
                 RETURN(rc);
         }
         if (smfs_dotsnap_inode(inode)) {
-                rc = smfs_dotsnap_lookup(inode, dentry);
+                rc = smfs_dotsnap_lookup(inode, dentry, snap_info);
                 if (rc == 0)
                         rc = 1;
                 RETURN(rc);                
@@ -888,23 +1193,32 @@ int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1,
 
 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;
+        struct fsfilt_operations *sops = I2SNAPCOPS(inode); 
+        struct snap_info *snap_info = NULL;
+        struct snap_table *table = NULL;
         int slot;
 
-        ENTRY; 
+        ENTRY;
+        
+        snap_info = smfs_find_snap_info(inode);
+        if (!snap_info) {
+                CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+                RETURN(NULL);                
+        }
+        
+        table = snap_info->sni_table;        
+
         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);
+                cache_inode = sops->fs_get_indirect(I2CI(inode), NULL, index);
                                                                                                                                                                                                      
                 if (!cache_inode )  continue;
-                                                                                                                                                                                                     
+                
                 if (aops->bmap(cache_inode->i_mapping, block))
                        RETURN(cache_inode); 
                 iput(cache_inode);
index 1fe7f9a..56de8fc 100644 (file)
@@ -123,14 +123,13 @@ struct smfs_hook_ops *smfs_alloc_hook_ops(char *name,
                                           smfs_hook_func post_hook);
 
 void smfs_free_hook_ops(struct smfs_hook_ops *hops);
-int smfs_register_hook_ops(struct super_block *sb, 
+int smfs_register_hook_ops(struct smfs_super_info *smb, 
                            struct smfs_hook_ops *smh_ops);
 
-struct smfs_hook_ops *smfs_unregister_hook_ops(struct super_block *sb, 
+struct smfs_hook_ops *smfs_unregister_hook_ops(struct smfs_super_info *smb, 
                                                char *name);
 /*smfs_lib.c*/
 void smfs_put_super(struct super_block *sb);
-extern struct super_block *smfs_get_sb_by_path(char *path, int len);
 int smfs_fill_super(struct super_block *sb, void *data, int silent);
 /*sysctl.c*/
 extern int sm_debug_level;
@@ -161,6 +160,11 @@ struct inode *smfs_get_inode(struct super_block *sb, ino_t hash,
 
 extern struct super_operations smfs_super_ops;
 
+struct smfs_iget_args {
+        struct inode *s_inode;
+        int           s_index;
+        int           s_ino;
+};
 /*symlink.c*/
 extern struct inode_operations smfs_sym_iops;
 extern struct file_operations smfs_sym_fops;
@@ -178,19 +182,21 @@ extern int smfs_post_rec_setattr(struct inode *dir, struct dentry *dentry,
 extern int smfs_post_rec_create(struct inode *dir, struct dentry *dentry,
                                 void   *data1, void   *data2);
 /*kml.c*/
-extern int smfs_kml_init(struct super_block *sb);
-extern int smfs_do_rec(struct inode *inode);
-extern int smfs_rec_cleanup(struct super_block *sb);
-extern int smfs_rec_init(struct super_block *sb);
+int smfs_do_rec(struct inode *inode);
+int smfs_rec_cleanup(struct smfs_super_info *smfs_info);
+int smfs_rec_init(struct super_block *sb);
+
 extern int smfs_rec_unpack(struct smfs_proc_args *args, char *record,
                            char **pbuf, int *opcode);
 extern int smfs_process_rec(struct super_block *sb, int count,
                             char *dir, int flags);
 extern smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb);
 
-extern int ost_rec_pack_init(struct super_block *sb);
+
+/*mds_kml.c*/
+int mds_rec_pack_init(struct smfs_super_info *smsi);
 /*ost_kml.c*/
-extern int mds_rec_pack_init(struct super_block *sb);
+int ost_rec_pack_init(struct smfs_super_info *smsi);
 
 /*smfs_llog.c*/
 extern int smfs_llog_setup(struct super_block *sb, struct vfsmount *mnt);
@@ -224,10 +230,10 @@ extern int cache_space_post(int op, void *handle, struct inode *old_dir,
                             struct dentry *old_dentry, struct inode *new_dir,
                             struct dentry *new_dentry);
 
-extern int cache_space_hook_setup(struct super_block *);
-extern int cache_space_hook_cleanup(void);
-extern int cache_space_hook_init(struct super_block *);
-extern int cache_space_hook_exit(struct super_block *);
+int cache_space_hook_setup(struct super_block *);
+int cache_space_hook_cleanup(void);
+int cache_space_hook_init(struct super_block *sb);
+int cache_space_hook_exit(struct smfs_super_info *smfs_info);
 
 #define XATTR_SMFS_HOARD_MARK           "hoard"
 #define XATTR_SMFS_CACHE_LOGCOOKIE      "cache"
@@ -316,11 +322,21 @@ do {                                                                           \
                 GOTO(label, rc);                                               \
 } while(0)                                                                     \
 
+#define SMFS_GET_INODE(sb, cache_inode, dir, index, inode, rc, label)   \
+do {                                                                    \
+        LASSERT(cache_inode);                                           \
+        inode = smfs_get_inode(sb, cache_inode->i_ino, dir, index);     \
+        iput(cache_inode);                                              \
+        if (!inode)                                                     \
+                GOTO(label, rc = -ENOENT);                              \
+} while(0)        
+
+
 #if CONFIG_SNAPFS
-extern int smfs_cow_init(struct super_block *sb);
-extern int smfs_cow_cleanup(struct super_block *sb);
-extern int smfs_init_snap_inode_info(struct inode *inode, 
-                                     struct snap_inode_info *sn_info); 
+int smfs_cow_init(struct super_block *sb);
+int smfs_cow_cleanup(struct smfs_super_info *smb);
+int smfs_init_snap_inode_info(struct inode *inode, struct smfs_iget_args *args); 
+int smfs_snap_test_inode(struct inode *inode, void *args);
 #else
 #define SMFS_PRE_COW(dir, dentry, new_dir, new_dentry, op, name, rc, label)                 
 #endif 
index f9045d1..dc4809c 100644 (file)
 #include <linux/lustre_fsfilt.h>
 #include <linux/lustre_smfs.h>
 #include "smfs_internal.h"
-static char *smfs_options(char *data, char **devstr, char **namestr,
-                          int *kml, int *cache, char **opts, int *iopen_nopriv,
-                          int *cow)
+
+static char *smfs_options(char *data, char **devstr, char **namestr, 
+                          char *opts, int *flags)  
 {
-        char *pos;
         struct option *opt_value = NULL;
+        char   *pos;
+        int    opt_len = 0;
+        
+        LASSERT(opts && flags);
 
         while (!(get_opt(&opt_value, &pos))) {
                 if (!strcmp(opt_value->opt, "dev")) {
@@ -59,115 +62,84 @@ static char *smfs_options(char *data, char **devstr, char **namestr,
                         if (namestr != NULL)
                                 *namestr = opt_value->value;
                 } else if (!strcmp(opt_value->opt, "kml")) {
-                        if (kml)
-                                *kml = 1;
+                        *flags |= SM_DO_REC;
                 } else if (!strcmp(opt_value->opt, "cache")) {
-                        if (cache)
-                                *cache = 1;
-                } else if (!strcmp(opt_value->opt, "options")) {
-                        if (opts != NULL)
-                                *opts = opt_value->value;
-                } else if (!strcmp(opt_value->opt, "iopen_nopriv")) {
-                        if (iopen_nopriv != NULL)
-                                *iopen_nopriv = 1;
+                        *flags |= SM_CACHE_HOOK;
                 } else if (!strcmp(opt_value->opt, "snap")) {
-                                *cow = 1;
+                        *flags |= SM_DO_COW;
+                } else if (!strcmp(opt_value->opt, "options")) {
+                        if (strlen(opts) == 0)
+                                sprintf((char *)opts + strlen(opts), "%s",
+                                        opt_value->value);
+                        else  
+                                sprintf((char *)opts + strlen(opts), ",%s",
+                                        opt_value->value);
                 } else {
-                        break;
+                        /*FIXME:WANGDI How about the opt_value->value*/
+                        if (strlen(opts) == 0)
+                                sprintf((char *)opts + strlen(opts), "%s",
+                                        opt_value->opt);
+                        else  
+                                sprintf((char *)opts + strlen(opts), ",%s",
+                                        opt_value->opt);
                 }
         }
         return pos;
 }
-
-struct super_block *smfs_get_sb_by_path(char *path, int len)
+static struct smfs_super_info *smfs_init_smb(struct super_block *sb)
 {
-        struct super_block *sb;
-        struct nameidata nd;
-        int error = 0;
-
+        struct smfs_super_info *smb;
         ENTRY;
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-        if (path_init(path, LOOKUP_FOLLOW, &nd)) {
-#else
-        if (path_lookup(path, LOOKUP_FOLLOW, &nd)) {
-#endif
-                error = path_walk(path, &nd);
-                if (error) {
-                        path_release(&nd);
-                        RETURN(NULL);
-                }
-        } else {
-                RETURN(NULL);
-        }
-
-        /* FIXME-WANGDI: add some check code here. */
-        sb = nd.dentry->d_sb;
-        path_release(&nd);
-        RETURN(sb);
+        OBD_ALLOC(smb, sizeof(*smb));
+        if (!smb)
+                RETURN(NULL);        
+        
+        S2SMI(sb) = smb;
+        RETURN(smb);        
 }
-
-static int smfs_init_fsfilt_ops(struct super_block *sb)
+static int smfs_init_fsfilt_ops(struct smfs_super_info *smb)
 {
         ENTRY;
-        if (!S2SMI(sb)->sm_cache_fsfilt) {
-                S2SMI(sb)->sm_cache_fsfilt =
-                        fsfilt_get_ops(S2SMI(sb)->smsi_cache_ftype);
-                if (!S2SMI(sb)->sm_cache_fsfilt) {
+        if (!smb->sm_cache_fsfilt) {
+                smb->sm_cache_fsfilt = fsfilt_get_ops(smb->smsi_cache_ftype);
+                if (!smb->sm_cache_fsfilt) {
                         CERROR("Can not get %s fsfilt ops needed by kml\n",
-                               S2SMI(sb)->smsi_cache_ftype);
+                               smb->smsi_cache_ftype);
                         RETURN(-EINVAL);
                 }
         }
-        if (!S2SMI(sb)->sm_fsfilt) {
-                S2SMI(sb)->sm_fsfilt =
-                        fsfilt_get_ops(S2SMI(sb)->smsi_ftype);
-                if (!S2SMI(sb)->sm_fsfilt) {
+        if (!smb->sm_fsfilt) {
+                smb->sm_fsfilt = fsfilt_get_ops(smb->smsi_ftype);
+                if (!smb->sm_fsfilt) {
                         CERROR("Can not get %s fsfilt ops needed by kml\n",
-                               S2SMI(sb)->smsi_ftype);
+                               smb->smsi_ftype);
                         RETURN(-EINVAL);
                 }
         }
         RETURN(0);
 }
 
-void smfs_cleanup_fsfilt_ops(struct super_block *sb)
+void smfs_cleanup_fsfilt_ops(struct smfs_super_info *smb)
 {
-        if (S2SMI(sb)->sm_cache_fsfilt)
-                fsfilt_put_ops(S2SMI(sb)->sm_cache_fsfilt);
-        if (S2SMI(sb)->sm_fsfilt)
-                fsfilt_put_ops(S2SMI(sb)->sm_fsfilt);
+        if (smb->sm_cache_fsfilt)
+                fsfilt_put_ops(smb->sm_cache_fsfilt);
+        if (smb->sm_fsfilt)
+                fsfilt_put_ops(smb->sm_fsfilt);
 }
 
-static int sm_mount_cache(struct super_block *sb, char *devstr,
-                          char *typestr, char *opts, int iopen_nopriv)
+static int smfs_mount_cache(struct smfs_super_info *smb, char *devstr, 
+                            char *typestr, char *opts)
 {
-        struct smfs_super_info *smb = S2SMI(sb);
         int err = 0, typelen;
         struct vfsmount *mnt;
-        unsigned long page;
         ENTRY;
 
         typelen = strlen(typestr);
 
-        page = __get_free_page(GFP_KERNEL);
-        if (!page)
-                GOTO(err_out, err = -ENOMEM);
-
-        memset((void *)page, 0, PAGE_SIZE);
-
-        if (iopen_nopriv)
-                sprintf((char *)page, "iopen_nopriv");
-
-        if (opts && strlen(opts)) {
-                int n = strlen((char *)page);
-                sprintf((char *)page + n, ",%s", opts);
-        }
-
         printk("smfs: mounting %s at %s\n", typestr, devstr);
 
-        mnt = do_kern_mount(typestr, 0, devstr, (void *)page);
-        free_page(page);
+        mnt = do_kern_mount(typestr, 0, devstr, (void *)opts);
 
         if (IS_ERR(mnt)) {
                 CERROR("do_kern_mount failed: rc = %ld\n", PTR_ERR(mnt));
@@ -184,24 +156,19 @@ static int sm_mount_cache(struct super_block *sb, char *devstr,
 
         OBD_ALLOC(smb->smsi_ftype, strlen(SMFS_TYPE) + 1);
         memcpy(smb->smsi_ftype, SMFS_TYPE, strlen(SMFS_TYPE));
-
-        duplicate_sb(sb, mnt->mnt_sb);
-        sm_set_sb_ops(mnt->mnt_sb, sb);
-
-        err = smfs_init_fsfilt_ops(sb);
+        
+        err = smfs_init_fsfilt_ops(smb);
 err_out:
-        return err;
+        RETURN(err);
 }
 
-static int sm_umount_cache(struct super_block *sb)
+static int smfs_umount_cache(struct smfs_super_info *smb)
 {
-        struct smfs_super_info *smb = S2SMI(sb);
-
-        iput(S2CSB(sb)->s_root->d_inode);
-        dput(S2CSB(sb)->s_root);
+        iput(smb->smsi_sb->s_root->d_inode);
+        dput(smb->smsi_sb->s_root);
         mntput(smb->smsi_mnt);
         smfs_cleanup_sm_ops(smb);
-        smfs_cleanup_fsfilt_ops(sb);
+        smfs_cleanup_fsfilt_ops(smb);
 
         if (smb->smsi_cache_ftype)
                 OBD_FREE(smb->smsi_cache_ftype,
@@ -212,18 +179,16 @@ static int sm_umount_cache(struct super_block *sb)
         return 0;
 }
 
-static int smfs_init_hook_ops(struct super_block *sb)
+static int smfs_init_hook_ops(struct smfs_super_info *smb)
 {
-        struct smfs_super_info *smb = S2SMI(sb);
         ENTRY;
 
         INIT_LIST_HEAD(&smb->smsi_hook_list);
 
         RETURN(0); 
 }
-static void smfs_cleanup_hook_ops(struct super_block *sb)
+static void smfs_cleanup_hook_ops(struct smfs_super_info *smb)
 {
-        struct smfs_super_info *smb = S2SMI(sb);
         struct list_head *hlist = &smb->smsi_hook_list;
         ENTRY;
 
@@ -234,77 +199,123 @@ static void smfs_cleanup_hook_ops(struct super_block *sb)
                                        smh_list);
                 CERROR("Unregister %s hook ops\n", smfs_hops->smh_name);         
                 
-                smfs_unregister_hook_ops(sb, smfs_hops->smh_name);
+                smfs_unregister_hook_ops(smb, smfs_hops->smh_name);
                 smfs_free_hook_ops(smfs_hops); 
         } 
         EXIT;
         return;        
 }
 
-void smfs_put_super(struct super_block *sb)
+static void smfs_cleanup_smb(struct super_block *sb)
 {
-        if (SMFS_CACHE_HOOK(S2SMI(sb)))
-                cache_space_hook_exit(sb);
-        if (SMFS_DO_REC(S2SMI(sb)))
-                smfs_rec_cleanup(sb);
+        struct smfs_super_info *smb;
+        ENTRY;
+
+        smb = S2SMI(sb);
+        if (smb) 
+                OBD_FREE(smb, sizeof(*smb));
+        EXIT;
+        return;
+}
+static void smfs_cleanup_hooks(struct smfs_super_info *smb)
+{
+        
+        if (SMFS_CACHE_HOOK(smb))
+                cache_space_hook_exit(smb);
+        if (SMFS_DO_REC(smb))
+                smfs_rec_cleanup(smb);
 #if CONFIG_SNAPFS
-        if (SMFS_DO_COW(S2SMI(sb)))
-                smfs_cow_cleanup(sb);
+        if (SMFS_DO_COW(smb))
+                smfs_cow_cleanup(smb);
 #endif  
-        smfs_cleanup_hook_ops(sb);
+}
+
+void smfs_put_super(struct super_block *sb)
+{
+        struct smfs_super_info *smfs_info = S2SMI(sb);
+
+        smfs_cleanup_hooks(smfs_info);
+        
+        smfs_cleanup_hook_ops(smfs_info);
         if (sb)
-                sm_umount_cache(sb);
+                smfs_umount_cache(smfs_info);
+        smfs_cleanup_smb(sb); 
         return;
 }
+
+static int smfs_init_hooks(struct super_block *sb)
+{ 
+        ENTRY;
+        if (SMFS_DO_REC(S2SMI(sb))) 
+                smfs_rec_init(sb);
+        if (SMFS_CACHE_HOOK(S2SMI(sb))) 
+                cache_space_hook_init(sb);
+#if CONFIG_SNAPFS
+        if (SMFS_DO_COW(S2SMI(sb))) 
+                smfs_cow_init(sb);
+#endif
+        RETURN(0);
+}
+
 int smfs_fill_super(struct super_block *sb, void *data, int silent)
 {
-        ino_t root_ino;
-        char *cache_data;
-
-        int iopen_nopriv = 0;
         struct inode *root_inode = NULL;
-        int err = 0, do_rec = 0, cache_hook = 0, do_cow = 0;
-        char *devstr = NULL, *typestr = NULL, *opts = NULL;
+        struct smfs_super_info *smb = NULL;
+        char *devstr = NULL, *typestr = NULL; 
+        char *opts = NULL, *cache_data = NULL;
+        unsigned long page;
+        int err = 0; 
+        ino_t root_ino;
 
         ENTRY;
 
-        CDEBUG(D_SUPER, "mount opts: %s\n", data ?
-               (char *)data : "(none)");
-
-        init_option(data);
+        CDEBUG(D_SUPER, "mount opts: %s\n", data ?  (char *)data : "(none)");
 
-        /* read and validate passed options. */
-        cache_data = smfs_options(data, &devstr, &typestr,
-                                  &do_rec, &cache_hook, &opts,
-                                  &iopen_nopriv, &do_cow);
+        smb = smfs_init_smb(sb);
+        if (!smb)
+                RETURN(-ENOMEM);
+        page = __get_free_page(GFP_KERNEL);
+        if (!page)
+                GOTO(out_err, err = -ENOMEM);
+                                                                                                                                                                                                     
+        memset((void *)page, 0, PAGE_SIZE);
+        opts = (char *)page;
 
+        init_option(data);
+        cache_data = smfs_options(data, &devstr, &typestr, opts, 
+                                  &smb->smsi_flags); 
         if (*cache_data)
                 CWARN("smfs_fill_super(): options parsing stoped at "
                       "option %s\n", cache_data);
 
         if (!typestr || !devstr) {
                 CERROR("mount options name and dev mandatory\n");
+                free_page(page);
                 GOTO(out_err, err = -EINVAL);
         }
-        err = sm_mount_cache(sb, devstr, typestr, opts, iopen_nopriv);
+        err = smfs_mount_cache(smb, devstr, typestr, opts);
+        
+        free_page(page);
+        
         if (err) {
                 CERROR("Can not mount %s as %s\n", devstr, typestr);
                 GOTO(out_err, 0);
         }
-        
-        err = smfs_init_hook_ops(sb);
+
+        duplicate_sb(sb, smb->smsi_sb);
+        sm_set_sb_ops(smb->smsi_sb, sb);
+
+        err = smfs_init_hook_ops(smb);
         if (err) {
                 CERROR("Can not init super hook ops err %d\n", err);
                 GOTO(out_err, 0);
         }
-        
-        if (do_rec) smfs_rec_init(sb);
-        if (cache_hook) cache_space_hook_init(sb);
-        
+        /*init the root_inode of smfs*/ 
         dget(S2CSB(sb)->s_root);
         root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
-        root_inode = iget(sb, root_ino);
+        root_inode = smfs_get_inode(sb, root_ino, NULL, 0);
 
         CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
                sb->s_op->read_inode, root_ino, root_inode);
@@ -312,13 +323,15 @@ int smfs_fill_super(struct super_block *sb, void *data, int silent)
         sb->s_root = d_alloc_root(root_inode);
 
         if (!sb->s_root) {
-                sm_umount_cache(sb);
+                smfs_umount_cache(smb);
                 GOTO(out_err, err=-EINVAL);
         }
-#if CONFIG_SNAPFS
-        if (do_cow) smfs_cow_init(sb);
-#endif
-
+        
+        err = smfs_init_hooks(sb);  
+        if (err) {
+                smfs_umount_cache(smb);
+                GOTO(out_err, err=-EINVAL);        
+        }       
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
         CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
                (ulong)sb, (ulong)&sb->u.generic_sbp);
@@ -326,13 +339,14 @@ int smfs_fill_super(struct super_block *sb, void *data, int silent)
         CDEBUG(D_SUPER, "sb %lx, &sb->s_fs_info: %lx\n",
                (ulong)sb, (ulong)&sb->s_fs_info);
 #endif
-
 out_err:
         cleanup_option();
+        if (err)
+                smfs_cleanup_smb(sb);
         return err;
 }
 struct smfs_hook_ops *smfs_alloc_hook_ops(char *name, smfs_hook_func pre_hook, 
-                                       smfs_hook_func post_hook)
+                                          smfs_hook_func post_hook)
 {
         struct smfs_hook_ops *smfs_hops = NULL;
         
@@ -367,10 +381,9 @@ void smfs_free_hook_ops(struct smfs_hook_ops *hops)
         }
 }
 
-int smfs_register_hook_ops(struct super_block *sb, 
+int smfs_register_hook_ops(struct smfs_super_info *smb, 
                            struct smfs_hook_ops *smh_ops)
 {
-        struct smfs_super_info *smb = S2SMI(sb);
         struct list_head *hlist = &smb->smsi_hook_list;
         struct list_head *p;
         ENTRY;
@@ -386,10 +399,9 @@ int smfs_register_hook_ops(struct super_block *sb,
        list_add(&smh_ops->smh_list, hlist);
         RETURN(0);
 } 
-struct smfs_hook_ops  *smfs_unregister_hook_ops(struct super_block *sb, 
-                                                char *name)
+struct smfs_hook_ops *smfs_unregister_hook_ops(struct smfs_super_info *smb, 
+                                               char *name)
 {
-        struct smfs_super_info *smb = S2SMI(sb);
         struct list_head *hlist = &smb->smsi_hook_list;
         struct list_head *p;
         ENTRY;      
index dfbe801..1056bfc 100644 (file)
@@ -78,16 +78,6 @@ static struct file_system_type smfs_type = {
 };
 #endif
 
-static int init_smfs(void)
-{
-        int err;
-
-        err = register_filesystem(&smfs_type);
-        if (err)
-                CERROR("register_filesystem() failed, rc = %d\n", err);
-        return err;
-}
-
 static int cleanup_smfs(void)
 {
         int err = 0;
@@ -97,7 +87,15 @@ static int cleanup_smfs(void)
                 CERROR("unregister_filesystem() failed, rc = %d\n", err);
         return 0;
 }
-
+static int init_smfs(void)
+{
+        int err;
+        
+        err = register_filesystem(&smfs_type);
+        if (err)
+                CERROR("register_filesystem() failed, rc = %d\n", err);
+        return err;
+}
 static int __init smfs_init(void)
 {
         int err;
index 906fefe..95421d2 100644 (file)
@@ -245,7 +245,8 @@ command_t cmdlist[] = {
         {"cache_off", jt_obd_cache_off, 0,
          "usage: lsync\n"},  
         /*snap operations*/
-        {"snap_add", jt_obd_snap_add, 0, "usage: snap_add <snap_name>\n"}, 
+        {"snap_add", jt_obd_snap_add, 0, 
+         "usage: snap_add <dev_name> <snap_name>\n"}, 
         /* Llog operations */ 
         {"llog_catlist", jt_llog_catlist, 0, 
          "list all catalog logs on current device.\n"
index 903fb61..6ba7578 100644 (file)
@@ -2099,17 +2099,25 @@ int jt_obd_snap_add(int argc, char **argv)
         struct obd_ioctl_data data;
         int rc = 0;
       
-        if (argc != 2)
-               return CMD_HELP; 
+        if (argc != 3)
+               return CMD_HELP;
+
+        SHMEM_SETUP();
+        register_ioc_dev(SMFS_DEV_ID, SMFS_DEV_PATH);
+        
         IOC_INIT(data);
         
         data.ioc_inllen1 = strlen(argv[1]) + 1;
         data.ioc_inlbuf1 = argv[1];
+        data.ioc_inllen2 = strlen(argv[2]) + 2;
+        data.ioc_inlbuf2 = argv[2];
 
         IOC_PACK(argv[0], data);
        
-        rc = l_ioctl(OBD_DEV_ID, OBD_IOC_SNAP_ADD, buf);
+        rc = l_ioctl(SMFS_DEV_ID, OBD_IOC_SMFS_SNAP_ADD, buf);
         
+        unregister_ioc_dev(SMFS_DEV_ID);       
         if (rc)
                 fprintf(stderr, "OBD_IOC_SNAP_ADD failed: rc=%d\n", rc);
         return rc;