Whamcloud - gitweb
port snapfs to 2.4
authorwangdi <wangdi>
Sun, 4 Jan 2004 07:24:39 +0000 (07:24 +0000)
committerwangdi <wangdi>
Sun, 4 Jan 2004 07:24:39 +0000 (07:24 +0000)
15 files changed:
lustre/snapfs/cache.c
lustre/snapfs/clonefs.c
lustre/snapfs/dcache.c
lustre/snapfs/dir.c
lustre/snapfs/dotsnap.c
lustre/snapfs/file.c
lustre/snapfs/filter.c
lustre/snapfs/inode.c
lustre/snapfs/journal_ext3.c
lustre/snapfs/psdev.c
lustre/snapfs/snap.c
lustre/snapfs/snaptable.c
lustre/snapfs/super.c
lustre/snapfs/symlink.c
lustre/snapfs/sysctl.c

index d0c8f1b..bb1ed30 100644 (file)
@@ -1,56 +1,35 @@
-/*
- *
- *
- *  Copyright (C) 2000 Stelias Computing, Inc.
- *  Copyright (C) 2000 Red Hat, Inc.
- *
- *
+/*  
+ *  snapfs/cache.c
  */
 
+#define DEBUG_SUBSYSTEM S_SNAP
 
-#include <stdarg.h>
-
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/blkdev.h>
-#include <linux/init.h>
-#define __NO_VERSION__
-#include <linux/module.h>
-
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
-
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+#include <portals/list.h>
+#include "snapfs_internal.h" 
 /*
  * XXX - Not sure for snapfs that the cache functions are even needed.
  * Can't all lookups be done by an inode->superblock->u.generic_sbp
  * lookup?
  */
 
-/*
-   This file contains the routines associated with managing a
-   cache of files .  These caches need to be found
-   fast so they are hashed by the device, with an attempt to have
-   collision chains of length 1.
-*/
+extern struct snap_table snap_tables[SNAP_MAX_TABLES];
 
 /* the intent of this hash is to have collision chains of length 1 */
 #define CACHES_BITS 8
 #define CACHES_SIZE (1 << CACHES_BITS)
 #define CACHES_MASK CACHES_SIZE - 1
+
 static struct list_head snap_caches[CACHES_SIZE];
 
+
 static inline int snap_cache_hash(kdev_t dev)
 {
        return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8));
@@ -78,68 +57,39 @@ struct snap_cache *snap_find_cache(kdev_t dev)
        struct list_head *lh, *tmp;
 
        lh = tmp = &(snap_caches[snap_cache_hash(dev)]);
-       while ( (tmp = lh->next) != lh ) {
-               cache = list_entry(tmp, struct snap_cache, cache_chain);
+        list_for_each_entry(cache, lh, cache_chain) { 
                if ( cache->cache_dev == dev )
                        return cache;
        }
        return NULL;
 }
 
-
-/* map an inode to a cache */
-struct snap_cache *snap_get_cache(struct inode *inode)
-{
-       struct snap_cache *cache;
-
-       /* find the correct snap_cache here, based on the device */
-       cache = snap_find_cache(inode->i_dev);
-       if ( !cache ) {
-               printk("WARNING: no  cache for dev %d, ino %ld\n",
-                      inode->i_dev, inode->i_ino);
-               return NULL;
-       }
-
-       return cache;
-}
-
-
-/* another debugging routine: check fs is InterMezzo fs */
-int snap_ispresto(struct inode *inode)
-{
-       struct snap_cache *cache;
-
-       if ( !inode )
-               return 0;
-       cache = snap_get_cache(inode);
-       if ( !cache )
-               return 0;
-       return (inode->i_dev == cache->cache_dev);
-}
-
 /* setup a cache structure when we need one */
 struct snap_cache *snap_init_cache(void)
 {
        struct snap_cache *cache;
 
        /* make a snap_cache structure for the hash */
-       SNAP_ALLOC(cache, struct snap_cache *, sizeof(struct snap_cache));
+       SNAP_ALLOC(cache,  sizeof(struct snap_cache));
        if ( cache ) {
-               memset(cache, 0, sizeof(struct snap_cache));
+               int i;
+                
+                memset(cache, 0, sizeof(struct snap_cache));
                INIT_LIST_HEAD(&cache->cache_chain);
                INIT_LIST_HEAD(&cache->cache_clone_list);
-       }
+                               
+                for (i = 0; i < SNAP_MAX_TABLES; i++) {
+                        init_MUTEX(&snap_tables[i].tbl_sema); 
+                }
+        }
        return cache;
 }
 
-
 /* free a cache structure and all of the memory it is pointing to */
 inline void snap_free_cache(struct snap_cache *cache)
 {
        if (!cache)
                return;
-
-
        SNAP_FREE(cache, sizeof(struct snap_cache));
 }
 
index 1ef8078..708b083 100644 (file)
  * 
  */
 
-#define __NO_VERSION__
+#define DEBUG_SUBSYSTEM S_SNAP
+
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
 #include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+#include "snapfs_internal.h" 
 
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
-#include <linux/string.h>
-#include <asm/uaccess.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <asm/segment.h>
-
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
 /* Clone is a simple file system, read only that just follows redirectors
    we have placed the entire implementation except clone_read_super in
    this file 
  */
 
-struct inode_operations clonefs_dir_inode_operations;
-struct inode_operations clonefs_file_inode_operations;
-struct inode_operations clonefs_symlink_inode_operations;
-struct inode_operations clonefs_special_inode_operations;
-struct file_operations clonefs_dir_file_operations;
-struct file_operations clonefs_file_file_operations;
-struct file_operations clonefs_special_file_operations;
+struct inode_operations clonefs_dir_inode_ops;
+struct inode_operations clonefs_file_inode_ops;
+struct inode_operations clonefs_symlink_inode_ops;
+//struct inode_operations clonefs_special_inode_operations;
+struct file_operations clonefs_dir_file_ops;
+struct file_operations clonefs_file_file_ops;
+//struct file_operations clonefs_special_file_operations;
+struct address_space_operations clonefs_file_address_ops;
 
 /* support routines for following redirectors */
 
@@ -82,14 +70,14 @@ struct inode *clonefs_get_inode(struct inode *inode)
        redirected_inode = snap_redirect(cache_inode, inode->i_sb);
 
        CDEBUG(D_SNAP, "redirected_inode: %lx, cache_inode %lx\n",
-              (ulong) redirected_inode, (ulong) cache_inode);
+              (unsigned long) redirected_inode, (unsigned long) cache_inode);
 
        CDEBUG(D_SNAP, "cache_inode: %lx, ino %ld, sb %lx, count %d\n",
-              (ulong) cache_inode, cache_inode->i_ino, 
-              (ulong) cache_inode->i_sb, cache_inode->i_count);
-
+              (unsigned long) cache_inode, cache_inode->i_ino, 
+              (unsigned long) cache_inode->i_sb, atomic_read(&cache_inode->i_count));
+       
        iput(cache_inode); 
-       EXIT;
+       
        return redirected_inode;
 }
 
@@ -102,39 +90,43 @@ static void clonefs_read_inode(struct inode *inode)
        ENTRY;
 
        CDEBUG(D_SNAP, "inode: %lx, ino %ld, sb %lx, count %d\n",
-              (ulong) inode , inode->i_ino, (long) inode->i_sb, 
-              inode->i_count);
+              (unsigned long)inode, inode->i_ino, (long) inode->i_sb, 
+              atomic_read(&inode->i_count));
 
        /* redirecting inode in the cache */
         cache_inode = clonefs_get_inode(inode);
        if (!cache_inode) {
                make_bad_inode(inode);
-               EXIT;
                return;
        }
        /* copy attrs of that inode to our clone inode */
        snapfs_cpy_attrs(inode, cache_inode);
 
-       if (S_ISREG(inode->i_mode))
-               inode->i_op = &clonefs_file_inode_operations;
-       else if (S_ISDIR(inode->i_mode))
-               inode->i_op = &clonefs_dir_inode_operations;
-       else if (S_ISLNK(inode->i_mode))
-               inode->i_op = &clonefs_symlink_inode_operations;
-       else if (S_ISCHR(inode->i_mode))
-               inode->i_op = &chrdev_inode_operations;
-       else if (S_ISBLK(inode->i_mode))
-               inode->i_op = &blkdev_inode_operations;
-       else if (S_ISFIFO(inode->i_mode))
-               init_fifo(inode);
-
+       if (S_ISREG(inode->i_mode)) {
+               inode->i_op = &clonefs_file_inode_ops;
+               if (inode->i_mapping)
+                       inode->i_mapping->a_ops = &clonefs_file_address_ops;
+       } else if (S_ISDIR(inode->i_mode)) {
+               inode->i_op = &clonefs_dir_inode_ops;
+       } else if (S_ISLNK(inode->i_mode)) {
+               inode->i_op = &clonefs_symlink_inode_ops;
+       } else {
+       /* init special inode 
+        * FIXME whether we should replace special inode ops*/
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+                init_special_inode(inode, inode->i_mode,
+                                   kdev_t_to_nr(inode->i_rdev));
+#else
+                init_special_inode(inode, inode->i_mode, inode->i_rdev);
+#endif
+       }
        iput(cache_inode);
 
        CDEBUG(D_SNAP, "cache_inode: %lx ino %ld, sb %lx, count %d\n",
-                (ulong) cache_inode, cache_inode->i_ino, 
-              (ulong) cache_inode->i_sb, cache_inode->i_count);
-       EXIT;
-       return
+               (unsigned long) cache_inode, cache_inode->i_ino, 
+              (unsigned long) cache_inode->i_sb, 
+              atomic_read(&cache_inode->i_count));
+       EXIT
 }
 
 
@@ -144,18 +136,15 @@ static void clonefs_put_super(struct super_block *sb)
 
        ENTRY;
        CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
-                (ulong) sb, (ulong) &sb->u.generic_sbp);
+                (unsigned long) sb, (unsigned long) &sb->u.generic_sbp);
        clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
-       dput( clone_sb->clone_cache->cache_sb->s_root );
+       dput(clone_sb->clone_cache->cache_sb->s_root);
        list_del(&clone_sb->clone_list_entry);
 
-       MOD_DEC_USE_COUNT;
-
        EXIT;
 }
 
-static int clonefs_statfs(struct super_block *sb, struct statfs *buf, 
-                       int bufsiz)
+static int clonefs_statfs(struct super_block *sb, struct statfs *buf) 
 {
        struct snap_clone_info *clone_sb;
        struct snap_cache *cache; 
@@ -165,26 +154,19 @@ static int clonefs_statfs(struct super_block *sb, struct statfs *buf,
 
        cache = clone_sb->clone_cache;
        if (!cache) {
-               printk("clone_statfs: no cache\n");
-               return -EINVAL;
+               CERROR("clone_statfs: no cache\n");
+               RETURN(-EINVAL);
        }
 
-       EXIT;
        return cache->cache_filter->o_caops.cache_sops->statfs
-               (cache->cache_sb, buf, bufsiz);
+               (cache->cache_sb, buf);
 }
 
 struct super_operations clone_super_ops =
 {
-       clonefs_read_inode,       /* read_inode */
-       NULL,                   /* write_inode */
-       NULL,                   /* put_inode */
-       NULL,                   /* delete_inode */
-       NULL,                   /* notify_change */
-       clonefs_put_super,      /* put_super */
-       NULL,                   /* write_super */
-       clonefs_statfs,         /* statfs */
-       NULL                    /* remount_fs */
+       read_inode:     clonefs_read_inode,     /* read_inode */
+       put_super:      clonefs_put_super,      /* put_super */
+       statfs:         clonefs_statfs,         /* statfs */
 };
 
 
@@ -220,8 +202,7 @@ struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
        cache_dentry = d_alloc(dentry->d_parent, &dentry->d_name);
        if (!cache_dentry) {
                 iput(cache_dir);
-               EXIT;
-               return ERR_PTR(-ENOENT);
+               RETURN(ERR_PTR(-ENOENT));
        }
 
         /* Lock cache directory inode. */
@@ -239,8 +220,7 @@ struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
                up(&cache_dir->i_sem);
                 iput(cache_dir);
                dentry->d_inode = NULL;
-               EXIT;
-               return ERR_PTR(-ENOENT);
+               RETURN(ERR_PTR(-ENOENT));
        }
         /* Unlock cache directory inode. */
        up(&cache_dir->i_sem);
@@ -268,8 +248,8 @@ struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
 
        if ( cache_inode != NULL ) {
                CDEBUG(D_INODE, "cache ino %ld, count %d, dir %ld, count %d\n", 
-                               cache_inode->i_ino, cache_inode->i_count, cache_dir->i_ino
-                               cache_dir->i_count);
+                      cache_inode->i_ino, atomic_read(&cache_inode->i_count)
+                      cache_dir->i_ino, atomic_read(&cache_dir->i_count));
        }
 
        d_unalloc(cache_dentry);
@@ -280,8 +260,7 @@ struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
          */
        d_add(dentry, inode);
 
-       EXIT;
-        return NULL;
+        RETURN(NULL);
 }
 
 
@@ -293,16 +272,17 @@ static void clonefs_prepare_snapfile(struct inode *i,
                                     struct dentry *cache_dentry)
 {
        ENTRY;
-        cache_file->f_pos = clone_file->f_pos;
+        
+       cache_file->f_pos = clone_file->f_pos;
         cache_file->f_mode = clone_file->f_mode;
         cache_file->f_flags = clone_file->f_flags;
         cache_file->f_count  = clone_file->f_count;
         cache_file->f_owner  = clone_file->f_owner;
-       cache_file->f_op = cache_inode->i_op->default_file_ops;
+       cache_file->f_op = cache_inode->i_fop;
        cache_file->f_dentry = cache_dentry;
         cache_file->f_dentry->d_inode = cache_inode;
+       
        EXIT;
-        return ;
 }
 
 /* update the clonefs file struct after IO in cache file */
@@ -312,10 +292,11 @@ static void clonefs_restore_snapfile(struct inode *cache_inode,
                                   struct file *clone_file)
 {
        ENTRY;
-        cache_file->f_pos = clone_file->f_pos;
+       cache_file->f_pos = clone_file->f_pos;
        cache_inode->i_size = clone_inode->i_size;
+       
        EXIT;
-        return;
 }
 
 static int clonefs_readdir(struct file *file, void *dirent, 
@@ -330,15 +311,13 @@ static int clonefs_readdir(struct file *file, void *dirent,
        ENTRY;
 
        if(!inode) {
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
         cache_inode = clonefs_get_inode(inode);
 
        if (!cache_inode) {
                make_bad_inode(inode);
-               EXIT;
-               return -ENOMEM;
+               RETURN(-ENOMEM);
        }
 
        CDEBUG(D_INODE,"clone ino %ld\n",cache_inode->i_ino);
@@ -354,56 +333,22 @@ static int clonefs_readdir(struct file *file, void *dirent,
        }
        clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
        iput(cache_inode);
-        EXIT;
-       return result;
+       RETURN(result);
 }
 
-struct file_operations clonefs_dir_file_operations = {
-        NULL,                   /* lseek */
-        NULL,                   /* read -- bad */
-        NULL,                   /* write */
-        clonefs_readdir,        /* readdir */
-        NULL,                   /* select */
-        NULL,                   /* ioctl */
-        NULL,                   /* mmap */
-        NULL,                   /* open */
-       NULL,
-        NULL,                   /* release */
-       NULL,                   /* fsync */
-        NULL,                   
-       NULL,
-       NULL
+struct file_operations clonefs_dir_file_ops = {
+       readdir:        clonefs_readdir,        /* readdir */
 };
 
-struct inode_operations clonefs_dir_inode_operations =
-{
-       &clonefs_dir_file_operations,
-       NULL,           /* create */
-       clonefs_lookup,   /* lookup */
-       NULL,           /* link */
-       NULL,           /* unlink */
-       NULL,           /* symlink */
-       NULL,           /* mkdir */
-       NULL,           /* rmdir */
-       NULL,           /* mknod */
-       NULL,           /* rename */
-       NULL,           /* readlink */
-       NULL,           /* follow_link */
-       NULL,           /* readpage */
-       NULL,           /* writepage */
-       NULL,           /* bmap */
-       NULL,           /* truncate */
-       NULL,           /* permission */
-       NULL,           /* smap */
-       NULL,           /* update page */
-        NULL,           /* revalidate */
+struct inode_operations clonefs_dir_inode_ops = {
+       lookup:         clonefs_lookup,   /* lookup */
 };
 
 
 /* ***************** end of clonefs dir ops *******************  */ 
 /* ***************** begin clonefs file ops *******************  */ 
 
-int clonefs_readpage(struct file *file, struct page *page)
+static int clonefs_readpage(struct file *file, struct page *page)
 {
        int result = 0;
        struct inode *cache_inode;
@@ -417,8 +362,7 @@ int clonefs_readpage(struct file *file, struct page *page)
         cache_inode = clonefs_get_inode(file->f_dentry->d_inode); 
        if (!cache_inode) {
                make_bad_inode(file->f_dentry->d_inode);
-               EXIT;
-               return -ENOMEM;
+               RETURN(-ENOMEM);
        }
 
        clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
@@ -429,65 +373,28 @@ int clonefs_readpage(struct file *file, struct page *page)
        /* potemkin case: we are handed a directory inode */
        down(&cache_inode->i_sem);
         /* XXX - readpage NULL on directories... */
-        if (cache_inode->i_op->readpage == NULL)
-                printk("Yes, Grigori, directories are a problem.\n");
-        else
-               cache_inode->i_op->readpage(&open_file, page);
+        result = cache_inode->i_mapping->a_ops->readpage(&open_file, page);
+
        up(&cache_inode->i_sem);
        clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
        iput(cache_inode);
-        EXIT;
-       return result;
+       RETURN(result);
 }
 
-
-struct file_operations clonefs_file_file_operations = {
-        NULL,                   /* lseek */
-        generic_file_read,      /* read -- bad */
-        NULL,                   /* write */
-        NULL,                   /* readdir */
-        NULL,                   /* select */
-        NULL,                   /* ioctl */
-        generic_file_mmap,      /* mmap */
-        NULL,                   /* open */
-       NULL,
-        NULL,                   /* release */
-       NULL,                   /* fsync */
-        NULL,                   
-       NULL,
-       NULL
+struct file_operations clonefs_file_file_ops = {
+       read:   generic_file_read,      /* read -- bad */
+       mmap:   generic_file_mmap,      /* mmap */
 };
 
-struct inode_operations clonefs_file_inode_operations =
-{
-       &clonefs_file_file_operations,
-       NULL,           /* create */
-       NULL,           /* lookup */
-       NULL,           /* link */
-       NULL,           /* unlink */
-       NULL,           /* symlink */
-       NULL,           /* mkdir */
-       NULL,           /* rmdir */
-       NULL,           /* mknod */
-       NULL,           /* rename */
-       NULL,           /* readlink */
-       NULL,           /* follow_link */
-       clonefs_readpage, /* readpage */
-       NULL,           /* writepage */
-       NULL,           /* bmap */
-       NULL,           /* truncate */
-       NULL,           /* permission */
-       NULL,           /* smap */
-       NULL,           /* update page */
-        NULL,           /* revalidate */
+struct address_space_operations clonefs_file_address_ops = {
+        readpage:       clonefs_readpage
 };
 
 
-
 /* ***************** end of clonefs file ops *******************  */ 
 /* ***************** begin clonefs symlink ops *******************  */ 
 
-int clonefs_readlink(struct dentry *dentry, char *buf, int len)
+static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 {
        int res;
        struct inode * cache_inode;
@@ -501,12 +408,11 @@ int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 
        if ( ! cache_inode ) {
                CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-               EXIT;
-               return res;     
+               RETURN(res);    
        }
        
        /* XXX: shall we allocate a new dentry ? 
-               The following is safe for ext2, etc. because ext2_readlink only
+               The following is safe for ext3, etc. because ext2_readlink only
                use the inode info */
 
        /* save the old dentry inode */ 
@@ -525,26 +431,21 @@ int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 
        iput(cache_inode);
 
-       EXIT;
-       return res;
+       RETURN(res);
 }
 
-struct dentry * clonefs_follow_link(struct dentry * dentry,
-                                        struct dentry *base,
-                                        unsigned int follow)
+static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
 {
-       struct dentry * res;
        struct inode * cache_inode;
        struct inode * old_inode;
+       int    res;
 
        ENTRY;
-       res = ERR_PTR(-ENOENT);
 
        cache_inode = clonefs_get_inode(dentry->d_inode); 
        if ( ! cache_inode ) {
                CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-               EXIT;
-               return res;     
+               RETURN(-ENOENT);        
        }
 
        /* XXX: shall we allocate a new dentry ? 
@@ -557,7 +458,7 @@ struct dentry * clonefs_follow_link(struct dentry * dentry,
        dentry->d_inode = cache_inode;
 
        if ( cache_inode->i_op->follow_link ) {
-               res = cache_inode->i_op->follow_link(dentry, base, follow); 
+               res = cache_inode->i_op->follow_link(dentry, nd); 
        }
 
        /* restore the old inode */
@@ -565,32 +466,16 @@ struct dentry * clonefs_follow_link(struct dentry * dentry,
 
        iput(cache_inode);
 
-       EXIT;
-       return res;
+       RETURN(res);
 }
 
-struct inode_operations clonefs_symlink_inode_operations =
+struct inode_operations clonefs_symlink_inode_ops =
 {
-       NULL,               /* no file operations */      
-       NULL,               /* create */                  
-       NULL,               /* lookup */                  
-       NULL,               /* link */                    
-       NULL,               /* unlink */                  
-       NULL,               /* symlink */                 
-       NULL,               /* mkdir */                   
-       NULL,               /* rmdir */                   
-       NULL,               /* mknod */                   
-       NULL,               /* rename */                  
-       clonefs_readlink,   /* readlink */              
-       clonefs_follow_link,/* follow_link */             
-       NULL,               /* readpage */                
-       NULL,               /* writepage */               
-       NULL,               /* bmap */                    
-       NULL,               /* truncate */                
-       NULL,               /* permission */              
-       NULL,               /* smap */                    
-       NULL,               /* update page */             
-        NULL,               /* revalidate */          
+       /*FIXME later getxattr, listxattr, 
+        * other method need to be replaced too 
+        * */  
+       readlink:       clonefs_readlink,   /* readlink */              
+       follow_link:    clonefs_follow_link,/* follow_link */             
 };
 
 
index 88ce4bb..cf4337d 100644 (file)
@@ -2,20 +2,20 @@
  * Directory operations for SnapFS filesystem
  */
 
-#include <linux/types.h>
+#define DEBUG_SUBSYSTEM S_SNAP
+
+#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
 #include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
 /* called when a cache lookup succeeds */
 
@@ -45,7 +45,7 @@ static int currentfs_dentry_revalidate(struct dentry *de, int flag)
                return 0;
        }
 #else 
-       return 1;
+       RETURN(1);
 #endif
 }
 
index 0b83fa1..a1636f2 100644 (file)
@@ -1,30 +1,19 @@
 /*
  * dir.c
  */
+#define DEBUG_SUBSYSTEM S_SNAP
 
-#define EXPORT_SYMTAB
-
-
-#define __NO_VERSION__
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
-
-#ifdef CONFIG_SNAPFS_EXT3
-void ext3_orphan_del(handle_t *handle, struct inode *inode);
-#endif
+#include "snapfs_internal.h" 
 
 static ino_t get_parent_ino(struct inode * inode)
 {
@@ -32,7 +21,7 @@ static ino_t get_parent_ino(struct inode * inode)
        struct dentry * dentry;
 
        if (list_empty(&inode->i_dentry)) {
-                       printk("snapfs ERROR: no dentry for ino %lu\n", inode->i_ino);
+                       CERROR("No dentry for ino %lu\n", inode->i_ino);
                 return 0;
         }
 
@@ -69,8 +58,7 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 
        cache = snap_find_cache(dir->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return ERR_PTR(-EINVAL);
+               RETURN(ERR_PTR(-EINVAL));
        }
 
        if ( dentry->d_name.len == strlen(".snap") &&
@@ -80,30 +68,27 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 
                /* Don't permit .snap in clonefs */
                if( dentry->d_sb != cache->cache_sb )
-                       return ERR_PTR(-ENOENT);
+                       RETURN(ERR_PTR(-ENOENT));
 
                /* Don't permit .snap under .snap */
                if( currentfs_is_under_dotsnap(dentry) )
-                       return ERR_PTR(-ENOENT);
+                       RETURN(ERR_PTR(-ENOENT));
 
                ino = 0xF0000000 | dir->i_ino;
                snap = iget(dir->i_sb, ino);
                CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n", snap->i_ino, snap->i_mode);
                d_add(dentry, snap);
-               EXIT;
-               return NULL;
+               RETURN(NULL);
        }
 
        iops = filter_c2cdiops(cache->cache_filter); 
        if (!iops || !iops->lookup) {
-               EXIT;
-               return ERR_PTR(-EINVAL);
+               RETURN(ERR_PTR(-EINVAL));
        }
 
        rc = iops->lookup(dir, dentry);
        if ( rc || !dentry->d_inode) {
-               EXIT;
-               return NULL;
+               RETURN(NULL);
        }
        
        /*
@@ -144,8 +129,7 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
                        dentry->d_fsdata = (void*)pri_ino;
        }
 
-       EXIT;
-       return NULL;
+       RETURN(NULL);
 
 #if 0
        /* XXX: PJB these need to be set up again. See dcache.c */
@@ -159,70 +143,71 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 
 err_out:
        d_unadd_iput(dentry);
-       EXIT;
-       return ERR_PTR(-EINVAL);
+       RETURN(ERR_PTR(-EINVAL));
 }
 
 static int currentfs_create(struct inode *dir, struct dentry *dentry, int mode)
 {
-       struct snap_cache *cache;
-       int rc;
+       struct snap_cache       *cache;
        struct inode_operations *iops;
-       void *handle = NULL;
+       struct snapshot_operations *snapops;    
+       void                    *handle = NULL;
+       int                     rc;
 
        ENTRY;
 
        if (currentfs_is_under_dotsnap(dentry)) {
-               EXIT;
-               return -EPERM;
+               RETURN(-EPERM);
        }
 
        cache = snap_find_cache(dir->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
 
+       snapops = filter_c2csnapops(cache->cache_filter);
+       if (!snapops || !snapops->get_generation) 
+               RETURN(-EINVAL);
+
        handle = snap_trans_start(cache, dir, SNAP_OP_CREATE);
 
        if ( snap_needs_cow(dir) != -1 ) {
-               printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+               CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 1);
-               snap_do_cow(dir, get_parent_ino(dir), 0);
+               if (!(snap_do_cow(dir, get_parent_ino(dir), 0))) {
+                       CERROR("Do cow error\n");
+                       RETURN(-EINVAL);
+               }
        }
 
        iops = filter_c2cdiops(cache->cache_filter); 
-       if (!iops ||
-           !iops->create) {
-               rc = -EINVAL;
-               goto exit;
+       if (!iops || !iops->create) {
+               RETURN(-EINVAL);
        }
        snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 2);
        rc = iops->create(dir, dentry, mode);
 
        /* XXX now set the correct snap_{file,dir,sym}_iops */
-        if ( ! dentry->d_inode) {
-                printk("Error in currentfs_create, dentry->d_inode is NULL\n");
-                goto exit;
+        if (!dentry->d_inode) {
+                CERROR("Error in currentfs_create, dentry->d_inode is NULL\n");
+                GOTO(exit, 0);
         }
 
-       if ( S_ISDIR(dentry->d_inode->i_mode) )
+       if (S_ISDIR(dentry->d_inode->i_mode))
                 dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
-        else if ( S_ISREG(dentry->d_inode->i_mode) ) {
-                if ( !filter_c2cfiops(cache->cache_filter) ) {
-                        filter_setup_file_ops(cache->cache_filter,
-                                dentry->d_inode->i_op, &currentfs_file_iops);
+        else if (S_ISREG(dentry->d_inode->i_mode)) {
+                if (!filter_c2cfiops(cache->cache_filter)) {
+                        filter_setup_file_ops(cache->cache_filter, dentry->d_inode,
+                                             &currentfs_file_iops, &currentfs_file_fops,
+                                             &currentfs_file_aops);
                 }
                 dentry->d_inode->i_op = filter_c2ufiops(cache->cache_filter);
         }
-       printk("inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
-
+       CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
        snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 3);
-       
-exit:
+       init_filter_data(dentry->d_inode, snapops, 0); exit:
        snap_trans_commit(cache, handle);
-       EXIT;
-       return rc;
+       RETURN(rc);
 }
 
 static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
@@ -235,27 +220,24 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        ENTRY;
 
        if (currentfs_is_under_dotsnap(dentry)) {
-               EXIT;
-               return -EPERM;
+               RETURN(-EPERM);
        }
 
        cache = snap_find_cache(dir->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
 
        handle = snap_trans_start(cache, dir, SNAP_OP_MKDIR);
 
        if ( snap_needs_cow(dir) != -1 ) {
-               CDEBUG(D_FILE, "snap_needs_cow for ino %lu \n",dir->i_ino);
+               CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 1);
                snap_do_cow(dir, get_parent_ino(dir), 0);
        }
 
        iops = filter_c2cdiops(cache->cache_filter); 
-       if (!iops ||
-           !iops->mkdir) {
+       if (!iops || !iops->mkdir) {
                rc = -EINVAL;
                goto exit;
        }
@@ -269,17 +251,16 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        /* XXX now set the correct snap_{file,dir,sym}_iops */
         if ( dentry->d_inode) {
                 dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
-               printk("inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
+               CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
         } else {
-                printk("Error in currentfs_mkdir, dentry->d_inode is NULL\n");
+                CERROR("Error in currentfs_mkdir, dentry->d_inode is NULL\n");
         }
 
        snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 3);
        
 exit:
        snap_trans_commit(cache, handle);
-       EXIT;
-       return rc;
+       RETURN(rc);
 }
 
 static int currentfs_link (struct dentry * old_dentry, struct inode * dir, 
@@ -292,44 +273,37 @@ static int currentfs_link (struct dentry * old_dentry, struct inode * dir,
 
        ENTRY;
 
-       if (currentfs_is_under_dotsnap(dentry)) {
-               EXIT;
-               return -EPERM;
-       }
+       if (currentfs_is_under_dotsnap(dentry)) 
+               RETURN(-EPERM);
 
        cache = snap_find_cache(dir->i_dev);
-       if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
-       }
+       if ( !cache )  
+               RETURN(-EINVAL);
 
        handle = snap_trans_start(cache, dir, SNAP_OP_LINK);
 
        if ( snap_needs_cow(dir) != -1 ) {
-               printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+               CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 1);
                snap_do_cow(dir, get_parent_ino(dir), 0);
        }
         if ( snap_needs_cow(old_dentry->d_inode) != -1 ) {
-               printk("snap_needs_cow for ino %lu \n",old_dentry->d_inode->i_ino);
+               CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",old_dentry->d_inode->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2);
                snap_do_cow(old_dentry->d_inode, dir->i_ino, 0);
        }
 
        iops = filter_c2cdiops(cache->cache_filter); 
-       if (!iops ||
-           !iops->link) {
-               rc = -EINVAL;
-               goto exit;
-       }
+
+       if (!iops || !iops->link) 
+               GOTO(exit, rc = -EINVAL);
+       
        snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2);
        rc = iops->link(old_dentry,dir, dentry);
        snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 3);
-       
 exit:
        snap_trans_commit(cache, handle);
-       EXIT;
-       return rc;
+       RETURN(rc);
 }
 
 static int currentfs_symlink(struct inode *dir, struct dentry *dentry, 
@@ -343,33 +317,28 @@ static int currentfs_symlink(struct inode *dir, struct dentry *dentry,
        ENTRY;
 
        cache = snap_find_cache(dir->i_dev);
-       if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
-       }
+       if (!cache)  
+               RETURN(-EINVAL);
 
        handle = snap_trans_start(cache, dir, SNAP_OP_SYMLINK);
 
        if ( snap_needs_cow(dir) != -1 ) {
-               printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+               CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 1);
                snap_do_cow(dir, get_parent_ino(dir), 0);
        }
 
        iops = filter_c2cdiops(cache->cache_filter); 
-       if (!iops ||
-           !iops->symlink) {
-               rc = -EINVAL;
-               goto exit;
-       }
+       if (!iops || !iops->symlink) 
+               GOTO(exit, rc = -EINVAL);
+
        snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 2);
        rc = iops->symlink(dir, dentry, symname);
        snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3);
        
 exit:
        snap_trans_commit(cache, handle);
-       EXIT;
-       return rc;
+       RETURN(rc);
 }
 
 static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode, 
@@ -383,30 +352,26 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
        ENTRY;
 
        if (currentfs_is_under_dotsnap(dentry)) {
-               EXIT;
-               return -EPERM;
+               RETURN(-EPERM);
        }
 
        cache = snap_find_cache(dir->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
 
        handle = snap_trans_start(cache, dir, SNAP_OP_MKNOD);
 
        if ( snap_needs_cow(dir) != -1 ) {
-               printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+               CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 1);
                snap_do_cow(dir, get_parent_ino(dir), 0);
        }
 
        iops = filter_c2cdiops(cache->cache_filter); 
-       if (!iops ||
-           !iops->mknod) {
-               rc = -EINVAL;
-               goto exit;
-       }
+       if (!iops || !iops->mknod) 
+               GOTO(exit, rc = -EINVAL);
+
        snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 2);
        rc = iops->mknod(dir, dentry, mode, rdev);
        snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 3);
@@ -415,8 +380,7 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 
 exit:
        snap_trans_commit(cache, handle);
-       EXIT;
-       return rc;
+       RETURN(rc);
 }
 
 static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
@@ -436,30 +400,25 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
        ENTRY;
 
        if (currentfs_is_under_dotsnap(dentry)) {
-               EXIT;
-               return -EPERM;
+               RETURN(-EPERM);
        }
 
        cache = snap_find_cache(dir->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
 
        handle = snap_trans_start(cache, dir, SNAP_OP_RMDIR);
 
        if ( snap_needs_cow(dir) != -1 ) {
-               printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+               CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 1);
                snap_do_cow(dir, get_parent_ino(dir), 0);
        }
 
        iops = filter_c2cdiops(cache->cache_filter); 
-       if (!iops ||
-           !iops->rmdir) {
-               rc = -EINVAL;
-               goto exit;
-       }
+       if (!iops || !iops->rmdir) 
+               GOTO(exit, rc = -EINVAL);
 
        /* XXX : there are two cases that we can't remove this inode from disk. 
                1. the inode needs to be cowed. 
@@ -468,17 +427,12 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
                will not be deleted after rmdir, will only remove dentry 
        */
 
-       if( snap_needs_cow(dentry->d_inode) != -1) {
+       if (snap_needs_cow(dentry->d_inode) != -1 || 
+           snap_is_redirector(dentry->d_inode)) {
                snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 2);
-               snap_do_cow (dentry->d_inode, dir->i_ino, 
-                               SNAP_DEL_PRI_WITHOUT_IND);
+               snap_do_cow (dir, get_parent_ino(dir), SNAP_CREATE_IND_DEL_PRI);
                keep_inode = 1;
        }
-       else if( snap_is_redirector(dentry->d_inode) ) {
-               snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 3);
-               snap_do_cow(dentry->d_inode, dir->i_ino, SNAP_DEL_PRI_WITH_IND);
-               keep_inode = 1;
-       }       
 #if 0
        if ( keep_inode ) {     
                        printk("set up dentry ops, before %p\n",dentry->d_op);
@@ -499,8 +453,7 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
        //      i_ctime = dentry->d_inode->i_ctime;
                i_nlink = dentry->d_inode->i_nlink;
                i_size = dentry->d_inode->i_size;
-       
-}
+       }
 
        snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 4);
        rc = iops->rmdir(dir, dentry);
@@ -534,7 +487,6 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
                        snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 6);
                }
        }
-
 exit:
        snap_trans_commit(cache, handle);
        EXIT;
@@ -552,27 +504,24 @@ static int currentfs_unlink(struct inode *dir, struct dentry *dentry)
        ENTRY;
 
        if (currentfs_is_under_dotsnap(dentry)) {
-               EXIT;
-               return -EPERM;
+               RETURN(-EPERM);
        }
 
        cache = snap_find_cache(dir->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
 
        handle = snap_trans_start(cache, dir, SNAP_OP_UNLINK);
 
        if ( snap_needs_cow(dir) != -1 ) {
-               printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+               CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 1);
                snap_do_cow(dir, get_parent_ino(dir), 0);
        }
 
        iops = filter_c2cdiops(cache->cache_filter); 
-       if (!iops ||
-           !iops->unlink) {
+       if (!iops || !iops->unlink) {
                rc = -EINVAL;
                goto exit;
        }
@@ -588,18 +537,17 @@ static int currentfs_unlink(struct inode *dir, struct dentry *dentry)
        if( snap_needs_cow (inode) != -1) {
                /* call snap_do_cow with DEL_WITHOUT_IND option */
                snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 2);
-               snap_do_cow(inode, dir->i_ino,SNAP_DEL_PRI_WITHOUT_IND);
+               snap_do_cow(inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI);
                if( inode->i_nlink == 1 )
                        inode->i_nlink++;
-       }
-       else if( snap_is_redirector (inode) && inode->i_nlink == 1 ) {
+       } else if (snap_is_redirector (inode) && inode->i_nlink == 1) {
                /* call snap_do_cow with DEL_WITH_IND option 
                 * just free the blocks of inode, not really delete it
                 */
                snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 3);
-               snap_do_cow (inode, dir->i_ino, SNAP_DEL_PRI_WITH_IND);
+               snap_do_cow (inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI);
                inode->i_nlink++;
-       }       
+       }
 
        snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 4);
        rc = iops->unlink(dir, dentry);
@@ -607,8 +555,7 @@ static int currentfs_unlink(struct inode *dir, struct dentry *dentry)
 
 exit:
        snap_trans_commit(cache, handle);
-       EXIT;
-       return rc;
+       RETURN(rc);
 }
 
 static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
@@ -623,26 +570,24 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
 
        if (currentfs_is_under_dotsnap(old_dentry) ||
            currentfs_is_under_dotsnap(new_dentry)) {
-               EXIT;
-               return -EPERM;
+               RETURN(-EPERM);
        }
 
        cache = snap_find_cache(old_dir->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
 
        handle = snap_trans_start(cache, old_dir, SNAP_OP_RENAME);
        
         /* Always cow the old dir and old dentry->d_inode */ 
        if ( snap_needs_cow(old_dir) != -1 ) {
-               printk("rename: needs_cow for old_dir %lu\n",old_dir->i_ino);
+               CDEBUG(D_INODE, "rename: needs_cow for old_dir %lu\n",old_dir->i_ino);
                snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 1);
                snap_do_cow(old_dir, get_parent_ino(old_dir), 0);
        }
        if( snap_needs_cow (old_dentry->d_inode) != -1) {
-               printk("rename: needs_cow for old_dentry, ino %lu\n",
+               CDEBUG(D_INODE, "rename: needs_cow for old_dentry, ino %lu\n",
                        old_dentry->d_inode->i_ino);
                snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 2);
                snap_do_cow(old_dentry->d_inode, old_dir->i_ino,0);
@@ -654,10 +599,10 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
          */
        if(( old_dir != new_dir) ) {
                if( snap_needs_cow(new_dir) !=-1 ){
-                       printk("rename:snap_needs_cow for new_dir %lu\n",
+                       CDEBUG(D_INODE, "rename:snap_needs_cow for new_dir %lu\n",
                                new_dir->i_ino);
                        snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,3);
-                       snap_do_cow(new_dir, get_parent_ino(new_dir),0);        
+                       snap_do_cow(new_dir, get_parent_ino(new_dir), 0);       
                }
        }
 
@@ -681,7 +626,7 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                        /* call snap_do_cow with DEL_WITHOUT_IND option */
                        snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4);
                        snap_do_cow(new_dentry->d_inode, new_dir->i_ino,
-                                    SNAP_DEL_PRI_WITHOUT_IND);
+                                    SNAP_CREATE_IND_DEL_PRI);
                        new_dentry->d_inode->i_nlink++;
                }
                else if( snap_is_redirector (new_dentry->d_inode) ) {
@@ -690,14 +635,13 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                         */
                        snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4);
                        snap_do_cow (new_dentry->d_inode, new_dir->i_ino, 
-                                     SNAP_DEL_PRI_WITH_IND);
+                                     SNAP_CREATE_IND_DEL_PRI);
                        new_dentry->d_inode->i_nlink++;
                }       
         }
 
        iops = filter_c2cdiops(cache->cache_filter); 
-       if (!iops ||
-           !iops->rename) {
+       if (!iops || !iops->rename) {
                rc = -EINVAL;
                goto exit;
        }
@@ -708,8 +652,7 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
 
 exit:
        snap_trans_commit(cache, handle);
-       EXIT;
-       return rc;
+       RETURN(rc);
 }
 
 static int currentfs_readdir(struct file *filp, void *dirent,
@@ -721,19 +664,16 @@ static int currentfs_readdir(struct file *filp, void *dirent,
        
        ENTRY;
        if( !filp || !filp->f_dentry || !filp->f_dentry->d_inode ) {
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
 
        cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
        fops = filter_c2cdfops( cache->cache_filter );
        if( !fops ) {
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
 
        /*
@@ -745,7 +685,7 @@ static int currentfs_readdir(struct file *filp, void *dirent,
                if( filp->f_pos == 0 ){
                        if( filldir(dirent, ".snap",
                                    strlen(".snap")+1, filp->f_pos,
-                                   0xF0000000|filp->f_dentry->d_inode->i_ino) ){
+                                   -1, 0) ){
                                return -EINVAL;
                        }
                        filp->f_pos += strlen(".snap")+1;
@@ -756,7 +696,7 @@ static int currentfs_readdir(struct file *filp, void *dirent,
        }else
                rc = fops->readdir(filp, dirent, filldir);
 
-       return rc;
+       RETURN(rc);
 }
 
 struct file_operations currentfs_dir_fops = {
@@ -764,14 +704,13 @@ struct file_operations currentfs_dir_fops = {
 };
 
 struct inode_operations currentfs_dir_iops = { 
-       default_file_ops: &currentfs_dir_fops,
-       create: currentfs_create,
-       mkdir: currentfs_mkdir,
-       link: currentfs_link,
-       symlink: currentfs_symlink,
-       mknod: currentfs_mknod,
-       rmdir: currentfs_rmdir,
-       unlink: currentfs_unlink,
-       rename: currentfs_rename,
-       lookup: currentfs_lookup
+       create:         currentfs_create,
+       mkdir:          currentfs_mkdir,
+       link:           currentfs_link,
+       symlink:        currentfs_symlink,
+       mknod:          currentfs_mknod,
+       rmdir:          currentfs_rmdir,
+       unlink:         currentfs_unlink,
+       rename:         currentfs_rename,
+       lookup:         currentfs_lookup
 };
index 19dfc1c..62c026d 100644 (file)
@@ -2,25 +2,19 @@
  * dotsnap.c - support for .snap directories
  */
 
-#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#define __NO_VERSION__
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include "snapfs_internal.h" 
 
 struct inode_operations dotsnap_inode_operations;
 struct file_operations dotsnap_file_operations;
@@ -38,8 +32,7 @@ int currentfs_is_under_dotsnap(struct dentry *de)
                de = de->d_parent;
        }
 
-       EXIT;
-       return 0;
+       RETURN(0);
 }
 
 void currentfs_dotsnap_read_inode(struct snap_cache *cache, 
@@ -76,41 +69,39 @@ struct dentry *dotsnap_lookup(struct inode *dir,  struct dentry *dentry)
 
        cache = snap_find_cache(dir->i_dev);
        if ( !cache ) {
-               printk("dotsnap_readdir: cannot find cache\n");
+               CERROR("dotsnap_readdir: cannot find cache\n");
                make_bad_inode(dir);
-               EXIT;
-               return ERR_PTR(-EINVAL);
+               RETURN(ERR_PTR(-EINVAL));
        }
 
        snapops = filter_c2csnapops(cache->cache_filter);
        if (!snapops || !snapops->get_indirect_ino) {
-                EXIT;
-                return ERR_PTR(-EINVAL);
+                RETURN(ERR_PTR(-EINVAL));
         }
 
        tableno = cache->cache_snap_tableno; 
        table = &snap_tables[tableno];
 
        if( table->tbl_count <= 1 )
-               return NULL;
+               RETURN(NULL);
        
-       index = table->tbl_index[0]
+       index = table->snap_items[0].index;
        for ( i = 1 ; i < table->tbl_count ; i++ ) {
-               if ( (dentry->d_name.len == strlen(table->tbl_name[i])) &&
-                    (memcmp(dentry->d_name.name, table->tbl_name[i], 
+               if ( (dentry->d_name.len == strlen(table->snap_items[i].name)) &&
+                    (memcmp(&dentry->d_name.name[0], &table->snap_items[i].name[0], 
                             dentry->d_name.len) == 0) ) {
-                       index = table->tbl_index[i]
+                       index = table->snap_items[i].index
                        break;
                }
        }
        
        if( i >= table->tbl_count )
-               return ERR_PTR(-ENOENT);
+               RETURN(ERR_PTR(-ENOENT));
 
        inode = iget(dir->i_sb, dir->i_ino & (~0xF0000000));
 
         if ( !inode ) 
-                return ERR_PTR(-EINVAL);
+                RETURN(ERR_PTR(-EINVAL));
 
        ino =  snapops->get_indirect_ino(inode, index);
        iput(inode); 
@@ -120,15 +111,15 @@ struct dentry *dotsnap_lookup(struct inode *dir,  struct dentry *dentry)
        }
 
        if ( ino == -EINVAL ) {
-               return ERR_PTR(-EINVAL);
+               RETURN(ERR_PTR(-EINVAL));
        }
-CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino);
+       CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino);
 
        inode = iget(dir->i_sb, ino);
        d_add(dentry, inode); 
        dentry->d_fsdata = (void*)index;
        inode->i_op = dentry->d_parent->d_parent->d_inode->i_op;
-       return NULL;
+       RETURN(NULL);
 }
 
 
@@ -145,55 +136,47 @@ static int dotsnap_readdir(struct file * filp,
 
        cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
        if ( !cache ) {
-               printk("dotsnap_readdir: cannot find cache\n");
+               CDEBUG(D_INODE, "dotsnap_readdir: cannot find cache\n");
                make_bad_inode(filp->f_dentry->d_inode);
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
 
        snapops = filter_c2csnapops(cache->cache_filter);
        if (!snapops || !snapops->get_indirect_ino) {
-                EXIT;
-                return -EINVAL;
+                RETURN(-EINVAL);
         }
 
        tableno = cache->cache_snap_tableno; 
        table = &snap_tables[tableno];
-       CDEBUG(D_INODE, "\n");  
        for (i = filp->f_pos ; i < table->tbl_count -1 ; i++) {
                int index;
                struct inode *inode;
                ino_t ino;
 
-               CDEBUG(D_INODE, "%d\n",i);      
 
                inode = filp->f_dentry->d_inode;
-               index = table->tbl_index[i+1];
+               index = table->snap_items[i+1].index;
                ino =  snapops->get_indirect_ino 
                        (filp->f_dentry->d_inode, index);
 
-               CDEBUG(D_INODE, "\n");  
-
                if ( ino == -ENOATTR || ino == 0 ) {
                        ino = filp->f_dentry->d_parent->d_inode->i_ino;
                }
-
-               CDEBUG(D_INODE, "\n");  
+               
                if ( ino == -EINVAL ) {
                        return -EINVAL;
                }
 
-               CDEBUG(D_INODE, "Listing %s\n", table->tbl_name[i+1]);  
-               if (filldir(dirent, table->tbl_name[i+1],
-                           strlen(table->tbl_name[i+1]),
-                           filp->f_pos, ino) < 0){
+               CDEBUG(D_INODE, "Listing %s\n", &table->snap_items[i+1].name[0]);       
+               if (filldir(dirent, &table->snap_items[i+1].name[0],
+                           strlen(&table->snap_items[i+1].name[0]),
+                           filp->f_pos, ino, 0) < 0){
                        CDEBUG(D_INODE, "\n");
                        break;
                }
                filp->f_pos++;
        }
-       EXIT;
-       return 0;
+       RETURN(0);
 }
 
 
@@ -203,6 +186,5 @@ struct file_operations dotsnap_file_operations = {
 
 struct inode_operations dotsnap_inode_operations =
 {
-       default_file_ops: &dotsnap_file_operations,
        lookup: dotsnap_lookup
 };
index 38c5652..c6795aa 100644 (file)
@@ -2,25 +2,19 @@
  * file.c
  */
 
-#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#define __NO_VERSION__
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include "snapfs_internal.h" 
 
 /* instantiate a file handle to the cache file */
 static void currentfs_prepare_snapfile(struct inode *inode,
@@ -29,17 +23,13 @@ static void currentfs_prepare_snapfile(struct inode *inode,
                                     struct file *cache_file,
                                     struct dentry *cache_dentry)
 {
-       ENTRY;
         cache_file->f_pos = clone_file->f_pos;
         cache_file->f_mode = clone_file->f_mode;
         cache_file->f_flags = clone_file->f_flags;
         cache_file->f_count  = clone_file->f_count;
         cache_file->f_owner  = clone_file->f_owner;
-       cache_file->f_op = cache_inode->i_op->default_file_ops;
        cache_file->f_dentry = cache_dentry;
         cache_file->f_dentry->d_inode = cache_inode;
-       EXIT;
-        return ;
 }
 
 /* update the currentfs file struct after IO in cache file */
@@ -48,10 +38,7 @@ static void currentfs_restore_snapfile(struct inode *cache_inode,
                                   struct inode *clone_inode,
                                   struct file *clone_file)
 {
-       ENTRY;
         cache_file->f_pos = clone_file->f_pos;
-       EXIT;
-        return;
 }
 
 
@@ -67,41 +54,34 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
        struct snap_table *table;
        int slot = 0;
        int index = 0;
-       struct inode_operations *ciops;
+       struct address_space_operations *aops;
        struct inode *cache_inode = NULL;
        struct snapshot_operations *snapops;
   
        ENTRY;
 
-       if (currentfs_is_under_dotsnap(filp->f_dentry)) {
-               EXIT;
-               return -ENOSPC;
-       }
+       if (currentfs_is_under_dotsnap(filp->f_dentry)) 
+               RETURN(-ENOSPC);
 
         cache = snap_find_cache(inode->i_dev);
-        if ( !cache ) { 
-                EXIT;
-                return -EINVAL;
-        }
+        if ( !cache ) 
+                RETURN(-EINVAL);
 
         if ( snap_needs_cow(inode) != -1 ) {
-                CDEBUG(D_FILE, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
                 snap_do_cow(inode, filp->f_dentry->d_parent->d_inode->i_ino, 0);
        }
 
         fops = filter_c2cffops(cache->cache_filter); 
-        if (!fops ||
-            !fops->write) {
-                EXIT;
-                return -EINVAL;
-        }
+        if (!fops || !fops->write) 
+                RETURN(-EINVAL);
 
         if (filp->f_flags & O_APPEND)
                 pos = inode->i_size;
         else {
                 pos = *ppos;
                 if (pos != *ppos)
-                        return -EINVAL;
+                        RETURN(-EINVAL);
         }
 
        /*
@@ -115,41 +95,38 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
                block[1] = pos >> inode->i_sb->s_blocksize_bits;
        if( block[0] == block[1] )
                block[1] = -1;
-
-       ciops = filter_c2cfiops(cache->cache_filter);
+       
+       aops = filter_c2cfaops(cache->cache_filter);
        snapops = filter_c2csnapops(cache->cache_filter);
 
        for( i=0; i<2; i++ ){
-               if( block[i]!=-1 && !ciops->bmap(inode, block[i]) ) {
+               if(block[i]!=-1 && aops->bmap(inode->i_mapping, block[i])) {
                        table = &snap_tables[cache->cache_snap_tableno];
-                       for (slot = table->tbl_count ; slot >= 1; slot--)
-                       {
+                       for (slot = table->tbl_count ; slot >= 1; slot--) {
+                               struct address_space_operations *c_aops = 
+                                       cache_inode->i_mapping->a_ops;
                                cache_inode = NULL;
-                               index = table->tbl_index[slot];
+                               index = table->snap_items[slot].index;
                                cache_inode = snap_get_indirect(inode, NULL, index);
 
                                if ( !cache_inode )  continue;
 
-                               if (cache_inode->i_op->bmap(cache_inode, block[i])) {
-                                       CDEBUG(D_FILE, "find cache_ino %lu\n",
+                               if (c_aops->bmap(cache_inode->i_mapping, block[i])) {
+                                       CDEBUG(D_SNAP, "find cache_ino %lu\n",
                                                cache_inode->i_ino);
                                        if( snapops && snapops->copy_block) {
-                                               snapops->copy_block( inode, 
+                                               snapops->copy_block(inode, 
                                                                cache_inode, block[i]);
                                        }
-
                                        iput(cache_inode);
                                        break;
                                }
-                                        iput(cache_inode);
+                                       iput(cache_inode);
                        }
                }
        }
-
         rc = fops->write(filp, buf, count, ppos);
-        
-        EXIT;
-        return rc;
+        RETURN(rc);
 }
 
 static int currentfs_readpage(struct file *file, struct page *page)
@@ -161,7 +138,7 @@ static int currentfs_readpage(struct file *file, struct page *page)
        struct inode *cache_inode = NULL;
        struct file open_file;
        struct dentry open_dentry ;
-       struct inode_operations *ciops;
+       struct address_space_operations *c_aops;
        struct snap_cache *cache;
        long block;
        struct snap_table *table;
@@ -173,21 +150,19 @@ static int currentfs_readpage(struct file *file, struct page *page)
 
        cache = snap_find_cache(inode->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
+       
+       c_aops = filter_c2cfaops(cache->cache_filter);
 
-       ciops = filter_c2cfiops(cache->cache_filter);
-
-       block = page->offset >> inode->i_sb->s_blocksize_bits;
+       block = page->index >> inode->i_sb->s_blocksize_bits;
 
        /* if there is a block in the cache, return the cache readpage */
-       if( inode->i_blocks && ciops->bmap(inode, block) ) {
-               CDEBUG(D_FILE, "block %lu in cache, ino %lu\n", 
+       if( inode->i_blocks && c_aops->bmap(inode->i_mapping, block) ) {
+               CDEBUG(D_SNAP, "block %lu in cache, ino %lu\n", 
                                block, inode->i_ino);
-               result = ciops->readpage(file, page);
-               EXIT;
-               return result;
+               result = c_aops->readpage(file, page);
+               RETURN(result);
        }
 
        /*
@@ -197,7 +172,7 @@ static int currentfs_readpage(struct file *file, struct page *page)
        if( file->f_dentry->d_fsdata ){
                pri_inode = iget(inode->i_sb, (unsigned long)file->f_dentry->d_fsdata);
                if( !pri_inode )
-                       return -EINVAL;
+                       RETURN(-EINVAL);
                inode = pri_inode;
                search_older = 1;
        }
@@ -206,54 +181,55 @@ static int currentfs_readpage(struct file *file, struct page *page)
 
         for (slot = table->tbl_count ; slot >= 1; slot--)
         {
+               struct address_space_operations *c_aops = 
+                                       cache_inode->i_mapping->a_ops;
                cache_inode = NULL;
-                index = table->tbl_index[slot];
+                index = table->snap_items[slot].index;
                cache_inode = snap_get_indirect(inode, NULL, index);
 
-               if ( !cache_inode )  continue;
+               if (!cache_inode )  continue;
 
                /* we only want slots between cache_inode to the oldest one */
-               if( search_older && cache_inode->i_ino == ind_ino )
+               if(search_older && cache_inode->i_ino == ind_ino )
                        search_older = 0;
 
-                if ( !search_older && cache_inode->i_op->bmap(cache_inode, block)) {
+                if (!search_older && c_aops->bmap(cache_inode->i_mapping, block)) 
                         break;
-                }
                 iput(cache_inode);
         }
        if( pri_inode )
                iput(pri_inode);
 
-       if ( !cache_inode ) { 
-               EXIT;
-               return -EINVAL;
-       }
+       if ( !cache_inode )  
+               RETURN(-EINVAL);
 
        currentfs_prepare_snapfile(inode, file, cache_inode, &open_file,
                              &open_dentry);
 
        down(&cache_inode->i_sem);
 
-       if( ciops->readpage ) {
-               CDEBUG(D_FILE, "block %lu NOT in cache, use redirected ino %lu\n", block, cache_inode->i_ino );
-               result = ciops->readpage(&open_file, page);
+       if( c_aops->readpage ) {
+               CDEBUG(D_SNAP, "block %lu NOT in cache, use redirected ino %lu\n", 
+                      block, cache_inode->i_ino );
+               result = c_aops->readpage(&open_file, page);
        }else {
-               CDEBUG(D_FILE, "cache ino %lu, readpage is NULL\n", 
-                               cache_inode->i_ino);
+               CDEBUG(D_SNAP, "cache ino %lu, readpage is NULL\n", 
+                      cache_inode->i_ino);
        }
-
        up(&cache_inode->i_sem);
        currentfs_restore_snapfile(inode, file, cache_inode, &open_file);
        iput(cache_inode);
-        EXIT;
-       return result;
+       RETURN(result);
 }
-
+struct address_space_operations currentfs_file_aops = {
+       readpage:       currentfs_readpage,
+};
+                                                                                                                                                                                                     
 struct file_operations currentfs_file_fops = {
-       write:currentfs_write,
+       write:          currentfs_write,
 };
-
+                                                                                                                                                                                                     
 struct inode_operations currentfs_file_iops = {
-       default_file_ops: &currentfs_file_fops,
-       readpage: currentfs_readpage,
+       revalidate:     NULL,
 };
+
index c63caac..263029c 100644 (file)
@@ -1,37 +1,21 @@
 /*
- *
- *
- *  Copyright (C) 2000 Stelias Computing, Inc.
- *  Copyright (C) 2000 Red Hat, Inc.
- *  Copyright (C) 2000 Mountain View Data, Inc.
- *
- *
+ * filter.c
  */
+#define DEBUG_SUBSYSTEM S_SNAP
 
-#include <stdarg.h>
-
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/blkdev.h>
-#include <linux/init.h>
-#define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
 
-int filter_print_entry = 1;
-int filter_debug = 0xfffffff;
 /*
  * The function in this file are responsible for setting up the 
  * correct methods layered file systems like InterMezzo and SnapFS
@@ -71,6 +55,11 @@ inline struct file_operations *filter_c2uffops(struct filter_fs *cache)
        return &cache->o_fops.filter_file_fops;
 }
 
+inline struct address_space_operations *filter_c2ufaops(struct filter_fs *cache)
+{
+       return &cache->o_fops.filter_file_aops;
+}
+
 inline struct file_operations *filter_c2usfops(struct filter_fs *cache)
 {
        return &cache->o_fops.filter_sym_fops;
@@ -97,6 +86,11 @@ inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache)
        return cache->o_caops.cache_file_iops;
 }
 
+inline struct address_space_operations *filter_c2cfaops(struct filter_fs *cache)
+{
+       return cache->o_caops.cache_file_aops;
+}
+
 inline struct inode_operations *filter_c2csiops(struct filter_fs *cache)
 {
        return cache->o_caops.cache_sym_iops;
@@ -131,50 +125,51 @@ inline struct snapshot_operations *filter_c2csnapops(struct filter_fs *cache)
 struct filter_fs *filter_get_filter_fs(const char *cache_type)
 {
        struct filter_fs *ops = NULL;
-       FENTRY;
+       ENTRY;
 
        if ( strlen(cache_type) == strlen("ext2") &&
             memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) {
                ops = &filter_oppar[FILTER_FS_EXT2];
-               FDEBUG(D_SUPER, "ops at %p\n", ops);
+               CDEBUG(D_SUPER, "ops at %p\n", ops);
        }
 
        if ( strlen(cache_type) == strlen("ext3") &&
             memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
                ops = &filter_oppar[FILTER_FS_EXT3];
-               FDEBUG(D_SUPER, "ops at %p\n", ops);
+               CDEBUG(D_SUPER, "ops at %p\n", ops);
        }
        if ( strlen(cache_type) == strlen("reiser") &&
             memcmp(cache_type, "reiser", strlen("reiser")) == 0 ) {
                ops = &filter_oppar[FILTER_FS_REISER];
-               FDEBUG(D_SUPER, "ops at %p\n", ops);
+               CDEBUG(D_SUPER, "ops at %p\n", ops);
        }
 
        if (ops == NULL) {
-               printk("prepare to die: unrecognized cache type for Filter\n");
+               CERROR("prepare to die: unrecognized cache type for Filter\n");
        }
-       FEXIT;
+       EXIT;
        return ops;
 }
 
-
 /*
  *  Frobnicate the InterMezzo/SnapFS operations
  *    this establishes the link between the InterMezzo/SnapFS file system
  *    and the underlying file system used for the cache.
  */
 
-void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_sops, struct super_operations *filter_sops)
+void filter_setup_super_ops(struct filter_fs *cache, 
+                           struct super_operations *cache_sops, 
+                           struct super_operations *filter_sops)
 {
         /* Get ptr to the shared struct snapfs_ops structure. */
        struct filter_ops *uops = &cache->o_fops;
         /* Get ptr to the shared struct cache_ops structure. */
        struct cache_ops *caops = &cache->o_caops;
 
-       FENTRY;
+       ENTRY;
 
        if ( cache->o_flags & FILTER_DID_SUPER_OPS ) {
-               FEXIT;
+               EXIT;
                return;
        }
        cache->o_flags |= FILTER_DID_SUPER_OPS;
@@ -182,7 +177,6 @@ void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *ca
         /* Set the cache superblock operations to point to the
           superblock operations of the underlying file system.  */
        caops->cache_sops = cache_sops;
-
         /*
          * Copy the cache (real fs) superblock ops to the "filter"
          * superblock ops as defaults. Some will be changed below
@@ -195,189 +189,163 @@ void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *ca
        }
        if (cache_sops->read_inode && uops->filter_sops.read_inode) {
                uops->filter_sops.read_inode = filter_sops->read_inode;
-               FDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n",
+               CDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n",
                      cache, cache, uops->filter_sops.read_inode);
        }
-       if (cache_sops->notify_change && uops->filter_sops.notify_change) 
-               uops->filter_sops.notify_change = filter_sops->notify_change;
-       if (cache_sops->remount_fs && uops->filter_sops.remount_fs)
-               uops->filter_sops.remount_fs = filter_sops->remount_fs;
-       FEXIT;
+       uops->filter_sops.clear_inode = filter_sops->clear_inode;
+       
+       EXIT;
 }
 
-
-void filter_setup_dir_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops)
+void filter_setup_dir_ops(struct filter_fs *cache, 
+                         struct inode     *inode,
+                         struct inode_operations *filter_iops, 
+                         struct file_operations *filter_fops)
 {
        struct inode_operations *u_iops;
-       struct file_operations *u_fops, *c_fops, *f_fops;
-       FENTRY;
+       struct file_operations *u_fops;
+       
+       ENTRY;
 
-       if ( cache->o_flags & FILTER_DID_DIR_OPS ) {
-               FEXIT;
+       if (cache->o_flags & FILTER_DID_DIR_OPS) {
+               EXIT;
                return;
        }
-       FDEBUG(D_SUPER, "\n");
        cache->o_flags |= FILTER_DID_DIR_OPS;
 
        /* steal the old ops */
-       cache->o_caops.cache_dir_iops = cache_iops;
-       cache->o_caops.cache_dir_fops = 
-               cache_iops->default_file_ops;
-
-       FDEBUG(D_SUPER, "\n");
-       /* abbreviate */
-       u_iops = &cache->o_fops.filter_dir_iops;
-
-       /* setup our dir iops: copy and modify */
-       memcpy(u_iops, cache_iops, sizeof(*cache_iops));
-       FDEBUG(D_SUPER, "\n");
+       cache->o_caops.cache_dir_iops = inode->i_op;
+       cache->o_caops.cache_dir_fops = inode->i_fop;
+       
+       u_iops = filter_c2udiops(cache);
+       u_fops = filter_c2udfops(cache); 
+       
+       /* setup our dir iops and fops: copy and modify */
+       memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
+       memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
 
        /* methods that filter if cache filesystem has these ops */
-       if ( cache_iops->lookup && filter_iops->lookup ) {
-       FDEBUG(D_SUPER, "\n");
-               u_iops->lookup = filter_iops->lookup;
-               FDEBUG(D_SUPER, "lookup at %p\n", &filter_iops->lookup);
+       if (filter_iops) {
+               struct inode_operations *cache_iops = inode->i_op;
+               
+               if (cache_iops->lookup && filter_iops->lookup) 
+                       u_iops->lookup = filter_iops->lookup;
+               if (cache_iops->create && filter_iops->create)
+                       u_iops->create = filter_iops->create;
+               if (cache_iops->link && filter_iops->link)
+                       u_iops->link = filter_iops->link;
+               if (cache_iops->unlink && filter_iops->unlink)
+                       u_iops->unlink = filter_iops->unlink;
+               if (cache_iops->mkdir && filter_iops->mkdir)
+                       u_iops->mkdir = filter_iops->mkdir;
+               if (cache_iops->rmdir && filter_iops->rmdir)
+                       u_iops->rmdir = filter_iops->rmdir;
+               if (cache_iops->symlink && filter_iops->symlink)
+                       u_iops->symlink = filter_iops->symlink;
+               if (cache_iops->rename && filter_iops->rename)
+                       u_iops->rename = filter_iops->rename;
+               if (cache_iops->mknod && filter_iops->mknod)
+                       u_iops->mknod = filter_iops->mknod;
+               if (cache_iops->permission && filter_iops->permission)
+                       u_iops->permission = filter_iops->permission;
        }
-       if (cache_iops->create && filter_iops->create)
-               u_iops->create = filter_iops->create;
-       FDEBUG(D_SUPER, "\n");
-       if (cache_iops->link && filter_iops->link)
-               u_iops->link = filter_iops->link;
-       FDEBUG(D_SUPER, "\n");
-       if (cache_iops->unlink && filter_iops->unlink)
-               u_iops->unlink = filter_iops->unlink;
-       FDEBUG(D_SUPER, "\n");
-       if (cache_iops->mkdir && filter_iops->mkdir)
-               u_iops->mkdir = filter_iops->mkdir;
-       FDEBUG(D_SUPER, "\n");
-       if (cache_iops->rmdir && filter_iops->rmdir)
-               u_iops->rmdir = filter_iops->rmdir;
-       FDEBUG(D_SUPER, "\n");
-       if (cache_iops->symlink && filter_iops->symlink)
-               u_iops->symlink = filter_iops->symlink;
-       FDEBUG(D_SUPER, "\n");
-       if (cache_iops->rename && filter_iops->rename)
-               u_iops->rename = filter_iops->rename;
-       FDEBUG(D_SUPER, "\n");
-       if (cache_iops->mknod && filter_iops->mknod)
-               u_iops->mknod = filter_iops->mknod;
-       FDEBUG(D_SUPER, "\n");
-       if (cache_iops->permission && filter_iops->permission)
-               u_iops->permission = filter_iops->permission;
-
        /* copy dir fops */
-       FDEBUG(D_SUPER, "\n");
-       u_fops = &cache->o_fops.filter_dir_fops;
-       c_fops = cache_iops->default_file_ops;
-       f_fops = filter_iops->default_file_ops;
-
-        memcpy(u_fops, c_fops, sizeof(*c_fops));
-
-       if( c_fops->readdir && f_fops->readdir )
-               u_fops->readdir = f_fops->readdir;
-
-       /* assign */
-       FDEBUG(D_SUPER, "\n");
-       filter_c2udiops(cache)->default_file_ops = filter_c2udfops(cache);
-       FDEBUG(D_SUPER, "\n");
-
-       /* unconditional filtering operations */
-       if ( filter_iops->default_file_ops && 
-            filter_iops->default_file_ops->open ) 
-               filter_c2udfops(cache)->open = 
-                       filter_iops->default_file_ops->open;
-
-       FEXIT;
+       
+       if (filter_fops) {
+               struct file_operations *cache_fops = inode->i_fop;
+               
+               if(cache_fops->readdir && filter_fops->readdir)
+                       u_fops->readdir = filter_fops->readdir;
+       }
+       EXIT;
 }
 
-
-void filter_setup_file_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops)
+void filter_setup_file_ops(struct filter_fs       *cache, 
+                          struct inode            *inode,
+                          struct inode_operations *filter_iops,
+                          struct file_operations  *filter_fops,
+                          struct address_space_operations *filter_aops)
 {
        struct inode_operations *u_iops;
-       FENTRY;
+       struct file_operations *u_fops;
+       struct address_space_operations *u_aops;
+       ENTRY;
 
-       if ( cache->o_flags & FILTER_DID_FILE_OPS ) {
-               FEXIT;
+       if (cache->o_flags & FILTER_DID_FILE_OPS || !inode ) { 
+               EXIT;
                return;
        }
+
        cache->o_flags |= FILTER_DID_FILE_OPS;
 
        /* steal the old ops */
-       cache->o_caops.cache_file_iops = cache_iops;
-       cache->o_caops.cache_file_fops = 
-               cache_iops->default_file_ops;
+       cache->o_caops.cache_file_iops = inode->i_op; 
+       cache->o_caops.cache_file_fops = inode->i_fop;
 
        /* abbreviate */
        u_iops = filter_c2ufiops(cache); 
-
+       u_fops = filter_c2uffops(cache); 
+       u_aops = filter_c2ufaops(cache); 
+               
        /* setup our dir iops: copy and modify */
-       memcpy(u_iops, cache_iops, sizeof(*cache_iops));
+       memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
+       memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
 
-       /* copy dir fops */
-        memcpy(filter_c2uffops(cache), cache_iops->default_file_ops, 
-              sizeof(*cache_iops->default_file_ops));
-       /* assign */
-       filter_c2ufiops(cache)->default_file_ops = filter_c2uffops(cache);
-
-       /* unconditional filtering operations */
-       if (filter_iops->default_file_ops &&
-           filter_iops->default_file_ops->open ) 
-               filter_c2uffops(cache)->open = 
-                       filter_iops->default_file_ops->open;
-       if (filter_iops->default_file_ops &&
-           filter_iops->default_file_ops->release ) 
-               filter_c2uffops(cache)->release = 
-                       filter_iops->default_file_ops->release;
-       if (filter_iops->default_file_ops &&
-           filter_iops->default_file_ops->write ) 
-               filter_c2uffops(cache)->write = 
-                       filter_iops->default_file_ops->write;
-
-       /* set up readpage */
-       if (filter_iops->readpage) 
-               filter_c2ufiops(cache)->readpage = filter_iops->readpage;
-
-       FEXIT;
+       if (inode->i_mapping && inode->i_mapping->a_ops) {
+               cache->o_caops.cache_file_aops = inode->i_mapping->a_ops; 
+               memcpy(u_aops, inode->i_mapping->a_ops, 
+                      sizeof(struct address_space_operations));
+       }
+       if (filter_iops) {
+               if (filter_iops->revalidate)
+                       u_iops->revalidate = filter_iops->revalidate;
+       }
+       if (filter_fops) {
+               if (filter_fops->read)
+                       u_fops->read = filter_fops->read;
+       }
+       if (filter_aops) {
+               if (filter_aops->readpage)
+                       u_aops->readpage = filter_aops->readpage;
+       }
+       EXIT;
 }
 
-/* XXX in 2.3 there are "fast" and "slow" symlink ops for ext2 XXX */
-void filter_setup_symlink_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops)
+void filter_setup_symlink_ops(struct filter_fs *cache, 
+                             struct inode *inode,
+                             struct inode_operations *filter_iops, 
+                             struct file_operations *filter_fops)
 {
        struct inode_operations *u_iops;
-       FENTRY;
+       struct file_operations *u_fops;
+       
+       ENTRY;
 
-       if ( cache->o_flags & FILTER_DID_SYMLINK_OPS ) {
-               FEXIT;
+       if (cache->o_flags & FILTER_DID_SYMLINK_OPS || !inode ) {
+               EXIT;
                return;
        }
        cache->o_flags |= FILTER_DID_SYMLINK_OPS;
 
        /* steal the old ops */
-       cache->o_caops.cache_sym_iops = cache_iops;
-       cache->o_caops.cache_sym_fops = 
-               cache_iops->default_file_ops;
+       cache->o_caops.cache_sym_iops = inode->i_op;
+       cache->o_caops.cache_sym_fops = inode->i_fop; 
 
        /* abbreviate */
        u_iops = filter_c2usiops(cache); 
+       u_fops = filter_c2usfops(cache); 
 
        /* setup our dir iops: copy and modify */
-       memcpy(u_iops, cache_iops, sizeof(*cache_iops));
-
-       /* copy fops - careful for symlinks they might be NULL */
-       if ( cache_iops->default_file_ops ) { 
-               memcpy(filter_c2usfops(cache), cache_iops->default_file_ops, 
-                      sizeof(*cache_iops->default_file_ops));
+       memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
+       memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
+       if (filter_iops) {
+               struct inode_operations *cache_iops = inode->i_op; 
+               if (cache_iops->readlink && filter_iops->readlink) 
+                       u_iops->readlink = filter_iops->readlink;
+               if (cache_iops->follow_link && filter_iops->follow_link)
+                       u_iops->follow_link = filter_iops->follow_link;
        }
-
-       /* assign */
-       filter_c2usiops(cache)->default_file_ops = filter_c2usfops(cache);
-
-       if (cache_iops->readlink && filter_iops->readlink) 
-               u_iops->readlink = filter_iops->readlink;
-       if (cache_iops->follow_link && filter_iops->follow_link)
-               u_iops->follow_link = filter_iops->follow_link;
-
-       FEXIT;
+       EXIT;
 }
 
 void filter_setup_dentry_ops(struct filter_fs *cache,
@@ -385,7 +353,7 @@ void filter_setup_dentry_ops(struct filter_fs *cache,
                             struct dentry_operations *filter_dop)
 {
        if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) {
-               FEXIT;
+               EXIT;
                return;
        }
        cache->o_flags |= FILTER_DID_DENTRY_OPS;
@@ -395,39 +363,40 @@ void filter_setup_dentry_ops(struct filter_fs *cache,
               filter_dop, sizeof(*filter_dop));
        
        if (cache_dop &&  cache_dop != filter_dop && cache_dop->d_revalidate){
-               printk("WARNING: filter overriding revalidation!\n");
+               CWARN("filter overriding revalidation!\n");
        }
+       EXIT;
        return;
 }
 /* snapfs : for snapshot operations */
 void filter_setup_snapshot_ops (struct filter_fs *cache, 
                                struct snapshot_operations *cache_snapops)
 {
-       FENTRY;
+       ENTRY;
 
        if ( cache->o_flags & FILTER_DID_SNAPSHOT_OPS ) {
-               FEXIT;
+               EXIT;
                return;
        }
        cache->o_flags |= FILTER_DID_SNAPSHOT_OPS;
 
        cache->o_snapops = cache_snapops;
 
-       FEXIT;
+       EXIT;
 }
 
 void filter_setup_journal_ops (struct filter_fs *cache,
                               struct journal_ops *cache_journal_ops)
 {
-       FENTRY;
+       ENTRY;
 
        if( cache->o_flags & FILTER_DID_JOURNAL_OPS ){
-               FEXIT;
+               EXIT;
                return;
        }
        cache->o_flags |= FILTER_DID_JOURNAL_OPS;
 
        cache->o_trops = cache_journal_ops;
 
-       FEXIT;
+       EXIT;
 }
index d6434f3..9f43d0d 100644 (file)
@@ -5,32 +5,17 @@
  *
  */
 
-#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-#ifdef CONFIG_SNAPFS_EXT2
-#include <linux/ext2_fs.h>
-#endif
-#ifdef CONFIG_SNAPFS_EXT3
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/jbd.h>
 #include <linux/ext3_fs.h>
-#endif
-
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include <linux/string.h>
+#include <linux/snap.h>
+#include "snapfs_internal.h" 
 
 
 extern int currentfs_remount(struct super_block * sb, int *flags, char *data);
@@ -43,104 +28,100 @@ extern int currentfs_remount(struct super_block * sb, int *flags, char *data);
  
 extern void currentfs_dotsnap_read_inode(struct snap_cache *, struct inode *);
 
+static kmem_cache_t *filter_info_cache = NULL;
+
+void cleanup_filter_info_cache()
+{
+       kmem_cache_destroy(filter_info_cache);
+}
+
+int init_filter_info_cache()
+{
+       filter_info_cache = kmem_cache_create("snapfs_filter_info",
+                                              sizeof(struct filter_inode_info), 
+                                           0, 0, NULL, NULL);
+        if (!filter_info_cache) {
+                CERROR("unable to create snap_inode info cache\n");
+               return -ENOMEM;
+        }
+        return 0;
+}
+
+
+void init_filter_data(struct inode *inode, 
+                            struct snapshot_operations *snapops, 
+                            int flag)
+{
+       struct filter_inode_info *i;
+
+       if (inode->i_filterdata){
+                return;
+        }
+       inode->i_filterdata = (struct filter_inode_info *) \
+                             kmem_cache_alloc(filter_info_cache, SLAB_KERNEL);
+       i = inode->i_filterdata;
+       i -> generation = snapops->get_generation(inode);
+       i -> flags      = flag;
+}
 /* Superblock operations. */
 static void currentfs_read_inode(struct inode *inode)
 {
         struct snap_cache *cache;
+       struct snapshot_operations *snapops;    
        ENTRY;
 
        if( !inode ) 
-       {
-               EXIT;
                return;
-       }
 
        CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
 
        cache = snap_find_cache(inode->i_dev);
-       if ( !cache ) {
-               printk("currentfs_read_inode: cannot find cache\n");
+       if (!cache) {
+               CERROR("currentfs_read_inode: cannot find cache\n");
                make_bad_inode(inode);
-               EXIT;
-               return ;
+               return;
        }
 
-       if ( inode->i_ino & 0xF0000000 ) { 
-               CDEBUG(D_INODE, "\n");
+       if (inode->i_ino & 0xF0000000) { 
                currentfs_dotsnap_read_inode(cache, inode);
-               EXIT;
-               return ;
+               return;
        }
+       snapops = filter_c2csnapops(cache->cache_filter);
+       
+       if (!snapops || !snapops->get_indirect) 
+               return;
 
-       if( filter_c2csops(cache->cache_filter) )
+       if(filter_c2csops(cache->cache_filter))
                filter_c2csops(cache->cache_filter)->read_inode(inode);
 
        /* XXX now set the correct snap_{file,dir,sym}_iops */
-       if ( S_ISDIR(inode->i_mode) 
+       if (S_ISDIR(inode->i_mode)
                inode->i_op = filter_c2udiops(cache->cache_filter);
-       else if ( S_ISREG(inode->i_mode) ) {
+       else if (S_ISREG(inode->i_mode)) {
                if ( !filter_c2cfiops(cache->cache_filter) ) {
-                       filter_setup_file_ops(cache->cache_filter,
-                               inode->i_op, &currentfs_file_iops);
+                       filter_setup_file_ops(cache->cache_filter, inode, 
+                                             &currentfs_file_iops, 
+                                             &currentfs_file_fops, 
+                                             &currentfs_file_aops);
                }
-               inode->i_op = filter_c2ufiops(cache->cache_filter);
-               printk("inode %lu, i_op at %p\n", inode->i_ino, inode->i_op);
+               CDEBUG(D_INODE, "inode %lu, i_op at %p\n", 
+                      inode->i_ino, inode->i_op);
        }
-       else if ( S_ISLNK(inode->i_mode) ) {
+       else if (S_ISLNK(inode->i_mode)) {
                if ( !filter_c2csiops(cache->cache_filter) ) {
-                       filter_setup_symlink_ops(cache->cache_filter,
-                               inode->i_op, &currentfs_sym_iops);
+                       filter_setup_symlink_ops(cache->cache_filter, inode,
+                               &currentfs_sym_iops, &currentfs_sym_fops);
                }
                inode->i_op = filter_c2usiops(cache->cache_filter);
-               printk("inode %lu, i_op at %p\n", inode->i_ino, inode->i_op);
+               CDEBUG(D_INODE, "inode %lu, i_op at %p\n", 
+                      inode->i_ino, inode->i_op);
        }
-
-       EXIT;
+       /*init filter_data struct 
+        * FIXME flag should be set future*/
+       init_filter_data(inode, snapops, 0); 
        return; 
 }
 
-
-static int currentfs_notify_change(struct dentry *dentry, struct iattr *iattr)
-{
-       struct snap_cache *cache;
-       int rc;
-       struct super_operations *sops;
-
-       ENTRY;
-
-       if (currentfs_is_under_dotsnap(dentry)) {
-               EXIT;
-               return -EPERM;
-       }
-
-       cache = snap_find_cache(dentry->d_inode->i_dev);
-       if ( !cache ) { 
-               EXIT;
-               return -EINVAL;
-       }
-
-       /* XXX better alloc a new dentry */
-
-       if ( snap_needs_cow(dentry->d_inode) != -1 ) {
-               printk("notify_change:snap_needs_cow for ino %lu \n",
-                       dentry->d_inode->i_ino);
-               snap_do_cow(dentry->d_inode, 
-                       dentry->d_parent->d_inode->i_ino, 0);
-       }
-
-       sops = filter_c2csops(cache->cache_filter); 
-       if (!sops ||
-           !sops->notify_change) {
-               EXIT;
-               return -EINVAL;
-       }
-       rc = sops->notify_change(dentry, iattr);
-       
-       EXIT;
-       return rc;
-}
-
-
 static void currentfs_put_super(struct super_block *sb)
 {
 
@@ -150,10 +131,10 @@ static void currentfs_put_super(struct super_block *sb)
        CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
                 (ulong) sb, (ulong) sb->u.generic_sbp);
        cache = snap_find_cache(sb->s_dev);
-       if (!cache) {
-               EXIT;
-               goto exit;
-       }
+
+       if (!cache) 
+               GOTO(exit, 0);  
+       
        /* handle COMPAT_FEATUREs */
 #ifdef CONFIG_SNAPFS_EXT2
        else if( cache->cache_type == FILTER_FS_EXT2 ){
@@ -182,7 +163,7 @@ static void currentfs_put_super(struct super_block *sb)
        }
        
        if (!list_empty(&cache->cache_clone_list)) {
-               printk("Warning: snap_put_super: clones exist!\n");
+               CWARN("snap_put_super: clones exist!\n");
        }
 
        list_del(&cache->cache_chain);
@@ -191,21 +172,32 @@ static void currentfs_put_super(struct super_block *sb)
        CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
                 (ulong) sb, (ulong) sb->u.generic_sbp);
 exit:
-       CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
-              snap_kmemory, snap_vmemory);
-       MOD_DEC_USE_COUNT;
        EXIT;
-       return ;
+       return;
+}
+static void currentfs_clear_inode(struct inode *inode)
+{
+       struct snap_cache *cache;
+        struct super_operations *sops;
+       ENTRY;                                                                                                                                                                                                                       
+        cache = snap_find_cache(inode->i_dev);
+        if (!cache) {
+                CDEBUG(D_INODE, "inode has invalid dev\n");
+                return;
+        }
+       
+       if (inode->i_filterdata) {
+               kmem_cache_free(filter_info_cache, inode->i_filterdata);
+               inode->i_filterdata = NULL;
+       }
+
+       sops = filter_c2csops(cache->cache_filter);
+        if (sops && sops->clear_inode)
+                sops->clear_inode(inode);
 }
 
 struct super_operations currentfs_super_ops = {
-       currentfs_read_inode,
-       NULL, /* write inode */
-       NULL, /* put inode */
-       NULL, /* delete inode */
-       currentfs_notify_change,
-       currentfs_put_super,
-       NULL, /* write super */
-       NULL,
-       NULL, /* remount */
+       read_inode:     currentfs_read_inode,
+       put_super:      currentfs_put_super,
+       clear_inode:    currentfs_clear_inode,
 };
index 8171842..7a4fa7e 100644 (file)
@@ -3,26 +3,21 @@
  * Snapfs. (C) 2000 Peter J. Braam
  */
 
-#include <linux/types.h>
+#define DEBUG_SUBSYSTEM S_SNAP
+
+#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
 #include <linux/string.h>
-#ifdef CONFIG_SNAPFS_EXT3
-#include <linux/ext3_jfs.h>
-#endif
-#include "linux/filter.h"
-#include "linux/snapfs.h"
-#include "linux/snapsupport.h"
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#ifdef CONFIG_SNAPFS_EXT3
 
 #define EXT3_EA_TRANS_BLOCKS EXT3_DATA_TRANS_BLOCKS
 
@@ -63,17 +58,17 @@ static void *snap_e3_trans_start(struct inode *inode, int op)
                jblocks = 4 * COW_CREDITS + 2 * EXT3_DATA_TRANS_BLOCKS + 2;
                break;
        default:
-               CDEBUG(D_JOURNAL, "invalid operation %d for journal\n", op);
+               CDEBUG(D_INODE, "invalid operation %d for journal\n", op);
                return NULL;
        }
 
-       CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks);
-       return journal_start(EXT3_JOURNAL(inode), jblocks);
+       CDEBUG(D_INODE, "creating journal handle (%d blocks)\n", jblocks);
+       return ext3_journal_start(inode, jblocks);
 }
 
 static void snap_e3_trans_commit(void *handle)
 {
-       journal_stop(current->j_handle);
+       journal_stop(handle);
 }
 
 struct journal_ops snap_ext3_journal_ops = {
@@ -81,4 +76,3 @@ struct journal_ops snap_ext3_journal_ops = {
        snap_e3_trans_commit
 };
 
-#endif /* CONFIG_EXT3_FS */
index 424d325..764adcc 100644 (file)
 
 #define EXPORT_SYMTAB
 
-#include <linux/config.h> /* for CONFIG_PROC_FS */
+
+#define DEBUG_SUBSYSTEM S_SNAP
+
 #include <linux/module.h>
-#include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
-/* #include <linux/kmod.h>    for request_module() */
-#include <linux/sched.h>
-#include <linux/lp.h>
-#include <linux/malloc.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/skbuff.h>
-#include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/poll.h>
-#include <asm/uaccess.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
 #include <linux/miscdevice.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
-#if 1 /* XXX - enable for debug messages */
 int snap_print_entry = 1;
-int snap_debug_level = ~D_INFO;
-#else
-int snap_print_entry = 0;
 int snap_debug_level = 0;
-#endif
 int snap_inodes = 0;
-long snap_memory = 0;
-
+long snap_kmemory = 0;
+int snap_stack = 0;
 struct snap_control_device snap_dev;
 
 extern int snap_ioctl (struct inode * inode, struct file * filp, 
@@ -64,14 +46,12 @@ static int snap_psdev_open(struct inode * inode, struct file * file)
         ENTRY;
 
        if (!inode)
-               return -EINVAL;
+               RETURN(-EINVAL);
        dev = MINOR(inode->i_rdev);
        if (dev != SNAP_PSDEV_MINOR)
-               return -ENODEV;
+               RETURN(-ENODEV);
 
-        MOD_INC_USE_COUNT;
-        EXIT;
-        return 0;
+        RETURN(0);
 }
 
 /* called when closing /dev/device */
@@ -81,15 +61,12 @@ static int snap_psdev_release(struct inode * inode, struct file * file)
         ENTRY;
 
        if (!inode)
-               return -EINVAL;
+               RETURN(-EINVAL);
        dev = MINOR(inode->i_rdev);
        if (dev != SNAP_PSDEV_MINOR)
-               return -ENODEV;
-
-        MOD_DEC_USE_COUNT;
+               RETURN(-ENODEV);
 
-        EXIT;
-        return 0;
+        RETURN(0);
 }
 
 /* XXX need ioctls here to do snap_delete and snap_restore, snap_backup */
@@ -97,19 +74,9 @@ static int snap_psdev_release(struct inode * inode, struct file * file)
 
 /* declare character device */
 static struct file_operations snapcontrol_fops = {
-       NULL,                  /* llseek */
-       NULL,                  /* read */
-       NULL,                  /* write */
-       NULL,                  /* presto_psdev_readdir */
-        NULL,                  /* poll */
-       snap_ioctl,            /* ioctl */
-       NULL,                  /* presto_psdev_mmap */
-       snap_psdev_open,       /* open */
-       NULL,
-       snap_psdev_release,    /* release */
-       NULL,                  /* fsync */
-       NULL,                  /* fasync */
-       NULL                   /* lock */
+       ioctl:          snap_ioctl,            /* ioctl */
+       open:           snap_psdev_open,       /* open */
+       release:        snap_psdev_release,    /* release */
 };
 
 
@@ -117,14 +84,14 @@ static struct file_operations snapcontrol_fops = {
 #define SNAPFS_MINOR 240
 
 static struct miscdevice snapcontrol_dev = {
-       SNAPFS_MINOR,
-       "snapcontrol",
-       &snapcontrol_fops
+       minor:  SNAPFS_MINOR,
+       name:   "snapcontrol",
+       fops:   &snapcontrol_fops
 };
 
 int init_snap_psdev(void)
 {
-       printk(KERN_INFO "SNAP psdev driver  v0.01, braam@mountainviewdata.com\n");
+       printk(KERN_INFO "SNAP psdev driver  v0.01, braam@clusterfs.com\n");
        
        misc_register( &snapcontrol_dev );
 
@@ -138,7 +105,6 @@ void snap_cleanup_psdev(void)
        EXIT;
 }
 
-#ifdef MODULE
 MODULE_AUTHOR("Peter J. Braam <braam@cs.cmu.edu>");
 MODULE_DESCRIPTION("Snapfs file system filters v0.01");
 
@@ -147,7 +113,7 @@ extern int cleanup_snapfs(void);
 extern int init_clonefs(void);
 extern int init_snap_sysctl(void); 
 
-int init_module(void)
+static int __init snapfs_init(void)
 {
        int err;
        if ( (err = init_snap_psdev()) ) {
@@ -164,17 +130,18 @@ int init_module(void)
                printk("Error initializing snapfs proc sys, %d\n", err);
                return -EINVAL;
        }
-
-
+       
        return 0;
 }
 
-void cleanup_module(void)
+static void __exit snapfs_cleanup(void)
 {
 
        cleanup_snapfs();
        snap_cleanup_psdev();
        
 }
-#endif
+module_init(snapfs_init);
+module_exit(snapfs_cleanup);
+                                                                                                                                                                                                     
 
index 463e0fa..a5032a6 100644 (file)
@@ -6,25 +6,15 @@
  *
  */
 
-#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include <linux/snap.h>
+#include "snapfs_internal.h" 
 
 /*
  * Return true if the inode is a redirector inode.
@@ -36,12 +26,10 @@ int snap_is_redirector(struct inode *cache_inode)
 
        cache = snap_find_cache(cache_inode->i_dev);
        if (!cache) {
-               EXIT;
                return 0;
        }
         snapops = filter_c2csnapops(cache->cache_filter);
         if (!snapops || !snapops->is_redirector) {
-                EXIT;
                 return 0;
         }
 
@@ -68,13 +56,11 @@ struct inode *snap_redirect(struct inode *cache_inode,
 
         cache = snap_find_cache(cache_inode->i_dev);
         if (!cache) {
-                EXIT;
-                return NULL;
+                RETURN(NULL);
         }
         snapops = filter_c2csnapops(cache->cache_filter);
         if (!snapops || !snapops->get_indirect) {
-                EXIT;
-                return NULL;
+                RETURN(NULL);
         }
 
        CDEBUG(D_SNAP, "cache ino %ld\n", cache_inode->i_ino);
@@ -87,22 +73,19 @@ struct inode *snap_redirect(struct inode *cache_inode,
                                        clone_info->clone_index);
        /* if not found, get the FIRST index after this and before NOW */
        /* XXX fix this later, now use tbl_count, not NOW */
-       if(!redirected) {
+       if (!redirected) {
+               int index;
                clone_slot = snap_index2slot(table, clone_info->clone_index);
-               for(slot = table->tbl_count; slot >= clone_slot; slot --)
-               {
-                       my_table[slot-clone_slot+1] = table->tbl_index[slot];
+               for (slot = table->tbl_count; slot >= clone_slot; slot --) {
+                       my_table[slot-clone_slot+1] = table->snap_items[slot].index;
                }
-               redirected = snapops->get_indirect 
-               (cache_inode, my_table, table->tbl_count - clone_slot + 1);
+               index = table->tbl_count - clone_slot + 1;
+               redirected = snapops->get_indirect(cache_inode, my_table, index);
        }
-        /* old version
-       redirected = snapops->get_indirect 
-                       (cache_inode, table->tbl_index,
-                       snap_index2slot(table, clone_info->clone_index));
-       */
-       if(redirected) CDEBUG(D_SNAP,"redirected ino %ld\n",redirected->i_ino);
-       EXIT;
+
+       if (redirected) 
+               CDEBUG(D_SNAP,"redirected ino %ld\n",redirected->i_ino);
+
        return redirected;
 }
 
@@ -122,23 +105,19 @@ int snap_do_cow(struct inode *inode, ino_t parent_ino, int del)
 
        cache = snap_find_cache(inode->i_dev);
        if (!cache) {
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
        snapops = filter_c2csnapops(cache->cache_filter);
        if (!snapops || !snapops->create_indirect) {
-               EXIT;
-               return -EINVAL;
+               RETURN(-EINVAL);
        }
+
        snap_last(cache, &snap);
-       ind = snapops->create_indirect(inode, parent_ino, snap.index, del);
-       EXIT;
-       if(ind) {
-               iput(ind);
-               return  0;
-       }
-       else
-               return -EINVAL;
+       ind = snapops->create_indirect(inode, snap.index, 0, parent_ino, del);
+       if(!ind)
+               RETURN(-EINVAL);                
+       iput(ind);
+       RETURN(0);
 }
 
 int snap_iterate(struct super_block *sb,
@@ -153,16 +132,13 @@ int snap_iterate(struct super_block *sb,
 
         cache = snap_find_cache(inode->i_dev);
         if (!cache) {
-                EXIT;
-                return 0;
+                RETURN(0);
         }
         snapops = filter_c2csnapops(cache->cache_filter);
         if (!snapops || !snapops->iterate) {
-                EXIT;
-                return 0;
+                RETURN(0);
         }
 
-       EXIT;
        return snapops->iterate(sb, repeat, start, priv, flag);
 }
 
@@ -173,17 +149,12 @@ int snap_destroy_indirect(struct inode *pri, int index, struct inode *next_ind )
 
        ENTRY;
         cache = snap_find_cache(pri->i_dev);
-        if (!cache) {
-                EXIT;
-                return 0;
-        }
+        if (!cache) 
+               RETURN(0);
         snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->destroy_indirect) {
-                EXIT;
-                return 0;
-        }
+        if (!snapops || !snapops->destroy_indirect) 
+                RETURN(0);
 
-       EXIT;
        return snapops->destroy_indirect(pri, index, next_ind);
 }
 
@@ -195,17 +166,13 @@ int snap_restore_indirect(struct inode *pri, int index )
        ENTRY;
 
         cache = snap_find_cache(pri->i_dev);
-        if (!cache) {
-                EXIT;
-                return 0;
-        }
+        if (!cache) 
+                RETURN(0);
+
         snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->restore_indirect) {
-                EXIT;
-                return 0;
-        }
+        if (!snapops || !snapops->restore_indirect) 
+                RETURN(0);
 
-       EXIT;
        return snapops->restore_indirect(pri, index);
 }
 
@@ -217,42 +184,16 @@ struct inode *snap_get_indirect(struct inode *pri, int *table, int slot)
        ENTRY;
 
         cache = snap_find_cache(pri->i_dev);
-        if (!cache) {
-                EXIT;
-                return NULL;
-        }
+        if (!cache) 
+                RETURN(NULL);
+        
         snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->get_indirect) {
-                EXIT;
-                return NULL;
-        }
+        if (!snapops || !snapops->get_indirect) 
+                RETURN(NULL);
 
-       EXIT;
        return snapops->get_indirect(pri, table, slot);
 }
 
-int snap_migrate_data(struct inode *dst, struct inode *src)
-{
-       struct snap_cache *cache;
-        struct snapshot_operations *snapops;
-
-       ENTRY;
-
-        cache = snap_find_cache(src->i_dev);
-        if (!cache) {
-                EXIT;
-                return 0;
-        }
-        snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->migrate_data) {
-                EXIT;
-                return 0;
-        }
-
-       EXIT;
-       return snapops->migrate_data(dst, src);
-}
-
 int snap_set_indirect(struct inode *pri, ino_t ind_ino, int index, ino_t parent_ino)
 {
        struct snap_cache *cache;
@@ -261,15 +202,12 @@ int snap_set_indirect(struct inode *pri, ino_t ind_ino, int index, ino_t parent_
        ENTRY;
 
         cache = snap_find_cache(pri->i_dev);
-        if (!cache) {
-                EXIT;
-                return -EINVAL;
-        }
-        snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->set_indirect) {
-                EXIT;
-                return -EINVAL;
-        }
+        if (!cache) 
+                RETURN(-EINVAL);
+        
+       snapops = filter_c2csnapops(cache->cache_filter);
+        if (!snapops || !snapops->set_indirect) 
+                RETURN(-EINVAL);
 
        EXIT;
        return snapops->set_indirect(pri, ind_ino, index, parent_ino);
index 058164b..ac5b712 100644 (file)
@@ -6,28 +6,18 @@
  *
  */
 
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/malloc.h>
-#include <linux/locks.h>
-#include <linux/errno.h>
-#include <linux/swap.h>
-#include <linux/smp_lock.h>
-#include <linux/vmalloc.h>
-#include <linux/blkdev.h>
-#include <linux/sysrq.h>
-#include <linux/file.h>
-#include <linux/init.h>
-#include <linux/quotaops.h>
+#define DEBUG_SUBSYSTEM S_SNAP
 
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/snap.h>
 #include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/mmu_context.h>
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapsupport.h>
-#include <linux/snapfs.h>
 
 struct snap_table snap_tables[SNAP_MAX_TABLES];
 
@@ -52,7 +42,7 @@ int snap_index2slot(struct snap_table *snap_table, int snap_index)
        int slot;
 
        for ( slot=0 ; slot<snap_table->tbl_count ; slot++ )
-               if ( snap_table->tbl_index[slot] == snap_index )
+               if ( snap_table->snap_items[slot].index == snap_index )
                        return slot;
        return -1;
 }
@@ -63,7 +53,8 @@ int snap_index2slot(struct snap_table *snap_table, int snap_index)
    -  the index of the latest snapshot before NOW
    -  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 snap_cache *info, struct snap *snap)
 {
        int i ;
@@ -73,9 +64,10 @@ void snap_last(struct snap_cache *info, struct snap *snap)
 
        ENTRY;
        if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-               printk(__FUNCTION__ ": invalid table no %d\n", tableno);
+               CERROR("invalid table no %d\n", tableno);
                snap->index = -1;
        }
+       
        table = &snap_tables[tableno];
 
        /* start at the highest index in the superblock 
@@ -83,16 +75,11 @@ void snap_last(struct snap_cache *info, struct snap *snap)
        i = table->tbl_count - 1;
 
        /* NOTE: i>0 is an unnecessary check */
-       while ( table->tbl_times[i] > now && i > 0) {
-               CDEBUG(D_SNAP, "time: %ld, i: %d\n", table->tbl_times[i], i);
-               i--;
-       }
-
-       snap->index = table->tbl_index[i];
-       snap->time = table->tbl_times[i];
+       snap->index = table->snap_items[i].index;
+       snap->time = table->snap_items[i].time;
+       snap->gen = table->snap_items[i].gen;
        CDEBUG(D_SNAP, "index: %d, time[i]: %ld, now: %ld\n",
               snap->index, snap->time, now);
-       EXIT;
        return;
 }
 
@@ -104,117 +91,30 @@ int snap_needs_cow(struct inode *inode)
 {
        struct snap snap;
        struct snap_cache *cache;
+       struct filter_inode_info   *filter_info; 
        int index = -1;
        ENTRY;
 
        cache = snap_find_cache(inode->i_dev);
        if ( !cache ) {
-               EXIT;
-               return -1;
+               RETURN(index);
        }
-
+       filter_info = (struct filter_inode_info *) inode->i_filterdata;
        /* here we find the time of the last snap to compare with */
-       snap_last(cache, &snap);
 
+       snap_last(cache, &snap);
        /* decision .... if the snapshot is more recent than the object,
         * then any change to the object should cause a COW.
         */
-       if (inode->i_mtime <= snap.time && inode->i_ctime <= snap.time) {
+       if (filter_info && filter_info->generation < snap.gen ) {
                index = snap.index;
        }
-       printk("snap_needs_cow, ino %lu , get index %d\n",inode->i_ino, index);
 
-       EXIT;
-       return index;
-} /* snap_needs_cow */
+       CDEBUG(D_SNAP, "snap_needs_cow, ino %lu , get index %d\n",
+              inode->i_ino, index);
 
-#if 0
-int  snap_obd2snap(struct snap_clone_info *info, struct snap *snap)
-{
-       struct snap_table *table;
-       int tableno = info->clone_cache->cache_snap_tableno;
-       int index =  info->clone_index;
-       int slot;
-
-       ENTRY;
-       if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-               printk(__FUNCTION__ ": invalid table no %d\n", tableno);
-               snap->index = -1;
-       }
-       table = &snap_tables[tableno];
-       slot = snap_index2slot(table, index);
-
-       snap->index = index;
-       snap->time = table->tbl_times[slot];
-       EXIT;
-       return slot;
-}
-#endif
-
-/* at what index is the current snapshot located */
-int snap_current(struct snap_cache *cache)
-{
-       int tableno = cache->cache_snap_tableno;
-
-       return snap_tables[tableno].tbl_index[0];
-}
-
-int snap_is_used(int table_no, int snap_index) 
-
-{
-       /* ENTRY; */
-       if ( snap_index < 0 || snap_index >= SNAP_MAX ) {
-               printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-                      snap_index, table_no);
-               EXIT;
-               return -1;
-       }
-       if ( table_no < 0 || table_no > SNAP_MAX_TABLES ) {
-               printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-                      snap_index, table_no);
-               EXIT;
-               return -1;
-       }
-
-       /* EXIT; */
-       return snap_tables[table_no].tbl_used & (1<<snap_index);
-}
-
-void snap_use(int table_no, int snap_index) 
-{
-       if ( snap_index < 0 || snap_index >= SNAP_MAX ) {
-               printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-                      snap_index, table_no);
-               return;
-       }
-       if ( table_no < 0 || table_no > SNAP_MAX_TABLES ) {
-               printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-                      snap_index, table_no);
-               return;
-       }
-       if ( snap_index2slot(&snap_tables[table_no], snap_index) < 0 ) 
-               return;
-
-       snap_tables[table_no].tbl_used |=  (1<<snap_index);
-}
-
-void snap_unuse(int table_no, int snap_index) 
-{
-       if ( snap_index < 0 || snap_index >= SNAP_MAX ) {
-               printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-                      snap_index, table_no);
-               return;
-       }
-       if ( table_no < 0 || table_no > SNAP_MAX_TABLES ) {
-               printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-                      snap_index, table_no);
-               return;
-       }
-       if ( snap_index2slot(&snap_tables[table_no], snap_index) < 0 ) 
-               return;
-
-       snap_tables[table_no].tbl_used &=  ~(1<<snap_index);
-}
+       RETURN(index);
+} /* snap_needs_cow */
 
 static int nprint_buf(char *buf, int buflen, char *fmt, ...)
 {
@@ -247,20 +147,18 @@ int snap_print_table(struct snap_table_data *data, char *buf, int *buflen)
        int nprint = 0;
 
        if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-               printk(__FUNCTION__ ": invalid table number %d\n", tableno);
-               EXIT;
-               return -EINVAL;
+               CERROR("invalid table number %d\n", tableno);
+               RETURN(-EINVAL);
        }
 
        table = &snap_tables[tableno];
 
        printk("------- snap table %d\n", tableno);
        printk("     -- snap count %d\n", table->tbl_count);
-       printk("     -- snap used  0x%x\n", table->tbl_used);
        for ( i = 0 ; i < SNAP_MAX ; i++ ) {
                printk("     -- slot %d, idx %d, time %ld, name %s\n",
-                      i, table->tbl_index[i], table->tbl_times[i]
-                       table->tbl_name[i]);
+                      i, table->snap_items[i].index, table->snap_items[i].time
+                       &table->snap_items[i].name[0]);
        }
 
        buf_ptr = buf;
@@ -272,15 +170,14 @@ int snap_print_table(struct snap_table_data *data, char *buf, int *buflen)
        nleft -= nprint;
        if( nleft > 0 )  buf_ptr += nprint;
        else goto exit;
-       nprint = nprint_buf(buf_ptr, nleft, "     -- snap used  0x%x\n", table->tbl_used);
-       nleft -= nprint;
+
        if( nleft > 0 )  buf_ptr += nprint;
        else goto exit;
        for ( i = 0 ; i < SNAP_MAX ; i++ ) {
                nprint = nprint_buf( buf_ptr, nleft,
                        "     -- slot %d, idx %d, time %ld, name %s\n",
-                      i, table->tbl_index[i], table->tbl_times[i]
-                       table->tbl_name[i]);
+                      i, table->snap_items[i].index, table->snap_items[i].time
+                       &table->snap_items[i].name[0]);
                nleft -= nprint;
                if( nleft > 0 )  buf_ptr += nprint;
                else goto exit;
@@ -291,153 +188,301 @@ exit:
 
        return 0;
 }
-
-int snap_install_table(int len, struct snap_table_data *data)
+static int inline get_index_of_item(struct snap_table *table)
 {
+       int count = table->tbl_count;
        int i, j;
-       int tableno = data->tblcmd_no;
-//     int found_current;
-       struct snap_table *table;
 
+       for (i = 0; i < SNAP_MAX; i ++) {
+               for (j = 1; j < count; j++) {
+                       if (table->snap_items[j].index == i)
+                               break;
+                }
+               if (j >= count) 
+                       return i;
+       }
+       return -EINVAL;
+}
+/* This function will write one item(a snapshot) to snaptable  
+ * and will also write to disk.
+ */
+int snaptable_add_item(struct snap_table_data *data)
+{
+       struct snap_table               *table;
+       struct snap_disk_table          *disk_snap_table;
+       struct snapshot_operations      *snapops;
+       struct snap_cache               *cache;
+       int                             tableno , index, i, count, rc;
+       
+       if (!(cache = snap_find_cache((kdev_t)data->dev)))
+               RETURN(-ENODEV);
+
+       snapops = filter_c2csnapops(cache->cache_filter);
+       if (!snapops || !snapops->set_meta_attr)
+               RETURN(-EINVAL);
+
+       tableno = data->tblcmd_no;
        if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-               printk(__FUNCTION__ ": invalid table number %d\n", tableno);
-               EXIT;
-               return -EINVAL;
+               CERROR("invalid table number %d\n", tableno);
+               RETURN(-EINVAL);
        }
        table = &snap_tables[tableno];  
+       count = table->tbl_count;
+
+       /* XXX Is down this sema necessary*/
+       down_interruptible(&table->tbl_sema);
+
+       /*add item in snap_table*/
+       table->snap_items[count+1].gen = table->generation;
+       table->snap_items[count+1].time = CURRENT_TIME;
+       /* find table index */
+       index = get_index_of_item(table);
+       if (index < 0)
+               RETURN(-EINVAL);
+
+       table->snap_items[count+1].index = index;
+       table->snap_items[count+1].flags = 0;
+       memcpy(&table->snap_items[count + 1].name[0], 
+              &data->tblcmd_snaps[0].name[0], SNAP_MAX_NAMELEN);
+       /* we will write the whole snap_table to disk */
+       SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
+       if (!disk_snap_table)
+               RETURN(-ENOMEM);
+       disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC);
+       disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count);
+       disk_snap_table->generation = cpu_to_le32((__u32)table->generation);
+       memset(&disk_snap_table->snap_items[0], 0, 
+              SNAP_MAX * sizeof(struct snap_disk));
+       for (i = 1; i <= count; i++) {
+               struct snap *item = &table->snap_items[i];
+               disk_snap_table->snap_items[i].time = cpu_to_le64((__u64)item->time);
+               disk_snap_table->snap_items[i].gen = cpu_to_le32((__u32)item->gen);
+               disk_snap_table->snap_items[i].flags = cpu_to_le32((__u32)item->flags);
+               disk_snap_table->snap_items[i].index = cpu_to_le32((__u32)item->index);
+               memcpy(&disk_snap_table->snap_items[i].name , item->name, SNAP_MAX_NAMELEN);
+       }
+       rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
+                                   (char*)disk_snap_table, sizeof(struct snap_disk_table));
+
+       SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
+       table->tbl_count++;
+       table->generation++;
+       
+       up(&table->tbl_sema);
+       
+       return 0;
+}
 
-       /* for each index that is used by the current table
-          we need to make sure that the new table we are about
-          to put in contains that index too 
-       */
-       for ( i = 0; i < SNAP_MAX ; i++ ) {
-               int foundit;
-               int err;
-
-               if ((err = snap_is_used(tableno, i)) < 0 ) {
-                       printk(__FUNCTION__  ": table %d not used\n", tableno);
-                       EXIT;
-                       return -EINVAL;
-               } else if (err == 0) {
-                       continue;
-               }
+static int delete_inode(struct inode *primary, void *param)
+{
+       struct snap_iterdata * data;
+       int tableno = 0;
+       int index = 0;
+       int rc = 0;
 
-               foundit = 0;
-               for (j = 0 ; j<= data->tblcmd_count ; j++) {
-                       if ( i == data->tblcmd_snaps[j].index ) {
-                               foundit = 1;
-                               break;
-                       }
-               }
-               if ( !foundit ) {
-                       printk(__FUNCTION__ ": index %d not in table %d\n", 
-                              i, tableno);
-                       return -EINVAL;
-               }
-       }
+       struct inode *redirect;
+       ino_t old_ind = 0;
+       struct snap_table *table;
+       int slot;
+       int delete_slot;
+       int this_index;
+       struct inode *next_ind = NULL;
+       int my_table[SNAP_MAX];
 
-       /* we must have:
-           - valid indices 
-          - a current snapshot in the table 
-          - increasing snapshot times 
-       */
-//     found_current = 0;
-       CDEBUG(D_SNAP, "snaplist: tblcmd_count %d\n", data->tblcmd_count);
-       for (i = 0 ; i < data->tblcmd_count ; i++) {
-
-               if ( (data->tblcmd_snaps[i].index < 0) ||
-                    (data->tblcmd_snaps[i].index >= SNAP_MAX) ) {
-                       printk(__FUNCTION__ ": snap_index out of range!\n");
-                       return -EINVAL;
-               }
+       if(!primary) return 0;
 
-               if (i>0 && data->tblcmd_snaps[i].time <= 
-                   data->tblcmd_snaps[i-1].time) {
-                       printk(__FUNCTION__ ": times not increasing\n");
-                       return -EINVAL;
-               }
+       data = (struct snap_iterdata*) param;
 
-//             if ( 0 == data->tblcmd_snaps[i].time ) {
-//                     found_current = 1;
-//                     break;
-//             }
+       if(data) {
+               index = data->index;
+               tableno = data->tableno;
        }
-//     if ( !found_current ) {
-//             printk(__FUNCTION__ "no current snapshot in table\n");
-//             return -EINVAL;
-//     }
-
-       /* ready to go: over write the table */
-/*     
-       for (i = 0 ; i < data->tblcmd_count ; i++) {
-
-               table->tbl_times[i] = data->tblcmd_snaps[i].time;
-               table->tbl_index[i] = data->tblcmd_snaps[i].index;
-               memcpy(table->tbl_name[i], data->tblcmd_snaps[i].name, 
-                       SNAP_MAX_NAMELEN);
-               table->tbl_name[i][SNAP_MAX_NAMELEN - 1] = '\0';
 
-               CDEBUG(D_SNAP, "snaplist: i %d, time %ld, idx %d, name %s\n",
-                      i, table->tbl_times[i], table->tbl_index[i], 
-                       table->tbl_name[i]);
-       }
-*/
-       /* below : new, we don't need current snapshot for data
-        * current snapshot always has slot 0, index 0, name "current" 
-        */
-       table->tbl_times[0] = 0;
-       table->tbl_index[0] = 0;
-       strcpy(table->tbl_name[0], "current");
+       CDEBUG(D_INODE, "delete_inode ino %lu, index %d\n", primary->i_ino, index);
 
-       i=0;    
-       CDEBUG(D_SNAP, "snaplist: i %d, time %ld, idx %d, name %s\n",
-              i, table->tbl_times[i], table->tbl_index[i], 
-               table->tbl_name[i]);
+       table = &snap_tables[tableno];
 
-       for (i = 0 ; i < data->tblcmd_count ; i++) {
+       redirect = snap_get_indirect(primary, NULL, index);
 
-               table->tbl_times[i+1] = data->tblcmd_snaps[i].time;
-               table->tbl_index[i+1] = data->tblcmd_snaps[i].index;
-               memcpy(table->tbl_name[i+1], data->tblcmd_snaps[i].name, 
-                       SNAP_MAX_NAMELEN);
-               table->tbl_name[i+1][SNAP_MAX_NAMELEN - 1] = '\0';
+       if(!redirect)   
+               return 0;
 
-               CDEBUG(D_SNAP, "snaplist: i %d, time %ld, idx %d, name %s\n",
-                      i+1, table->tbl_times[i+1], table->tbl_index[i+1], 
-                       table->tbl_name[i+1]);
+       old_ind = redirect->i_ino;
+       iput(redirect);
+       slot = snap_index2slot(table, index) - 1;
+       if( slot > 0 ) {
+               this_index = table->snap_items[slot].index;
+               redirect = snap_get_indirect(primary, NULL, this_index);
+               if(redirect)    
+                       iput(redirect);
+               else  {
+                       snap_set_indirect(primary, old_ind, this_index, 0);
+                       snap_set_indirect(primary, 0, index, 0);
+                       return 0;
+               }
+       }
+
+       /* get the FIRST index after this and before NOW */
+       /* used for destroy_indirect and block level cow */
+       /* XXX fix this later, now use tbl_count, not NOW */
+       delete_slot = snap_index2slot(table, index);
+       for(slot = table->tbl_count; slot > delete_slot; slot --)
+       {
+               my_table[slot - delete_slot] = table->snap_items[slot].index;
+       }
+       next_ind = snap_get_indirect 
+               (primary, my_table, table->tbl_count - delete_slot );
+       if( next_ind && (next_ind->i_ino == primary->i_ino) ) {
+               iput(next_ind);
+               next_ind = NULL;
        }
 
-       for ( i = data->tblcmd_count + 1 ; i < SNAP_MAX ; i++ ) {
-               table->tbl_times[i] = 0;
-               table->tbl_index[i] = 0;
-               memset(table->tbl_name[i], 0, SNAP_MAX_NAMELEN);
+       if( next_ind && (next_ind->i_ino == old_ind) ) {
+               iput(next_ind);
+               next_ind = NULL;
        }
 
-       /* set the table count */
-//     table->tbl_count = data->tblcmd_count;
-       table->tbl_count = data->tblcmd_count + 1;
+       rc = snap_destroy_indirect(primary, index, next_ind);
+
+       if(next_ind)    iput(next_ind);
+
+       if(rc != 0)     
+               CERROR("snap_destroy_indirect(ino %lu,index %d),ret %d\n",
+                       primary->i_ino, index, rc);
        return 0;
 }
 
+static int snap_delete(struct super_block *sb, struct snap_iterdata *data)
+{
+       CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
+               data->dev, data->tableno, data->index, data->time );
 
-int snap_table_attach(int tableno, int snap_index) 
+       snap_iterate(sb, &delete_inode, NULL, data, SNAP_ITERATE_COWED_INODE);
+       
+       return 0;
+}
+
+/* This function will delete one item(a snapshot) in the snaptable  
+ * and will also delete the item in the disk.
+ */
+int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
 {
-       struct snap_table *table;
+       struct snap_table               *table;
+       struct snap_disk_table          *disk_snap_table;
+       struct snapshot_operations      *snapops;
+       struct snap_cache               *cache;
+       int                             tableno = data->tableno, index, i, slot, rc, count;
+       
+       if (!(cache = snap_find_cache((kdev_t)data->dev)))
+               RETURN(-ENODEV);
+
+       snapops = filter_c2csnapops(cache->cache_filter);
+       if (!snapops || !snapops->set_meta_attr)
+               RETURN(-EINVAL);
+
+       if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
+               CERROR("invalid table number %d\n", tableno);
+               RETURN(-EINVAL);
+       }
+       /*first delete the snapshot
+        * FIXME if snap delete error, how to handle this error*/
+       rc = snap_delete(sb, data);
+       if (rc) 
+               RETURN(-EINVAL);
+       /*delete item in snaptable */
+       table = &snap_tables[tableno];
+       index = data->index;
 
-       if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-               printk(__FUNCTION__ ": invalid table number %d\n", tableno);
-               EXIT;
-               return -EINVAL;
+       slot = snap_index2slot(table, index);
+       if (slot < 0)
+               RETURN(-EINVAL);
+
+       down_interruptible(&table->tbl_sema);
+       while(slot < table->tbl_count) {
+               struct snap *item = &table->snap_items[slot];
+               item->time = table->snap_items[slot + 1].time;
+               item->flags = table->snap_items[slot + 1].flags;
+               item->gen = table->snap_items[slot + 1].gen;
+               item->index = table->snap_items[slot + 1].index;
+               memcpy(&item->name[0], &table->snap_items[slot + 1].name[0],
+                       SNAP_MAX_NAMELEN);
        }
-       table = &snap_tables[tableno];  
+
+       table->tbl_count --;
        
-       if ( snap_index2slot(table, snap_index) < 0 ) {
-               printk(__FUNCTION__ ": snap index %d not present in table %d\n",
-                      snap_index, tableno);
-               return -EINVAL;
+       SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
+
+       if (!disk_snap_table)
+               RETURN(-ENOMEM);
+       /* we will delete the item  snap_table to disk */
+       
+       disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC);
+       disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count);
+       disk_snap_table->generation = cpu_to_le32((__u32)table->generation);
+       memset(&disk_snap_table->snap_items[0], 0, 
+              SNAP_MAX * sizeof(struct snap_disk));
+
+       count = table->tbl_count;
+
+       for (i = 1; i <= count; i++) {
+               struct snap *item = &table->snap_items[i];
+               disk_snap_table->snap_items[i].time = cpu_to_le64((__u64)item->time);
+               disk_snap_table->snap_items[i].gen = cpu_to_le32((__u32)item->gen);
+               disk_snap_table->snap_items[i].flags = cpu_to_le32((__u32)item->flags);
+               disk_snap_table->snap_items[i].index = cpu_to_le32((__u32)item->index);
+               memcpy(&disk_snap_table->snap_items[i].name , item->name, SNAP_MAX_NAMELEN);
+       }
+       rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
+                                   (char*)disk_snap_table, sizeof(struct snap_disk_table));
+
+       SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
+       
+       up(&table->tbl_sema);
+       
+       RETURN(0);
+}
+
+int snapfs_read_snaptable(struct snap_cache *cache, int tableno)
+{
+       struct snap_table               *table;
+       struct snap_disk_table          *disk_snap_table;
+       struct snapshot_operations      *snapops;
+       int                             i, rc;
+       int                             size = 0;
+
+       
+       snapops = filter_c2csnapops(cache->cache_filter);
+       if (!snapops || !snapops->get_meta_attr)
+               RETURN(-EINVAL);
+       
+       SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
+
+       size = sizeof(struct snap_disk_table);
+
+       rc = snapops->get_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
+                              (char*)disk_snap_table, &size);
+       if (rc < 0) {
+               SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
+               RETURN(rc);
        }
+       table = &snap_tables[tableno];
 
-       snap_use(tableno, snap_index);
+       if (le32_to_cpu(disk_snap_table->magic) != DISK_SNAP_TABLE_MAGIC) {
+               CERROR("On disk snaptable is not right \n");
+               RETURN(rc);
+       }
+       table->generation = le32_to_cpu(disk_snap_table->generation);
+       table->tbl_count = le32_to_cpu(disk_snap_table->count);
+       for ( i = 0; i < disk_snap_table->count; i++) {
+               struct snap *item = &table->snap_items[i + 1];
+               item->time = le64_to_cpu(disk_snap_table->snap_items[i].time);
+               item->gen = le32_to_cpu(disk_snap_table->snap_items[i].gen);
+               item->flags = le32_to_cpu(disk_snap_table->snap_items[i].flags);
+               item->index = le32_to_cpu(disk_snap_table->snap_items[i].index);
+               memcpy(&item->name[0], &disk_snap_table->snap_items[i].name[0],
+                      SNAP_MAX_NAMELEN);
+       }
+       SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
        return 0;
 }
 
@@ -450,16 +495,16 @@ static int getdata(int len, void **data)
                return 0;
        }
 
-       SNAP_ALLOC(tmp, void *, len);
+       SNAP_ALLOC(tmp, len);
        if ( !tmp )
                return -ENOMEM;
 
-       CDEBUG(D_MALLOC, "snap_alloc:len %d, add %p\n", len, tmp);
+       CDEBUG(D_SNAP, "snap_alloc:len %d, add %p\n", len, tmp);
 
        memset(tmp, 0, len);
        if ( copy_from_user(tmp, *data, len)) {
                SNAP_FREE(tmp, len);
-               CDEBUG(D_MALLOC, "snap_free:len %d, add %p\n", len, tmp);
+               CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", len, tmp);
                return -EFAULT;
        }
        *data = tmp;
@@ -469,7 +514,7 @@ static int getdata(int len, void **data)
 
 static void freedata(void *data, int len) {
        SNAP_FREE(data, len);
-       CDEBUG(D_MALLOC, "snap_free:len %d, add %p\n", len, data);
+       CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", len, data);
 }
 
 static int get_next_inode(struct inode *pri, void *ino)
@@ -527,7 +572,7 @@ static int snap_get_next_inode(struct snap_ino_list_data *data, ino_t *found_ino
        *parent_ino = 0;
        inode = iget (cache->cache_sb, *found_ino);
        if (list_empty(&inode->i_dentry)) {
-               printk("No dentry for ino %lu, Error(XXX)! \n", inode->i_ino);
+               CERROR("No dentry for ino %lu, Error(XXX)! \n", inode->i_ino);
                iput(inode);    
                        return 0;
        }
@@ -544,35 +589,6 @@ static int snap_get_next_inode(struct snap_ino_list_data *data, ino_t *found_ino
 
        return 0;
 }
-/*
-static int snap_get_inode_info(struct snap_ino_list_data *data,  int index)
-{
-       kdev_t dev = data->dev;
-       ino_t pri = data->ino; 
-       int index = data->index;
-
-       struct snap_cache *cache;
-
-       struct inode *pri;
-       struct inode *ind;
-       ino_t ind_ino = 0;
-
-       ENTRY;
-
-       cache = snap_find_cache(dev); 
-       if ( !cache ) {
-                EXIT;
-                return -EINVAL;
-        }
-       pri = iget(cache->cache->sb, pri_ino);
-       ind = snap_get_indirect(pri, NULL, index);
-       if(ind) {
-               ind_ino = ind->i_ino;   
-               iput(ind);
-       }
-       return ind_ino;
-}
-*/
 
 static int print_inode(struct inode *pri,void *param)
 {
@@ -586,94 +602,6 @@ static int snap_print(struct super_block *sb, void *data)
        return 0;
 }
 
-static int delete_inode(struct inode *primary, void *param)
-{
-       struct snap_iterdata * data;
-       int tableno = 0;
-       int index = 0;
-       int rc = 0;
-
-       struct inode *redirect;
-       ino_t old_ind = 0;
-       struct snap_table *table;
-       int slot;
-       int delete_slot;
-       int this_index;
-       struct inode *next_ind = NULL;
-       int my_table[SNAP_MAX];
-
-       if(!primary) return 0;
-
-       data = (struct snap_iterdata*) param;
-
-       if(data) {
-               index = data->index;
-               tableno = data->tableno;
-       }
-
-       printk("delete_inode ino %lu, index %d\n", primary->i_ino, index);
-
-       table = &snap_tables[tableno];
-
-       redirect = snap_get_indirect(primary, NULL, index);
-
-       if(!redirect)   
-               return 0;
-
-       old_ind = redirect->i_ino;
-       iput(redirect);
-       slot = snap_index2slot(table, index) - 1;
-       if( slot > 0 ) {
-               this_index = table->tbl_index[slot];
-               redirect = snap_get_indirect(primary, NULL, this_index);
-               if(redirect)    
-                       iput(redirect);
-               else  {
-                       snap_set_indirect(primary, old_ind, this_index, 0);
-                       snap_set_indirect(primary, 0, index, 0);
-                       return 0;
-               }
-       }
-
-       /* get the FIRST index after this and before NOW */
-       /* used for destroy_indirect and block level cow */
-       /* XXX fix this later, now use tbl_count, not NOW */
-       delete_slot = snap_index2slot(table, index);
-       for(slot = table->tbl_count; slot > delete_slot; slot --)
-       {
-               my_table[slot - delete_slot] = table->tbl_index[slot];
-       }
-       next_ind = snap_get_indirect 
-               (primary, my_table, table->tbl_count - delete_slot );
-       if( next_ind && (next_ind->i_ino == primary->i_ino) ) {
-               iput(next_ind);
-               next_ind = NULL;
-       }
-
-       if( next_ind && (next_ind->i_ino == old_ind) ) {
-               iput(next_ind);
-               next_ind = NULL;
-       }
-
-       rc = snap_destroy_indirect(primary, index, next_ind);
-
-       if(next_ind)    iput(next_ind);
-
-       if(rc != 0)     
-               printk("ERROR:snap_destroy_indirect(ino %lu,index %d),ret %d\n",                        primary->i_ino, index, rc);
-       return 0;
-}
-
-static int snap_delete(struct super_block *sb, struct snap_iterdata *data)
-//static int snap_delete(struct super_block *sb, void *data)
-{
-       CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
-               data->dev, data->tableno, data->index, data->time );
-
-       snap_iterate(sb,&delete_inode,NULL, data, SNAP_ITERATE_COWED_INODE);
-       return 0;
-}
-
 static int delete_new_inode(struct inode *pri, void *param)
 {
        struct snap_iterdata * data;
@@ -706,7 +634,6 @@ static int delete_new_inode(struct inode *pri, void *param)
 
                CDEBUG(D_SNAP, "snap_restore ino %lu is newer, delete \n",pri->i_ino);
                for( pos = head->next; pos != head; pos = pos->next ){
-//                     d_invalidate( list_entry(pos, struct dentry, d_alias) );
                        d_drop( list_entry(pos, struct dentry, d_alias) );
                }
                pri->i_nlink = 0;
@@ -728,7 +655,6 @@ static int restore_inode(struct inode *pri, void *param)
        int slot;
        int restore_slot;
        struct snap_table *table;
-//     int my_table[SNAP_MAX];
        int restore_index;
        
        ENTRY; 
@@ -760,33 +686,18 @@ static int restore_inode(struct inode *pri, void *param)
                        for(slot = restore_slot; slot <= table->tbl_count; 
                            slot++) {
                                ind = snap_get_indirect (pri, NULL, 
-                                       table->tbl_index[slot]);
+                                       table->snap_items[slot].index);
                                if(ind) {
-                                       restore_index = table->tbl_index[slot];
+                                       restore_index = table->snap_items[slot].index;
                                        break;
                                }
                        }
-/*                     for(slot = table->tbl_count; slot >= restore_slot; 
-                               slot --)
-                       {
-                               my_table[slot - restore_slot + 1] = 
-                                       table->tbl_index[slot];
-                       }
-                       ind = snap_get_indirect (pri, my_table, 
-                                       table->tbl_count - restore_slot + 1);
-
-                       if( ind && (ind->i_ino == pri->i_ino) ) {
-                               iput(ind);
-                               ind =  NULL;
-                       }
-*/
                }
 
                if(ind) {
                        CDEBUG(D_SNAP, "restore ino %lu with index %d\n",
                                        pri->i_ino, restore_index);
                        iput(ind);
-//                     snap_restore_indirect(pri, index);
                        snap_restore_indirect(pri, restore_index);
                        /* XXX */
                        //delete_inode(pri, param);
@@ -797,7 +708,7 @@ static int restore_inode(struct inode *pri, void *param)
                }
        }
        else {
-               printk("ino %lu is older, don't restore\n",pri->i_ino);
+               CDEBUG(D_SNAP, "ino %lu is older, don't restore\n", pri->i_ino);
        }
        EXIT;
        return 0;
@@ -821,21 +732,16 @@ int snap_get_index_from_name(int tableno, char *name)
        int slot;
 
        if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-               printk(__FUNCTION__ ": invalid table number %d\n", tableno);
+               CDEBUG(D_SNAP, ": invalid table number %d\n", tableno);
                return -EINVAL;
        }
 
        table = &snap_tables[tableno];
 
        for ( slot = 0 ; slot < SNAP_MAX ; slot++ ) {
-/*             if(memcmp (table->tbl_name[slot], name, 
-                       strlen(table->tbl_name[slot]) ) == 0 ) {
-                       return table->tbl_index[slot];
-               }
-*/
-               if(strncmp (table->tbl_name[slot], name, 
+               if(strncmp (&table->snap_items[slot].name[0], name, 
                        SNAP_MAX_NAMELEN) == 0 ) {
-                       return table->tbl_index[slot];
+                       return table->snap_items[slot].index;
                }
        }
        return -EINVAL;
@@ -844,27 +750,20 @@ int snap_get_index_from_name(int tableno, char *name)
 int snap_iterate_func(int len, struct snap_ioc_data *ioc_data, unsigned int cmd)
 {
        struct snap_iterdata data;
-
-       kdev_t dev ;
-       char name[SNAP_MAX_NAMELEN];
-
-       int index ;
-       int tableno; 
-       int name_len;
-       int slot;
-
        struct super_block *sb;
        struct snap_cache *cache;
        struct snap_table *table;
+       char name[SNAP_MAX_NAMELEN];
+       int index, tableno, name_len, slot, rc;
+       
+       kdev_t dev ;
 
        ENTRY;
 
        dev = ioc_data->dev;
        cache = snap_find_cache(dev); 
-       if ( !cache ) {
-                EXIT;
-                return -EINVAL;
-        }
+       if ( !cache ) 
+                RETURN(-EINVAL);
 
        sb = cache->cache_sb;
        tableno = cache->cache_snap_tableno;
@@ -877,41 +776,37 @@ int snap_iterate_func(int len, struct snap_ioc_data *ioc_data, unsigned int cmd)
        if(name_len < 0 ) 
                name_len = 0;
        memcpy(name, ioc_data->name, name_len);
-       if ( (index = snap_get_index_from_name (tableno, name)) < 0 ) {
-               EXIT;
-               return -EINVAL;
-       }
+       
+       if ((index = snap_get_index_from_name (tableno, name)) < 0) 
+               RETURN(-EINVAL);
        
        data.dev = dev;
        data.index = index;
        data.tableno = tableno;
        slot = snap_index2slot (table, index);
-       if( slot < 0 ) {
-               EXIT;
-               return -EINVAL;
-       }
-       data.time = table->tbl_times[slot];
-
+       if( slot < 0 ) 
+               RETURN(-EINVAL);
+       
+       data.time = table->snap_items[slot].time;
        CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
                data.dev, data.tableno, data.index, data.time );
 
        switch (cmd) {
                case IOC_SNAP_DEBUG:
-                       snap_print(sb, &data);  
+                       rc = snap_print(sb, &data);     
                        break;
                case IOC_SNAP_DELETE:
-                       snap_delete(sb, &data); 
+                       rc = snaptable_delete_item(sb, &data);  
                        break;
                case IOC_SNAP_RESTORE:
-                       snap_restore(sb, &data);        
+                       rc = snap_restore(sb, &data);   
                        break;
                default:
-                       return -EINVAL;
+                       CERROR("unrecognized cmd %d \n", cmd);
+                       rc = -EINVAL;
+                       break;
        }
-       
-       EXIT;
-
-       return 0;
+       RETURN(0);
 }
 
 int snap_ioctl (struct inode * inode, struct file * filp, 
@@ -941,10 +836,12 @@ int snap_ioctl (struct inode * inode, struct file * filp,
         if ( _IOC_TYPE(cmd) != IOC_SNAP_TYPE || 
              _IOC_NR(cmd) < IOC_SNAP_MIN_NR  || 
              _IOC_NR(cmd) > IOC_SNAP_MAX_NR ) {
-                CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
+                /*FIXME: Sometimes Gettimeof the day will come here
+                * Do not know the reason*/
+               CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
                                 _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
                 EXIT;
-                return -EINVAL;
+                return 0;
         }
 
        /* get data structures */
@@ -964,8 +861,8 @@ int snap_ioctl (struct inode * inode, struct file * filp,
        }
        
        switch (cmd) {
-       case IOC_SNAP_SETTABLE:
-               rc = snap_install_table(len, karg);
+       case IOC_SNAP_ADD:
+               rc = snaptable_add_item(karg);
                break;
        case IOC_SNAP_PRINTTABLE: {
                struct output_data{
@@ -1064,9 +961,11 @@ int snap_ioctl (struct inode * inode, struct file * filp,
        case IOC_SNAP_DEBUG:
                rc = snap_iterate_func(len, karg, cmd);
                break;
+#ifdef SNAP_DEBUG
        case IOC_SNAP_DEVFAIL:
                snap_debug_failcode = (unsigned int)arg;
                break;
+#endif
        case IOC_SNAP_SHOW_DOTSNAP: {
                struct ioc_show_info{
                        kdev_t dev;
index f101977..e4b4ef8 100644 (file)
@@ -8,43 +8,22 @@
  *
  *  Author: Peter J. Braam <braam@mountainviewdata.com>
  */
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#include <stdarg.h>
-
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/dcache.h>
-
-#ifdef CONFIG_SNAPFS_EXT2
-#include <linux/ext2_fs.h>
-#endif
-#ifdef CONFIG_SNAPFS_EXT3
-#include <linux/ext3_fs.h>
-#endif
-
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/blkdev.h>
-#include <linux/init.h>
-#define __NO_VERSION__
-#include <linux/module.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+#include <linux/errno.h>
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
 #ifdef SNAP_DEBUG
-long snap_vmemory = 0;
-long snap_kmemory = 0;
 unsigned int snap_debug_failcode = 0;
 #endif
 
@@ -54,15 +33,16 @@ extern inline void snap_init_cache_hash(void);
 
 extern int snap_get_index_from_name (int tableno, char *name);
 
-#ifdef CONFIG_SNAPFS_EXT2
-extern struct snapshot_operations ext2_snap_operations;
-extern struct journal_ops snap_ext2_journal_ops;
-#endif
 
-#ifdef CONFIG_SNAPFS_EXT3
 extern struct snapshot_operations ext3_snap_operations;
 extern struct journal_ops snap_ext3_journal_ops;
-#endif
+                                                                                                                                                                                                     
+static void put_filesystem(struct file_system_type *fs)
+{
+       if (fs->owner)
+               __MOD_DEC_USE_COUNT(fs->owner);
+}
+
 
 /* returns an allocated string, copied out from data if opt is found */
 static char *read_opt(const char *opt, char *data)
@@ -78,9 +58,9 @@ static char *read_opt(const char *opt, char *data)
                return NULL;
 
        value++;
-       SNAP_ALLOC(retval, char *, strlen(value) + 1);
+       SNAP_ALLOC(retval, strlen(value) + 1);
        if ( !retval ) {
-               printk("snapfs: Out of memory!\n");
+               CERROR("snapfs: Out of memory!\n");
                return NULL;
        }
 
@@ -114,15 +94,15 @@ static char *snapfs_options(char *options, char *cache_data,
 
        /* set the defaults here */
        if (cache_type && !*cache_type) {
-               SNAP_ALLOC(*cache_type, char *, strlen("ext2") + 1);
-               strcpy(*cache_type, "ext2");
+               SNAP_ALLOC(*cache_type, strlen("ext3") + 1);
+               strcpy(*cache_type, "ext3");
        }
        if (cow_type && !*cow_type) {
-               SNAP_ALLOC(*cow_type, char *, strlen("block") + 1);
+               SNAP_ALLOC(*cow_type, strlen("block") + 1);
                strcpy(*cow_type, "block");
        }
        if (snaptable && !*snaptable) {
-               SNAP_ALLOC(*snaptable, char *, strlen("-1")+1);
+               SNAP_ALLOC(*snaptable, strlen("-1")+1);
                strcpy(*snaptable, "-1");
        }
 
@@ -167,25 +147,18 @@ int snapfs_remount(struct super_block * sb, int *flags, char *data)
        int err = 0;
 
        ENTRY;
-       CDEBUG(D_MALLOC, "before remount: kmem %ld, vmem %ld\n",
-              snap_kmemory, snap_vmemory);
        CDEBUG(D_SUPER, "remount opts: %s\n", data ? (char *)data : "(none)");
        if (data) {
                /* reserve space for the cache's data */
-               SNAP_ALLOC(cache_data, void *, PAGE_SIZE);
-               if ( !cache_data ) {
-                       err = -ENOMEM;
-                       EXIT;
-                       goto out_err;
-               }
+               SNAP_ALLOC(cache_data, PAGE_SIZE);
+               if ( !cache_data ) 
+                       GOTO(out_err, err = -ENOMEM);
        }
 
        cache = snap_find_cache(sb->s_dev);
        if (!cache) {
-               printk(__FUNCTION__ ": cannot find cache on remount\n");
-               err = -ENODEV;
-               EXIT;
-               goto out_err;
+               CERROR("cannot find cache on remount\n");
+               GOTO(out_err, err = -ENODEV);
        }
 
        /* If an option has not yet been set, we allow it to be set on
@@ -211,8 +184,6 @@ int snapfs_remount(struct super_block * sb, int *flags, char *data)
                err = sops->remount_fs(sb, flags, cache_data);
        }
 
-       CDEBUG(D_MALLOC, "after remount: kmem %ld, vmem %ld\n",
-              snap_kmemory, snap_vmemory);
        EXIT;
 out_err:
        if (cache_data)
@@ -251,15 +222,12 @@ snapfs_read_super (
        int tableno;
 
        ENTRY;
-       CDEBUG(D_MALLOC, "before parsing: kmem %ld, vmem %ld\n",
-              snap_kmemory, snap_vmemory);
 
        /* reserve space for the cache's data */
-       SNAP_ALLOC(cache_data, void *, PAGE_SIZE);
+       SNAP_ALLOC(cache_data, PAGE_SIZE);
        if ( !cache_data ) {
-               printk("snapfs_read_super: Cannot allocate data page.\n");
-               EXIT;
-               goto out_err;
+               CERROR("snapfs_read_super: Cannot allocate data page.\n");
+               GOTO(out_err, 0);
        }
 
        CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
@@ -281,20 +249,21 @@ snapfs_read_super (
        /* set up the cache */
        cache = snap_init_cache();
        if ( !cache ) {
-               printk("snapfs_read_super: failure allocating cache.\n");
-               EXIT;
-               goto out_err;
+               CERROR("snapfs_read_super: failure allocating cache.\n");
+               GOTO(out_err, 0);
        }
 
        fstype = get_fs_type(cache_type);
        if ( !fstype || !fstype->read_super) {
-               EXIT;
-               goto out_err;
+               GOTO(out_err, 0);
        }
        
        cache->cache_filter = filter_get_filter_fs((const char *)cache_type); 
-       /* XXX if cache->cache_filter==NULL?although it's rare ***/
-
+       
+       if (!cache->cache_filter) {
+               CERROR("Unrecognized cache type %s \n", cache_type);
+               GOTO(out_err, 0);
+       }
 
        /*
          * Read the underlying file system superblock - ext2, ext3, reiser.
@@ -303,20 +272,12 @@ snapfs_read_super (
          *
          * Note: It's assumed that sb is always returned.
          */
-       CDEBUG(D_SUPER, "\n");
        if (fstype->read_super(sb, cache_data, silent) != sb) {
-               printk("snapfs: cache mount failure.\n");
-               EXIT;
-               goto out_err;
+               CERROR("snapfs: cache mount failure.\n");
+               GOTO(out_err, 0);
         }
 
-       /* XXX now look at the flags in the superblock and determine if this 
-              is a block cow file system or a file cow fs.  Then assign the 
-              snap operations accordingly.  This goes in the sections for ext2/ext3/xfs etc
-        */ 
-
        /* this might have been freed above */
-       CDEBUG(D_SUPER, "\n");
        if (cache_data) {
                SNAP_FREE(cache_data, PAGE_SIZE);
                cache_data = NULL;
@@ -329,14 +290,13 @@ snapfs_read_super (
          * 'cache' is the struct snap_cache allocated for this
          * snapfs mount.
          */
-       CDEBUG(D_SUPER, "\n");
        snap_cache_add(cache, sb->s_dev);
 
        tableno  =  simple_strtoul(snapno, &endptr, 0);
        cache->cache_snap_tableno = tableno;
 
-       CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno);
 
+       CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno);
        /*
          * make sure we have our own super operations
          *
@@ -344,10 +304,8 @@ snapfs_read_super (
          * struct snap_ops structure set based on the underlying
          * file system type.
          */
-       CDEBUG(D_SUPER, "\n");
        filter_setup_super_ops(cache->cache_filter, sb->s_op,
                               &currentfs_super_ops);
-       CDEBUG(D_SUPER, "\n");
        sb->s_op = filter_c2usops(cache->cache_filter); 
         /*
          * Save pointers in the snap_cache structure to the
@@ -358,25 +316,6 @@ snapfs_read_super (
        /* set up snapshot ops, handle COMPAT_FEATUREs */
        if( 0 ){
        }
-#ifdef CONFIG_SNAPFS_EXT2
-       else if ( strcmp (cache_type,"ext2") == 0 ){
-               cache->cache_type = FILTER_FS_EXT2;
-               filter_setup_snapshot_ops(cache->cache_filter, 
-                                       &ext2_snap_operations);
-               filter_setup_journal_ops(cache->cache_filter,
-                                       &snap_ext2_journal_ops);
-               if( !EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_SNAPFS) ){
-                       if( strcmp(cow_type, "block")==0 ){
-                               sb->u.ext2_sb.s_feature_compat |=
-                                       EXT2_FEATURE_COMPAT_BLOCKCOW;
-                               sb->u.ext2_sb.s_es->s_feature_compat |=
-                                       cpu_to_le32(EXT2_FEATURE_COMPAT_BLOCKCOW);
-                       }
-               }
-                sb->u.ext2_sb.s_last_cowed_ino = 0;
-       }
-#endif
-#ifdef CONFIG_SNAPFS_EXT3
        else if ( strcmp (cache_type,"ext3") == 0 ){
                cache->cache_type = FILTER_FS_EXT3;
                filter_setup_snapshot_ops(cache->cache_filter,
@@ -389,37 +328,32 @@ snapfs_read_super (
                                        cpu_to_le32(EXT3_FEATURE_COMPAT_BLOCKCOW);
                        }
                }
-               sb->u.ext3_sb.s_last_cowed_ino = 0;
+               sb->u.ext3_sb.s_last_cowed_pri_ino = 0;
+               sb->u.ext3_sb.s_first_cowed_pri_ino = 0;
        }
-#endif
-
-       CDEBUG(D_SUPER, "\n");
        /* now get our own directory operations */
        if ( sb->s_root && sb->s_root->d_inode ) {
-               CDEBUG(D_SUPER, "\n");
                filter_setup_dir_ops(cache->cache_filter, 
-                                    sb->s_root->d_inode->i_op,
-                                    &currentfs_dir_iops);
-               CDEBUG(D_SUPER, "\n");
+                                    sb->s_root->d_inode,
+                                    &currentfs_dir_iops, &currentfs_dir_fops);
                sb->s_root->d_inode->i_op =filter_c2udiops(cache->cache_filter);
-//     CDEBUG(D_SUPER, "\n");
-//             sb->s_root->d_inode->i_snapop = ext2_snapops();
 
                CDEBUG(D_SUPER, "lookup at %p\n", 
                       sb->s_root->d_inode->i_op->lookup);
-#if 0
-               /* XXX is this needed ?? */
+               /* XXX is this needed ?? ext3 do not have dentry operations*/
                filter_setup_dentry_ops(cache->cache_filter, 
                                        sb->s_root->d_op, 
                                        &currentfs_dentry_ops);
                sb->s_root->d_op = filter_c2udops(cache->cache_filter);
-#endif
        }
         /*
          * Save a pointer to the snap_cache structure in the
          * "snap_current" superblock.
          */
         (struct snap_cache *) sb->u.generic_sbp = cache;
+
+       snapfs_read_snaptable(cache, tableno);
+       
        CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
                 (ulong) sb, (ulong) sb->u.generic_sbp);
 
@@ -436,12 +370,10 @@ snapfs_read_super (
                SNAP_FREE(cow_type, strlen(cow_type) + 1);
                cow_type = NULL;
        }
+       /* Inc in get_fs_type, Dec in put_fs_type*/
 
-       CDEBUG(D_MALLOC, "after mounting: kmem %ld, vmem %ld\n",
-              snap_kmemory, snap_vmemory);
-
-       MOD_INC_USE_COUNT;
-       EXIT;
+       put_filesystem(fstype);
+       
        return sb;
 
  out_err:
@@ -456,19 +388,13 @@ snapfs_read_super (
                SNAP_FREE(cache_type, strlen(cache_type) + 1);
        if (cow_type)
                SNAP_FREE(cow_type, strlen(cow_type) + 1);
+       if (fstype)
+               put_filesystem(fstype);
 
-       CDEBUG(D_MALLOC, "mount error exit: kmem %ld, vmem %ld\n",
-              snap_kmemory, snap_vmemory);
        return NULL;
 }
 
-
-struct file_system_type snapfs_current_type = {
-       "snap_current",
-       FS_REQUIRES_DEV, /* can use Ibaskets when ext2 does */
-       snapfs_read_super,
-       NULL
-};
+static DECLARE_FSTYPE_DEV(snapfs_current_type, "snap_current", snapfs_read_super);
 
 
 /* Find the options for the clone. These consist of a cache device
@@ -510,19 +436,26 @@ static char *clonefs_options(char *options, char *cache_data,
 static int snapfs_path2dev(char *dev_path, kdev_t *dev)
 {
        struct dentry *dentry;
+       struct nameidata nd;
+       int error = 0;
+       
+       if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
+               error = path_walk(dev_path, &nd);
+               if (error)
+                       return error;
+       } else
+               return -EINVAL;
 
-       dentry = lookup_dentry(dev_path, NULL, 0);
-       if (IS_ERR(dentry))
-               return PTR_ERR(dentry);
+       dentry = nd.dentry;
 
-       if (!dentry->d_inode)
-               return -ENODEV;
-
-       if (!S_ISBLK(dentry->d_inode->i_mode))
+       if (!dentry->d_inode || !S_ISBLK(dentry->d_inode->i_mode) || 
+           is_bad_inode(dentry->d_inode) ) {
+               path_release(&nd);
                return -ENODEV;
+       }
 
        *dev = dentry->d_inode->i_rdev;
-
+       path_release(&nd);
        return 0;
 }
 
@@ -554,15 +487,12 @@ clone_read_super(
 
        ENTRY;
 
-       CDEBUG(D_MALLOC, "before parsing: kmem %ld, vmem %ld\n",
-              snap_kmemory, snap_vmemory);
 
        /* reserve space for the cache's data */
-       SNAP_ALLOC(cache_data, void *, PAGE_SIZE);
+       SNAP_ALLOC(cache_data, PAGE_SIZE);
        if ( !cache_data ) {
-               printk("clone_read_super: Cannot allocate data page.\n");
-               EXIT;
-               goto out_err;
+               CERROR("clone_read_super: Cannot allocate data page.\n");
+               GOTO(out_err, 0);
        }
 
        CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
@@ -575,29 +505,25 @@ clone_read_super(
                SNAP_FREE(cache_data, PAGE_SIZE);
                cache_data = NULL;
        } else {
-               printk("clonefs: invalid mount option %s\n", cache_data);
-               EXIT;
-               goto out_err;
+               CERROR("clonefs: invalid mount option %s\n", cache_data);
+               GOTO(out_err, 0);
        }
 
        if (!namestr || !devstr) {
-               printk("snapfs: mount options name and dev mandatory\n");
-               EXIT;
-               goto out_err;
+               CERROR("snapfs: mount options name and dev mandatory\n");
+               GOTO(out_err, 0);
        }
 
        err = snapfs_path2dev(devstr, &dev);
        if ( err ) {
-               printk("snap: incorrect device option %s\n", devstr);
-               EXIT;
-               goto out_err;
+               CERROR("snap: incorrect device option %s\n", devstr);
+               GOTO(out_err, 0);
        }
        
        snap_cache = snap_find_cache(dev);
        if ( !snap_cache ) {
-               printk("snap: incorrect device option %s\n", devstr);
-               EXIT;
-               goto out_err;
+               CERROR("snap: incorrect device option %s\n", devstr);
+               GOTO(out_err, 0);
        }
 
        /*index =  simple_strtoul(indexstr, &endptr, 0);
@@ -614,9 +540,8 @@ clone_read_super(
                        snap_cache->cache_snap_tableno, namestr, index);
 
        if(index < 0 ) {
-               printk("No valid index for name %s passed to mount\n",namestr); 
-               EXIT;
-               goto out_err;
+               CERROR("No valid index for name %s passed to mount\n",namestr); 
+               GOTO(out_err, 0);
        }
 
         /*
@@ -640,13 +565,13 @@ clone_read_super(
        CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
               sb->s_op->read_inode, root_ino, root_inode);
 
-       sb->s_root = d_alloc_root(root_inode, NULL);
+       sb->s_root = d_alloc_root(root_inode);
        if (!sb->s_root) {
                list_del(&clone_sb->clone_list_entry);
                sb = NULL;
        }
 
-       dget( snap_cache->cache_sb->s_root );
+       dget(snap_cache->cache_sb->s_root);
 
        if (cache_data)
                SNAP_FREE(cache_data, PAGE_SIZE);
@@ -656,39 +581,29 @@ clone_read_super(
                SNAP_FREE(namestr, strlen(namestr) + 1);
        CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
                 (ulong) sb, (ulong) &sb->u.generic_sbp);
-
-       MOD_INC_USE_COUNT;
-       EXIT;
        return sb;
  out_err:
-       CDEBUG(D_MALLOC, "mount error exit: kmem %ld, vmem %ld\n",
-              snap_kmemory, snap_vmemory);
        return NULL;
 }
 
-
-struct file_system_type snapfs_clone_type = {
-       "snap_clone",
-       0,
-       clone_read_super,
-       NULL
-};
-
+static DECLARE_FSTYPE(snapfs_clone_type, "snap_clone", clone_read_super, 0);
 
 int init_snapfs(void)
 {
        int status;
 
        snap_init_cache_hash();
+       init_filter_info_cache();
 
-       status = register_filesystem(&snapfs_current_type);
-       if (status) {
-               printk("snapfs: failed in register current filesystem!\n");
-       }
        status = register_filesystem(&snapfs_clone_type);
        if (status) {
                unregister_filesystem(&snapfs_current_type);
-               printk("snapfs: failed in register clone filesystem!\n");
+               CERROR("snapfs: failed in register clone filesystem!\n");
+       }
+
+       status = register_filesystem(&snapfs_current_type);
+       if (status) {
+               CERROR("snapfs: failed in register current filesystem!\n");
        }
        return status;
 }
@@ -701,14 +616,14 @@ int cleanup_snapfs(void)
 
        ENTRY;
 
+       cleanup_filter_info_cache();
        err = unregister_filesystem(&snapfs_clone_type);
        if ( err ) {
-               printk("snapfs: failed to unregister clone filesystem\n");
+               CERROR("snapfs: failed to unregister clone filesystem\n");
        }
        err = unregister_filesystem(&snapfs_current_type);
        if ( err ) {
-               printk("snapfs: failed to unregister filesystem\n");
+               CERROR("snapfs: failed to unregister filesystem\n");
        }
-
        return 0;
 }
index 41efbd1..cf4c99c 100644 (file)
@@ -4,26 +4,19 @@
  *  A snap shot file system.
  *
  */
+#define DEBUG_SUBSYSTEM S_SNAP
 
-#define EXPORT_SYMTAB
-
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
 static inline int inode_has_ea(struct inode *inode)
 {               
@@ -92,19 +85,17 @@ static int cat_str_ahead(char *buf, int pos, const char* str)
  * (1) we are not lies in .snap
  * (2) we are already in the root's .snap
  */
-static struct dentry * dotsnap_follow_link(struct dentry *base,
-                                          struct dentry *dentry,
-                                          int follow)
+static int dotsnap_follow_link(struct dentry *dentry,
+                                          struct nameidata *nd)
 {
        struct super_block *sb = dentry->d_inode->i_sb;
-       struct dentry *rc = NULL;
        struct dentry *de = dentry, *de_save1=NULL, *de_save2=NULL;
        char *buf = NULL;
-       int pos = D_MAXLEN;
+       int pos = D_MAXLEN, rc;
 
-       SNAP_ALLOC(buf, char*, D_MAXLEN);
+       SNAP_ALLOC(buf, D_MAXLEN);
        if( !buf )
-               return ERR_PTR(-ENOMEM);
+               RETURN(-ENOMEM);
 
        /*
         * iterate upward to construct the path
@@ -139,49 +130,50 @@ lookup:
 
        pos = cat_str_ahead(buf, pos, ".snap");
        buf[D_MAXLEN-1] = 0;
-       CDEBUG(D_FILE, "constructed path: %s\n", &buf[pos]);
+       CDEBUG(D_SNAP, "constructed path: %s\n", &buf[pos]);
 
        /* FIXME lookup_dentry will never return NULL ?? */
+#if 0
        rc = lookup_dentry(&buf[pos], dget(sb->s_root), follow);
        if( !rc ){
                rc = ERR_PTR(-ENOENT);
-               CDEBUG(D_FILE, "lookup_dentry return NULL~!@#$^&*\n");
+               CDEBUG(D_SNAP, "lookup_dentry return NULL~!@#$^&*\n");
        }
-       dput(base);
-
+#else
+       if (path_init(&buf[pos], LOOKUP_FOLLOW, nd)) {
+               rc = path_walk(&buf[pos], nd);
+               if (rc)
+                       GOTO(exit, rc);
+       } 
+#endif
 exit:
        SNAP_FREE(buf, D_MAXLEN);
        return rc;
 }
 
-static struct dentry * currentfs_follow_link ( struct dentry *dentry, 
-                                               struct dentry *base,
-                                               unsigned int follow)
+static int currentfs_follow_link (struct dentry *dentry, struct nameidata *nd)
 {
        struct snap_cache *cache;
-       struct dentry * rc;
        struct inode_operations *iops;
        struct inode * inode = dentry->d_inode;
        int bpib = inode->i_sb->s_blocksize >> 9;
        __u32 save_i_blocks;
-
+       int     rc;
        ENTRY;
 
        cache = snap_find_cache(inode->i_dev);
        if ( !cache ) { 
-               EXIT;
-               return ERR_PTR(-EINVAL);
+               RETURN(-EINVAL);
        }
 
        iops = filter_c2csiops(cache->cache_filter); 
        if (!iops ||
            !iops->follow_link) {
-               rc = ERR_PTR(-EINVAL);
-               goto exit;
+               GOTO(exit, rc = -EINVAL);
        }
 
        if( currentfs_is_under_dotsnap(dentry) ){
-               rc = dotsnap_follow_link( base, dentry, follow );
+               rc = dotsnap_follow_link(dentry, nd);
                if( rc )
                        goto exit;
        }
@@ -193,7 +185,7 @@ static struct dentry * currentfs_follow_link (      struct dentry *dentry,
        if( inode_has_ea(inode) && inode->i_blocks == bpib ) {
                inode->i_blocks = 0; 
        }
-       rc = iops->follow_link(dentry, base, follow);
+       rc = iops->follow_link(dentry, nd);
        
        if( inode->i_blocks != save_i_blocks ){
                inode->i_blocks = save_i_blocks;
@@ -201,13 +193,14 @@ static struct dentry * currentfs_follow_link (    struct dentry *dentry,
        }
        
 exit:
-       EXIT;
-       return rc;
+       RETURN(rc);
 }
 
 struct inode_operations currentfs_sym_iops = {
        readlink:       currentfs_readlink,
-       follow_link:    currentfs_follow_link
+       follow_link:    currentfs_follow_link,
 };
 
-struct file_operations currentfs_sym_fops;
+struct file_operations currentfs_sym_fops = {
+       ioctl:          NULL,
+};
index f7f88a6..1969081 100644 (file)
@@ -2,53 +2,27 @@
  *  Sysctrl entries for Snapfs
  */
 
-#define __NO_VERSION__
-#include <linux/config.h> /* for CONFIG_PROC_FS */
+/* /proc entries */
+
+#define DEBUG_SUBSYSTEM S_SNAP
+
 #include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/sysctl.h>
-#include <linux/swapctl.h>
 #include <linux/proc_fs.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/stat.h>
-#include <linux/ctype.h>
-#include <linux/init.h>
-#include <asm/bitops.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/utsname.h>
-#include <linux/blk.h>
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
 
+#include "snapfs_internal.h" 
 
-/* /proc entries */
 
 #ifdef CONFIG_PROC_FS
-
-
-static void snapfs_proc_modcount(struct inode *inode, int fill)
-{
-       if (fill)
-               MOD_INC_USE_COUNT;
-       else
-               MOD_DEC_USE_COUNT;
-}
-
-struct proc_dir_entry proc_fs_snapfs = {
-       0, 10, "snapfs",
-       S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-       0, &proc_dir_inode_operations,
-       NULL, NULL,
-       NULL,
-       NULL, NULL
-};
-
-
+static struct proc_dir_entry *proc_snapfs_root;
 #endif
 
 
@@ -67,9 +41,11 @@ static struct ctl_table_header *snapfs_table_header = NULL;
 #define ENTRY_CNT 3
 
 /* XXX - doesn't seem to be working in 2.2.15 */
-static struct ctl_table snapfs_ctltable[ENTRY_CNT] =
+static struct ctl_table snapfs_ctltable[] =
 {
+#ifdef SNAP_DEBUG
        {PSDEV_DEBUG, "debug", &snap_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
        {PSDEV_TRACE, "trace", &snap_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
        {0}
 };
@@ -80,31 +56,35 @@ static ctl_table snapfs_table[2] = {
 };
 
 
-int /* __init */ init_snapfs_proc_sys(void)
+int  __init  init_snapfs_proc_sys(void)
 {
+#ifdef CONFIG_PROC_FS
+       proc_snapfs_root = proc_mkdir("snapfs", proc_root_fs);
+       if (!proc_snapfs_root) {
+               printk(KERN_ERR "SNAPFS: error registering /proc/fs/snapfs\n");
+               RETURN(-ENOMEM);
+       }
+       proc_snapfs_root->owner = THIS_MODULE;
+#endif
 
 #ifdef CONFIG_SYSCTL
        if ( !snapfs_table_header )
                snapfs_table_header =
                        register_sysctl_table(snapfs_table, 0);
 #endif
-#ifdef CONFIG_PROC_FS
-       proc_register(&proc_root_fs, &proc_fs_snapfs);
-       proc_fs_snapfs.fill_inode = &snapfs_proc_modcount;
-#endif
        return 0;
 }
 
-void cleanup_snapfs_proc_sys(void) {
-
+void cleanup_snapfs_proc_sys(void) 
+{
 #ifdef CONFIG_SYSCTL
        if ( snapfs_table_header )
                unregister_sysctl_table(snapfs_table_header);
        snapfs_table_header = NULL;
 #endif
-
 #if CONFIG_PROC_FS
-       proc_unregister(&proc_root_fs, proc_fs_snapfs.low_ino);
+       remove_proc_entry("snapfs", proc_root_fs);
 #endif
+
 }