Whamcloud - gitweb
b=3119
[fs/lustre-release.git] / lustre / kernel_patches / patches / snapfs_core-2.4.20.patch
index 4bf11cc..60b27d0 100644 (file)
@@ -2,8 +2,8 @@
 Index: linux-2.4.20-8/fs/ext3/snap.c
 ===================================================================
 --- linux-2.4.20-8.orig/fs/ext3/snap.c 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-8/fs/ext3/snap.c      2004-01-09 23:51:05.000000000 +0800
-@@ -0,0 +1,2650 @@
++++ linux-2.4.20-8/fs/ext3/snap.c      2004-01-27 00:07:10.000000000 +0800
+@@ -0,0 +1,2577 @@
 +/* fs/ext3/snap.c
 + *
 + * Copyright (c) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
@@ -46,8 +46,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +#define EXT3_MAX_SNAP_DATA (sizeof(struct snap_ea))
 +#define EXT3_SNAP_INDEX EXT3_XATTR_INDEX_LUSTRE
 +
++#define EXT3_SNAP_DEBUG
 +#ifdef EXT3_SNAP_DEBUG
-+       static long snap_kmem = 0;
 +       #define snap_debug(f, a...)                             \
 +       do {                                                    \
 +               printk (KERN_INFO "SNAP DEBUG: (%s, %d): %s: ", \
@@ -228,9 +228,10 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +/*SET FLAGS*/
 +extern int ext3_bmap(struct address_space *mapping, long block);
 +extern int ext3_load_inode_bitmap (struct super_block * sb, unsigned int block_group);
++extern int ext3_block_truncate_page(handle_t *handle, struct address_space *mapping, 
++                                  loff_t from);
 +/* helper functions to manipulate field 'parent' in snap_ea */
-+//static inline int
-+static int
++static inline int
 +set_parent_ino(struct snap_ea *pea, int size, int index, ino_t val)
 +{
 +       char * p = (char*) pea;
@@ -242,26 +243,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +
 +       return 0;
 +}
-+static inline ino_t
-+get_parent_ino(struct snap_ea *pea, int size, int index)
-+{
-+       char * p = (char*)pea;
-+       int offset;
-+
-+       offset = sizeof(ino_t)*2 + (size - sizeof(ino_t)*2)/2;
-+       offset += sizeof(ino_t) * index;
-+       return *(ino_t*)(p+offset);
-+}
-+static inline void snap_double_lock(struct inode *i1, struct inode *i2)
-+{
-+      double_down(&i1->i_sem, &i2->i_sem);
-+}
-+
-+static inline void snap_double_unlock(struct inode *i1, struct inode *i2)
-+{
-+      double_up(&i1->i_sem, &i2->i_sem);
-+}
-+
 +/* ext3_iterate_cowed_inode:
 + *    iterate all the cowed inode with the same index and 
 + *  run the associate function @repeat
@@ -425,7 +406,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              lock_super(pri->i_sb);
 +              ext3_journal_get_write_access(handle, sbi->s_sbh);
 +              sbi->s_es->s_first_cowed_pri_ino = cpu_to_le32(pri->i_ino);
-+              SB_LAST_COWED_INO(pri->i_sb) = cpu_to_le32(pri->i_ino);
++              SB_FIRST_COWED_INO(pri->i_sb) = cpu_to_le32(pri->i_ino);
 +              pri->i_sb->s_dirt = 1;
 +              ext3_journal_dirty_metadata(handle, sbi->s_sbh);
 +              unlock_super(pri->i_sb);
@@ -482,8 +463,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +       
 +      /* we update the new cowed ino list end in memory */ 
 +      SB_LAST_COWED_INO(pri->i_sb) = cpu_to_le32(pri->i_ino);
-+        snap_debug("cowed_inode_list_end %lu, append ino=%d\n",
-+                  last_inode->i_ino, le32_to_cpu(snaps->ino[index]));
++        snap_debug("cowed_inode_list_end %lu, append ino=%lu\n",
++                  last_inode->i_ino, pri->i_ino);
 +exit:
 +      if (last_inode)
 +              iput(last_inode);
@@ -516,7 +497,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      if (inode->i_ino == le32_to_cpu(SB_FIRST_COWED_INO(inode->i_sb))) {
 +              SB_FIRST_COWED_INO(inode->i_sb) = cpu_to_le32(next_ino); 
 +              EXT3_I(inode)->i_flags &= ~EXT3_SNAP_PRI_FLAG;
-+              
++              if (next_ino == 0)      
++                        SB_LAST_COWED_INO(inode->i_sb) = 0;
 +      } else {
 +              if (!prev_ino)  
 +                      goto err_exit;
@@ -674,7 +656,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +               * Is it right in snapfs EXT3, check it later?
 +               */
 +              inlist = 0; 
-+      //      ea_size = SNAP_EA_SIZE_FROM_INDEX(index);
 +      } else if (err < 0 || err > EXT3_MAX_SNAP_DATA) {
 +              goto out_unlock;
 +      }
@@ -740,7 +721,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 + * Copy inode metadata from one inode to another, excluding blocks and size.
 + * FIXME do we copy EA data - ACLs and such (excluding snapshot data)?
 + */
-+static void ext3_copy_meta(struct inode *dst, struct inode *src)
++static void ext3_copy_meta(handle_t *handle, struct inode *dst, struct inode *src)
 +{
 +      int size;
 +      
@@ -776,7 +757,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              while ((namelen = strlen(name))) {
 +                      int attrlen;
 +                      char *buf;
-+                      handle_t *handle = ext3_journal_current_handle();
 +                      
 +                      /* don't copy snap data */
 +                      if (!strcmp(name, EXT3_SNAP_ATTR)) {
@@ -806,8 +786,20 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +{
 +       return (EXT3_I(inode)->i_file_acl != 0);
 +}
++/* XXX This function has a very bad effect to 
++ * the performance of filesystem,
++ * will find another way to fix it 
++ */
++static void fs_flushinval_pages(handle_t *handle, struct inode* inode)
++{
++      if (inode->i_blocks > 0 && inode->i_mapping) { 
++              fsync_inode_data_buffers(inode);
++       //     ext3_block_truncate_page(handle, inode->i_mapping, inode->i_size);
++              truncate_inode_pages(inode->i_mapping, 0);
++      }
++}
 +
-+/* ext3_migrate_data:
++/* ext3_migrate_data2:
 + *  MOVE all the data blocks from inode src to inode dst as well as
 + *  COPY all attributes(meta data) from inode src to inode dst.
 + *  For extended attributes(EA), we COPY all the EAs but skip the Snap EA from src to dst.
@@ -816,10 +808,9 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 + *  This is for LAN free backup later.
 + */
 +
-+static int ext3_migrate_data (struct inode *dst, struct inode *src)
++static int ext3_migrate_data (handle_t *handle, struct inode *dst, struct inode *src)
 +{
 +      unsigned long err = 0;
-+      handle_t *handle = NULL;
 +      /* 512 byte disk blocks per inode block */
 +      int bpib = src->i_sb->s_blocksize >> 9;
 +      
@@ -828,13 +819,12 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      
 +      if (dst->i_ino == src->i_ino)
 +              return 0;
-+      handle = ext3_journal_start(dst, SNAP_MIGRATEDATA_TRANS_BLOCKS);
-+      if( !handle )
-+              return -EINVAL;
-+      ext3_copy_meta(dst, src);
 +
-+      snap_debug("migrating %ld data blocks from %lu to %lu\n",
-+                                      blocks, src->i_ino, dst->i_ino);
++      fs_flushinval_pages(handle, src);
++      
++      ext3_copy_meta(handle, dst, src);
++
++      snap_debug("migrating data blocks from %lu to %lu\n", src->i_ino, dst->i_ino);
 +      /* Can't check blocks in case of EAs */
 +        memcpy(EXT3_I(dst)->i_data, EXT3_I(src)->i_data,
 +                            sizeof(EXT3_I(src)->i_data));
@@ -863,7 +853,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +        ext3_mark_inode_dirty(handle, src);
 +        ext3_mark_inode_dirty(handle, dst);
 +
-+      ext3_journal_stop(handle, dst);
 +
 +      return SNAP_ERROR(err);
 +}
@@ -982,18 +971,17 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +
 +static int ext3_copy_block (struct inode *dst, struct inode *src, int blk) 
 +{
-+      struct buffer_head *bh_dst, *bh_src;
++      struct buffer_head *bh_dst = NULL, *bh_src = NULL;
 +      int err = 0;
-+      int journal_data;
 +      handle_t *handle = NULL;
 +
-+      if (!ext3_bmap(src->i_mapping, blk))
-+              return 0;
-+
++      
++      snap_debug("copy blk %d from %lu to %lu \n", blk, src->i_ino, dst->i_ino);
 +      /* 
 +       * ext3_getblk() require handle!=NULL
 +       */
-+      journal_data = !S_ISREG(src->i_mode);
++      if (S_ISREG(src->i_mode))
++              return 0;
 +
 +      handle = ext3_journal_start(dst, SNAP_COPYBLOCK_TRANS_BLOCKS);
 +      if( !handle )
@@ -1002,39 +990,29 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      bh_src = ext3_bread(handle, src, blk, 0, &err);
 +      if (!bh_src) {
 +              snap_err("error for src blk %d, error %d\n", blk, err);
-+              err = -1;
-+              goto exit_stop;
++              goto exit_relese;
 +      }
 +      bh_dst = ext3_getblk(handle, dst, blk, 1, &err);
 +      if (!bh_dst) {
 +              snap_err("error for dst blk %d, error %d\n", blk, err);
-+              err = -1;
-+              goto exit_rels_src;
++              err = -ENOSPC;
++              goto exit_relese;
 +      }
 +      snap_debug("copy block %lu to %lu (%ld bytes)\n",
-+                       bh_src->b_blocknr, bh_dst->b_blocknr, 
-+                      src->i_sb->s_blocksize);
++                 bh_src->b_blocknr, bh_dst->b_blocknr, 
++                 src->i_sb->s_blocksize);
 +
-+      if(journal_data){
-+              ext3_journal_get_write_access(handle, bh_dst);
-+      }
++      ext3_journal_get_write_access(handle, bh_dst);
 +
 +      memcpy(bh_dst->b_data, bh_src->b_data, src->i_sb->s_blocksize);
 +
-+      if(journal_data){
-+              ext3_journal_dirty_metadata(handle, bh_dst);
-+      }else{
-+              mark_buffer_dirty(bh_dst);
-+              if (IS_SYNC(src)) {
-+                      ll_rw_block (WRITE, 1, &bh_dst);
-+                      wait_on_buffer (bh_dst);
-+              }
-+      }
-+      brelse(bh_dst);
-+exit_rels_src:
-+      brelse(bh_src);
-+exit_stop:
-+      ext3_journal_stop(handle, dst);
++      ext3_journal_dirty_metadata(handle, bh_dst);
++      err = 1;
++exit_relese:
++      if (bh_src) brelse(bh_src);
++      if (bh_dst) brelse(bh_dst);
++      if (handle)     
++              ext3_journal_stop(handle, dst);
 +      return err;
 +}
 +
@@ -1258,7 +1236,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +                      goto exit;
 +              }
 +
-+              ext3_migrate_data(tmp, pri);
++              ext3_migrate_data(handle, tmp, pri);
 +              snap_debug("freeing half-copied %lu blocks\n", tmp->i_blocks );
 +              tmp->i_nlink = 0;
 +              iput( tmp );
@@ -1267,7 +1245,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      /* third: restore ind inode to pri inode */
 +      snap_debug("restore %lu blocks to primary inode %lu\n",
 +                      ind->i_blocks, pri->i_ino);
-+      ext3_migrate_data(pri, ind);
++      ext3_migrate_data(handle, pri, ind);
 +
 +      /* final: delete ind inode */
 +      ind->i_nlink = 0;
@@ -1278,9 +1256,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      ext3_journal_stop(handle, pri);
 +}
 +
-+
-+
-+
 +static handle_t * ext3_copy_data(handle_t *handle, struct inode *dst,
 +                              struct inode *src, int *has_orphan)
 +{
@@ -1304,7 +1279,9 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +                              snap_debug("create_indirect:fail to extend "
 +                                              "journal, restart trans\n");
 +                              loopfail( 3 );
-+                              if( !*has_orphan ){
++                              if(!*has_orphan) {
++                                      snap_debug("add orphan ino %lu nlink %d to orphan list \n", 
++                                                 dst->i_ino, dst->i_nlink); 
 +#ifdef EXT3_ENABLE_SNAP_ORPHAN
 +                                      add_snap_orphan(handle, dst, src);
 +#else
@@ -1407,7 +1384,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +{
 +      struct inode *ind;
 +      handle_t *handle = NULL;
-+      int err;
++      int err = 0;
 +      int has_orphan = 0;
 +
 +      if( pri == pri->i_sb->u.ext3_sb.s_journal_inode ){
@@ -1445,7 +1422,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +                      tmp = ext3_new_inode(handle, pri, (int)pri->i_mode, 0);
 +                      if(tmp) {
 +                              down(&tmp->i_sem);
-+                              ext3_migrate_data(tmp, pri);
++                              ext3_migrate_data(handle, tmp, pri);
 +                              up(&tmp->i_sem);
 +                              tmp->i_nlink = 0;
 +                              iput(tmp);      
@@ -1463,8 +1440,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      }
 +
 +      if (ind && !IS_ERR(ind)) {
-+              snap_err("existing indirect ino %lu for %lu: index %d\n",
-+                              ind->i_ino, pri->i_ino, index);
++              snap_debug("existing indirect ino %lu for %lu: index %d\n",
++                        ind->i_ino, pri->i_ino, index);
 +              err = 0;
 +              goto exit;
 +      }
@@ -1476,6 +1453,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      loopfail( 2 );
 +
 +      snap_debug("got new inode %lu\n", ind->i_ino);
++      ind->i_rdev = pri->i_rdev;
 +      ind->i_op = pri->i_op;
 +      ext3_set_generation(ind, (unsigned long)gen);
 +      /* If we are deleting the primary inode, we want to ensure that it is
@@ -1491,7 +1469,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              snap_debug("deleting primary inode\n");
 +              
 +              down(&ind->i_sem);
-+              err = ext3_migrate_data(ind, pri);
++              err = ext3_migrate_data(handle, ind, pri);
 +              if (err)
 +                      goto exit_unlock;
 +
@@ -1503,14 +1481,16 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +               * or ext3_rmdir will report errors "bad dir, no data blocks" 
 +               */
 +              if( S_ISDIR(pri->i_mode)) {
-+                      handle = ext3_copy_data( handle, pri, ind, &has_orphan );
-+                      if( !handle )
++                      handle = ext3_copy_data(handle, pri, ind, &has_orphan);
++                      if(!handle) {
++                              err = -EINVAL;
 +                              goto exit_unlock;
++                      }
 +              }
 +
 +              pri->u.ext3_i.i_flags |= EXT3_DEL_FL;
 +              ind->u.ext3_i.i_flags |= EXT3_COW_FL;
-+              if(S_ISREG(pri->i_mode))        pri->i_nlink = 1;
++              if(S_ISREG(pri->i_mode)) pri->i_nlink = 1;
 +              pri->u.ext3_i.i_dtime = CURRENT_TIME;
 +              //pri->u.ext3_i.i_generation++;
 +              ext3_mark_inode_dirty(handle, pri);
@@ -1518,7 +1498,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              up(&ind->i_sem);
 +      } else {
 +              down(&ind->i_sem);
-+              err = ext3_migrate_data(ind, pri);
++              err = ext3_migrate_data(handle, ind, pri);
 +              if (err)
 +                      goto exit_unlock;
 +
@@ -1542,17 +1522,15 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +                       *    it has been cowed and has ea )
 +                       */
 +                        if( S_ISLNK(ind->i_mode) &&
-+                         (( ind->i_blocks == 0) || (ext3_has_ea(ind) && ind->i_blocks == bpib )) ){
-+                              snap_debug("ino %lu is fast symlink\n",
-+                                              pri->i_ino);
-+                              memcpy(EXT3_I(pri)->i_data,
-+                                      EXT3_I(ind)->i_data,
-+                                      sizeof(EXT3_I(ind)->i_data));
++                         ((ind->i_blocks == 0) || (ext3_has_ea(ind) && ind->i_blocks == bpib))) {
++                              snap_debug("ino %lu is fast symlink\n", pri->i_ino);
++                              memcpy(EXT3_I(pri)->i_data, EXT3_I(ind)->i_data,
++                                     sizeof(EXT3_I(ind)->i_data));
 +                              pri->i_size = ind->i_size;
 +                      }
 +                      else {
 +                              handle = ext3_copy_data(handle, pri, ind, &has_orphan);
-+                              if( !handle )
++                              if (!handle)
 +                                      goto exit_unlock;
 +                      }
 +              }
@@ -1580,7 +1558,9 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              pri->i_sb->s_dirt = 1;
 +              unlock_super(pri->i_sb);
 +      }
-+      if(has_orphan) {
++      if (has_orphan) {
++              snap_debug("del %lu nlink %d from orphan list\n", 
++                         ind->i_ino, ind->i_nlink);
 +#ifdef EXT3_ENABLE_SNAP_ORPHAN        
 +              remove_snap_orphan(handle, ind);
 +#else
@@ -1597,9 +1577,19 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      up(&ind->i_sem);
 +      ind->i_nlink = 0;
 +exit:
++      if (has_orphan) {
++              snap_debug("del %lu nlink %d from orphan list\n", 
++                         ind->i_ino, ind->i_nlink);
++#ifdef EXT3_ENABLE_SNAP_ORPHAN        
++              remove_snap_orphan(handle, ind);
++#else
++              ext3_orphan_del(handle, ind);
++#endif
++      }
 +      iput(ind);
 +      ext3_journal_stop(handle, pri);
-+      snap_debug("exiting with error %d\n", err);
++      if (err)
++              snap_err("exiting with error %d\n", err);
 +      return NULL;
 +}
 +
@@ -1914,58 +1904,58 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              return 0;
 +
 +      if( pri == pri->i_sb->u.ext3_sb.s_journal_inode ){
-+              printk( KERN_EMERG "TRY TO DESTROY JOURNAL'S IND\n");
++              snap_err("TRY TO DESTROY JOURNAL'S IND\n");
 +              return -EINVAL;
 +      }
 +
-+      handle = ext3_journal_start(pri, SNAP_DESTROY_TRANS_BLOCKS);
-+      if( !handle )
-+              return -EINVAL;
-+
 +      err = ext3_xattr_get(pri, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR,
-+                                              buf, EXT3_MAX_SNAP_DATA);
++                           buf, EXT3_MAX_SNAP_DATA);
 +      if (err < 0) {
-+              if (err == -ENODATA)
-+                      snap_err("inode %lu is not a redirector\n", pri->i_ino);
-+              else
-+                      snap_err(EXT3_SNAP_ATTR " attribute read error\n");
-+              goto err_stop;
++              snap_err("inode %lu attribute read error\n", pri->i_ino);
++              return err;
 +      }
 +      
 +      snaps = (struct snap_ea *)buf;
 +      if ( !snaps->ino[index] ) {
 +              snap_err("for pri ino %lu, index %d, redirect ino is 0\n",
 +                              pri->i_ino, index);     
-+              err = -EINVAL;
-+              goto err_stop;
++              return -EINVAL;
 +      }
 +
 +      snap_debug("for pri ino %lu, reading inode %lu at index %d\n", 
 +              pri->i_ino, (ulong)le32_to_cpu(snaps->ino[index]), index);
 +
 +      ind = iget(pri->i_sb, le32_to_cpu (snaps->ino[index]) );
-+      snap_debug("iget ind %lu, ref count = %d\n", ind->i_ino, ind->i_count);
 +
-+      if ( !ind || IS_ERR(ind) || is_bad_inode(ind) ) {
-+              err = -EINVAL;
-+              goto err_stop;
-+      }
++      if ( !ind || IS_ERR(ind) || is_bad_inode(ind)) 
++              return  -EINVAL;
 +
++      snap_debug("iget ind %lu, ref count = %d\n", 
++                 ind->i_ino, atomic_read(&ind->i_count));
++
++      handle = ext3_journal_start(pri, SNAP_DESTROY_TRANS_BLOCKS);
++      if (!handle) {
++              iput(ind);
++              return -EINVAL;
++      }
 +      /* if it's block level cow, first copy the blocks back */       
 +      if (EXT3_HAS_COMPAT_FEATURE(pri->i_sb, EXT3_FEATURE_COMPAT_BLOCKCOW) &&
-+                      S_ISREG(pri->i_mode)) {
++          S_ISREG(pri->i_mode)) {
 +
 +              int blocks;
-+              if( !next_ind ) next_ind = pri;
++              if (!next_ind) {        
++                      next_ind = pri;
++                      down(&ind->i_sem);
++              } else {
++                      double_down(&next_ind->i_sem, &ind->i_sem);
++              }
 +              blocks = (next_ind->i_size + next_ind->i_sb->s_blocksize-1) 
 +                              >> next_ind->i_sb->s_blocksize_bits;
-+
 +#define FAST_MIGRATE_BLOCK
 +#ifdef FAST_MIGRATE_BLOCK
 +              snap_debug("migrate block back from ino %lu to %lu\n",
 +                              ind->i_ino, next_ind->i_ino);
 +
-+              snap_double_lock(next_ind, ind);
 +              for(i = 0; i < blocks; i++) {
 +                      if( ext3_bmap(next_ind->i_mapping, i) ) 
 +                              continue;
@@ -1978,38 +1968,25 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              next_ind->i_blocks = calculate_i_blocks( next_ind, blocks);
 +              ext3_mark_inode_dirty(handle, next_ind);
 +
-+              snap_double_unlock(next_ind, ind);
-+
-+#if 0
-+              snap_double_lock(pri, ind);
-+
-+              for(i = 0; i < blocks; i++) { 
-+                      if( ext3_bmap(pri, i) ) continue;
-+                      if( !ext3_bmap(ind, i) ) continue;
-+                      ext3_migrate_block( pri, ind, i) ;
-+              }
-+              /* Now re-compute the i_blocks */
-+              /* XXX shall we take care of ind here? probably not */
-+              pri->i_blocks = calculate_i_blocks( pri, blocks);
-+              mark_inode_dirty(pri);
-+
-+              double_unlock(pri, ind);
-+#endif
 +#else
-+              snap_double_lock(next_ind, ind);
 +              for (i = 0; i < blocks; i++) {
-+                      if (ext3_bmap (next_ind->i_mapping, i) )        
++                      if (ext3_bmap(next_ind->i_mapping, i))  
 +                              continue;
-+                      if (ext3_copy_block (next_ind, ind, i ) < 0)    break;
++                      if (ext3_copy_block(next_ind, ind, i ) < 0)     
++                              break;
 +              }
 +              ext3_mark_inode_dirty(handle, next_ind);
-+              double_unlock(next_ind, ind);
-+
 +#endif 
-+      }
++              if (next_ind == pri) 
++                      up(&ind->i_sem);
++              else 
++                      double_up(&next_ind->i_sem, &ind->i_sem);
 +
++      }
++      
 +      snap_debug("delete indirect ino %lu\n", ind->i_ino);
-+      snap_debug("iput ind %lu, ref count = %d\n", ind->i_ino, ind->i_count);
++      snap_debug("iput ind %lu, ref count = %d\n", 
++                  ind->i_ino, atomic_read(&ind->i_count));
 +      ind->i_nlink = 0;
 +      iput (ind);
 +
@@ -2076,7 +2053,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              pri->i_ctime = ctime;
 +              ext3_mark_inode_dirty(handle, pri);
 +      }
-+err_stop:
 +      ext3_journal_stop(handle, pri);
 +      return err;
 +}
@@ -2112,23 +2088,22 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      /* XXX: check this, ext3_new_inode, the first arg should be "dir" */ 
 +      tmp = ext3_new_inode(handle, pri, (int)pri->i_mode, 0);
 +      if(tmp) {
-+              snap_double_lock(pri, tmp);
-+              ext3_migrate_data(tmp, pri);
-+              snap_double_unlock(pri, tmp);
++              double_down(&pri->i_sem, &tmp->i_sem);
++              ext3_migrate_data(handle, tmp, pri);
++              double_up(&pri->i_sem, &tmp->i_sem);
 +
 +              tmp->i_nlink = 0;
 +              iput(tmp);      
 +      }
 +      else    
 +              snap_err("restore_indirect, new_inode err\n");
-+
-+      snap_double_lock(pri, ind);
-+      ext3_migrate_data(pri, ind);
++      
++      double_down(&pri->i_sem, &ind->i_sem);
++      ext3_migrate_data(handle, pri, ind);
 +      /* clear the cow flag for pri because ind has it */
 +      pri->u.ext3_i.i_flags &= ~EXT3_COW_FL;
 +      ext3_mark_inode_dirty(handle, pri);
-+      snap_double_unlock(pri, ind);
-+
++      double_up(&pri->i_sem, &ind->i_sem);
 +      iput(ind);
 +
 +//    ext3_destroy_indirect(pri, index);
@@ -2288,7 +2263,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      }
 +}
 +
-+#if 1 
 +static int find_snap_meta_index(
 +      struct table_snap_meta_data *snap_meta,
 +      char                        *name)
@@ -2299,9 +2273,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      for( i = 0; i < TABLE_ITEM_COUNT; i++){
 +              /*compare name Max name Length 15*/
 +              if (snap_meta->array[i].name[0]){
-+                      if(strcmp(snap_meta->array[i].name, name))
-+                              continue;
-+                      return i;
++                      if(!strncmp(snap_meta->array[i].name, name, strlen(name)))
++                              return i;
 +              }
 +      }
 +      return -1; /* can not find */
@@ -2335,8 +2308,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +        struct inode                          *inode;
 +      struct buffer_head              *bh = NULL;
 +      struct table_snap_meta_data     *s_attr;
-+      unsigned long                   map_len = 0, index = 0, left_size;
-+        int                           i, error = 0;
++      unsigned long                   map_len = 0,  left_size;
++        int                           i, error = 0, index = 0;
 +      
 +      ino = SB_SNAPTABLE_INO(sb);     
 +      if (ino == 0){
@@ -2359,8 +2332,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      s_attr = (struct table_snap_meta_data *)(bh->b_data);
 +      index = find_snap_meta_index(s_attr, name);
 +      if (index < 0) {
-+              snap_debug("not exit %s meta attr of table ino %llu \n", 
-+                                      name, ip->i_ino);
++              snap_debug("not exit %s meta attr of table ino %lu \n", 
++                                      name, inode->i_ino);
 +              error = 0;
 +              goto out_iput;
 +      }
@@ -2450,14 +2423,15 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      s_attr = (struct table_snap_meta_data *)(bh->b_data);
 +      index = find_snap_meta_index(s_attr, name);
 +      if (index < 0 && !buf) {        
-+              snap_debug("%s meta attr of table ino %llu do not exist\n", 
++              snap_debug("%s meta attr of table ino %lu do not exist\n", 
 +                          name, inode->i_ino);
 +                error = 0;
++              brelse(bh);
 +              goto exit;
 +      }
 +      if (!buf) {
-+              snap_debug("delete the meta attr %s in the table ino %s",
-+                         *name, inode->ino);
++              snap_debug("delete the meta attr %s in the table ino %lu",
++                         name, inode->i_ino);
 +              /*Here we only delete the entry of the attr
 +               *FIXME, should we also delete the block of 
 +               * this attr
@@ -2467,6 +2441,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              s_attr->array[index].len = 0;
 +              s_attr->count --;
 +              ext3_journal_dirty_metadata(handle, bh);
++              brelse(bh);
 +              goto exit;
 +      }
 +      new_len = (size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
@@ -2477,11 +2452,13 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              if (index < 0){
 +                      snap_err("table full of ino %lu \n", inode->i_ino);
 +                      error = index;
-+                      goto exit;
++                      brelse(bh);
++                      goto exit;
 +              }
 +      }
 +      s_attr->array[index].len = size;
 +      journal_dirty_metadata(handle, bh);
++      brelse(bh);
 +      /*put this attr to the snap table*/
 +      left_size = size;
 +      for(i = 0; i < new_len; i++) {
@@ -2491,8 +2468,9 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +                                    s_attr->array[index].start + i, 1, &error);
 +              if (!array_bh) {
 +                      snap_err("inode %lu Can not get the block of attr %s\n",  
-+                                      inode->i_ino, name);
++                                inode->i_ino, name);
 +                      error = -ENOSPC;
++                      brelse(array_bh);
 +                      goto exit;
 +              }
 +              ext3_journal_get_write_access(handle, array_bh);
@@ -2504,63 +2482,12 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +              left_size -= inode->i_sb->s_blocksize;
 +              brelse(array_bh);
 +      }
-+      ext3_journal_stop(handle, sb->s_root->d_inode); 
 +exit:
-+      brelse(bh);
++      if (handle)
++              ext3_journal_stop(handle, sb->s_root->d_inode); 
 +      iput(inode);
 +      return error;
 +}
-+#else
-+static int ext3_get_meta_attr(struct super_block *sb, 
-+                            char* name, char* buf, 
-+                            int *size)
-+{
-+        struct inode  *root_inode = sb->s_root->d_inode;
-+      int err = 0;
-+      
-+      if (!root_inode)
-+              return -EINVAL;
-+
-+      if (buf)
-+              err = ext3_xattr_get(root_inode, EXT3_SNAP_INDEX, name,
-+                           buf, *size);
-+      if (err == -ERANGE || !buf){
-+              /*get the size of the buf*/
-+              *size = ext3_xattr_get(root_inode, EXT3_SNAP_INDEX, name,
-+                                     NULL, *size);
-+      }
-+      
-+      return err;
-+}
-+/* 
-+ * set the meta info of the snap system
-+ * argument:
-+ *    buf     == NULL  delete "name" meta attr
-+ *            != NULL  set    "name" meta attr 
-+ * return value:
-+ *    = 0     ok;
-+ *    < 0     error;  
-+ */
-+
-+static int ext3_set_meta_attr(struct super_block *sb, char* name, 
-+                            char* buf, int size)
-+{
-+        struct inode  *root_inode = sb->s_root->d_inode;
-+        handle_t      *handle = NULL;
-+        int         error = 0;
-+              
-+
-+      handle = ext3_journal_start(root_inode, EXT3_XATTR_TRANS_BLOCKS);
-+      if(!handle)
-+              return -EINVAL;
-+      
-+      error = ext3_xattr_set(handle, root_inode, EXT3_SNAP_INDEX, name, buf, size, 0);        
-+      
-+      ext3_journal_stop(handle, root_inode); 
-+      
-+      return error;
-+}
-+#endif
 +
 +struct snapshot_operations ext3_snap_operations = {
 +      ops_version:            SNAP_VERSION(2,0,2),
@@ -2654,131 +2581,10 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +
 +
 +
-Index: linux-2.4.20-8/fs/ext3/ioctl.c
-===================================================================
---- linux-2.4.20-8.orig/fs/ext3/ioctl.c        2004-01-05 10:54:00.000000000 +0800
-+++ linux-2.4.20-8/fs/ext3/ioctl.c     2004-01-09 23:50:19.000000000 +0800
-@@ -13,6 +13,12 @@
- #include <linux/ext3_jbd.h>
- #include <linux/sched.h>
- #include <asm/uaccess.h>
-+#include <linux/locks.h>
-+
-+#include <linux/snap.h>
-+extern struct snapshot_operations ext3_snap_operations;
-+extern int ext3_snap_print(struct super_block *sb, int index);
-+extern int ext3_snap_delete(struct super_block *sb, int index);
- int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
-@@ -189,6 +195,103 @@
-                       return ret;
-               }
- #endif
-+#if 0
-+      case EXT3_IOC_SNAP_SETFILECOW: {
-+              printk(KERN_INFO "set file cow on dev %x\n",inode->i_dev);
-+
-+              /* clear block cow feature*/
-+              if (EXT3_HAS_COMPAT_FEATURE(inode->i_sb,
-+                                   EXT3_FEATURE_COMPAT_BLOCKCOW)) {
-+                      handle_t        *handle = ext3_journal_start(inode, 1);
-+                      
-+                      if (EXT3_HAS_COMPAT_FEATURE(inode->i_sb,
-+                                      EXT3_FEATURE_COMPAT_SNAPFS)) {
-+                              printk(KERN_INFO "can't change cow level while  snapfs feature exist");
-+                              return -EPERM;
-+                      }
-+                      lock_super(inode->i_sb);
-+                      journal_get_write_access(handle, EXT3_SB(inode->i_sb)->s_sbh);
-+                      inode->i_sb->u.ext3_sb.s_es->s_feature_compat &=
-+                              cpu_to_le32(~EXT3_FEATURE_COMPAT_BLOCKCOW);
-+                      inode->i_sb->s_dirt = 1;
-+                      journal_dirty_metadata(handle, EXT3_SB(inode->i_sb)->s_sbh);
-+                      unlock_super(inode->i_sb);
-+                      ext3_journal_stop(handle, inode);
-+              }
-+              return 0;
-+      }
-+      case EXT3_IOC_CREATE_INDIR: {
-+              struct inode *ind;
-+              printk(KERN_INFO "create indirect on inode %lu\n",inode->i_ino);
-+                      ind = ext3_snap_operations.create_indirect(inode, 0, 1, 0);
-+              if (!ind || IS_ERR(ind))
-+                      return PTR_ERR(ind);
-+              printk(KERN_INFO "got indirect inode %lu\n",ind->i_ino);
-+              put_user(ind->i_ino,(int *) arg);
-+              iput(ind);
-+              return 0;
-+      }
-+      case EXT3_IOC_GET_INDIR: {
-+              struct inode *ind;
-+              int index = 1;
-+              if (get_user(index, (int *) arg))
-+                      return -EFAULT; 
-+
-+              printk(KERN_INFO "get indirect on inode %lu, index %d\n", 
-+                              inode->i_ino, index);
-+              ind = ext3_snap_operations.get_indirect(inode, NULL, index);
-+              if (!ind || IS_ERR(ind)) {
-+                      put_user(0,(int *) arg);
-+                      return PTR_ERR(ind);
-+              }
-+              printk(KERN_INFO "got indirect inode %lu for index %d\n",
-+                              ind->i_ino, index);
-+              put_user(ind->i_ino,(int *) arg);
-+              iput(ind);
-+              return 0;
-+      }
-+      case EXT3_IOC_IS_REDIR: {
-+              int is_redirector = 0;
-+              printk(KERN_INFO "checking if inode %lu is redirector via\n",
-+                      inode->i_ino);
-+              is_redirector = ext3_snap_operations.is_redirector(inode);
-+              printk(KERN_INFO "redirector: %s\n",is_redirector ? "yes":"no");
-+              put_user(is_redirector,(int *) arg);
-+
-+              return 0;
-+      }
-+      case EXT3_IOC_RESTORE_INDIR: {
-+              printk(KERN_INFO "restore indirect on inode %lu\n",inode->i_ino);
-+              return ext3_snap_operations.restore_indirect(inode, 1);
-+      }
-+      case EXT3_IOC_SNAP_PRINT: {
-+              int index = 1;
-+              if (get_user(index, (int *) arg))
-+                      return -EFAULT; 
-+              printk(KERN_INFO "print snap for index %d\n",index);
-+
-+              return ext3_snap_print(inode->i_sb, 1);
-+      }
-+      case EXT3_IOC_SNAP_DELETE: {
-+              int index = 1;
-+              if (get_user(index, (int *) arg))
-+                      return -EFAULT; 
-+
-+              // XXX: debug code , always set index = 1
-+              if(index !=1) index=1;
-+              printk(KERN_INFO "delete all cowed inode for index %d\n",index);
-+              return ext3_snap_delete(inode->i_sb, index);
-+      }
-+
-+      case EXT3_IOC_DESTROY_INDIR: {
-+              int index = 1;
-+              if (get_user(index, (int *) arg))
-+                      index = 1;
-+              printk(KERN_INFO "destroy indirect on ino %lu, index %d\n",
-+                              inode->i_ino, index);
-+              return ext3_snap_operations.destroy_indirect(inode, index, NULL);
-+      }
-+#endif
-       default:
-               return -ENOTTY;
-       }
 Index: linux-2.4.20-8/fs/ext3/Makefile
 ===================================================================
---- linux-2.4.20-8.orig/fs/ext3/Makefile       2004-01-05 10:54:03.000000000 +0800
-+++ linux-2.4.20-8/fs/ext3/Makefile    2004-01-09 23:50:19.000000000 +0800
+--- linux-2.4.20-8.orig/fs/ext3/Makefile       2004-01-19 22:06:25.000000000 +0800
++++ linux-2.4.20-8/fs/ext3/Makefile    2004-01-19 22:06:25.000000000 +0800
 @@ -13,7 +13,7 @@
  
  obj-y    := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
@@ -2790,8 +2596,8 @@ Index: linux-2.4.20-8/fs/ext3/Makefile
  export-objs += xattr.o
 Index: linux-2.4.20-8/fs/ext3/inode.c
 ===================================================================
---- linux-2.4.20-8.orig/fs/ext3/inode.c        2004-01-05 10:54:03.000000000 +0800
-+++ linux-2.4.20-8/fs/ext3/inode.c     2004-01-09 23:50:19.000000000 +0800
+--- linux-2.4.20-8.orig/fs/ext3/inode.c        2004-01-19 22:06:24.000000000 +0800
++++ linux-2.4.20-8/fs/ext3/inode.c     2004-01-26 01:12:48.000000000 +0800
 @@ -1191,7 +1191,7 @@
   * So, if we see any bmap calls here on a modified, data-journaled file,
   * take extra steps to flush any blocks which might be in the cache. 
@@ -2801,19 +2607,20 @@ Index: linux-2.4.20-8/fs/ext3/inode.c
  {
        struct inode *inode = mapping->host;
        journal_t *journal;
+@@ -1403,7 +1403,7 @@
+  * This required during truncate. We need to physically zero the tail end
+  * of that block so it doesn't yield old data if the file is later grown.
+  */
+-static int ext3_block_truncate_page(handle_t *handle,
++int ext3_block_truncate_page(handle_t *handle,
+               struct address_space *mapping, loff_t from)
+ {
+       unsigned long index = from >> PAGE_CACHE_SHIFT;
 Index: linux-2.4.20-8/fs/ext3/ialloc.c
 ===================================================================
---- linux-2.4.20-8.orig/fs/ext3/ialloc.c       2004-01-05 10:54:03.000000000 +0800
-+++ linux-2.4.20-8/fs/ext3/ialloc.c    2004-01-09 23:50:19.000000000 +0800
-@@ -78,7 +78,6 @@
-       sb->u.ext3_sb.s_inode_bitmap[bitmap_nr] = bh;
-       return retval;
- }
--
- /*
-  * load_inode_bitmap loads the inode bitmap for a blocks group
-  *
-@@ -160,6 +159,13 @@
+--- linux-2.4.20-8.orig/fs/ext3/ialloc.c       2004-01-19 22:06:24.000000000 +0800
++++ linux-2.4.20-8/fs/ext3/ialloc.c    2004-01-19 22:06:25.000000000 +0800
+@@ -160,6 +160,13 @@
        return retval;
  }
  
@@ -2827,10 +2634,42 @@ Index: linux-2.4.20-8/fs/ext3/ialloc.c
  /*
   * NOTE! When we get the inode, we're the only people
   * that have access to it, and as such there are no
+Index: linux-2.4.20-8/fs/ext3/super.c
+===================================================================
+--- linux-2.4.20-8.orig/fs/ext3/super.c        2004-01-19 22:06:24.000000000 +0800
++++ linux-2.4.20-8/fs/ext3/super.c     2004-01-19 22:06:25.000000000 +0800
+@@ -1324,6 +1324,13 @@
+       sbi->s_mount_state = le16_to_cpu(es->s_state);
+       sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb));
+       sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb));
++#define EXT3_SNAP_FS
++#ifdef EXT3_SNAP_FS
++      init_MUTEX(&(sbi->s_snap_list_sem));
++      sbi->s_snaptable_ino = le32_to_cpu(es->s_snaptable_ino);
++      sbi->s_first_cowed_pri_ino = le32_to_cpu(es->s_first_cowed_pri_ino);
++      sbi->s_last_cowed_pri_ino = le32_to_cpu(es->s_last_cowed_pri_ino);
++#endif        
+       for (i=0; i < 4; i++)
+               sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+       sbi->s_def_hash_version = es->s_def_hash_version;
+Index: linux-2.4.20-8/fs/ext3/ext3-exports.c
+===================================================================
+--- linux-2.4.20-8.orig/fs/ext3/ext3-exports.c 2004-01-19 22:06:19.000000000 +0800
++++ linux-2.4.20-8/fs/ext3/ext3-exports.c      2004-01-26 01:13:53.000000000 +0800
+@@ -21,6 +21,9 @@
+ EXPORT_SYMBOL(ext3_xattr_set);
+ EXPORT_SYMBOL(ext3_prep_san_write);
+ EXPORT_SYMBOL(ext3_map_inode_page);
++EXPORT_SYMBOL(ext3_orphan_add);
++EXPORT_SYMBOL(ext3_orphan_del);
++EXPORT_SYMBOL(ext3_block_truncate_page)
+ EXPORT_SYMBOL(ext3_abort);
+ EXPORT_SYMBOL(ext3_decode_error);
 Index: linux-2.4.20-8/include/linux/snap.h
 ===================================================================
 --- linux-2.4.20-8.orig/include/linux/snap.h   2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.20-8/include/linux/snap.h        2004-01-09 23:50:19.000000000 +0800
++++ linux-2.4.20-8/include/linux/snap.h        2004-01-19 22:11:26.000000000 +0800
 @@ -0,0 +1,266 @@
 +/*
 + * Copyright (c) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
@@ -3100,8 +2939,8 @@ Index: linux-2.4.20-8/include/linux/snap.h
 +#endif
 Index: linux-2.4.20-8/include/linux/ext3_fs.h
 ===================================================================
---- linux-2.4.20-8.orig/include/linux/ext3_fs.h        2004-01-05 10:54:03.000000000 +0800
-+++ linux-2.4.20-8/include/linux/ext3_fs.h     2004-01-09 23:54:01.000000000 +0800
+--- linux-2.4.20-8.orig/include/linux/ext3_fs.h        2004-01-19 22:06:24.000000000 +0800
++++ linux-2.4.20-8/include/linux/ext3_fs.h     2004-01-19 22:11:15.000000000 +0800
 @@ -183,7 +183,13 @@
  #define EXT3_INDEX_FL                 0x00001000 /* hash-indexed directory */
  #define EXT3_IMAGIC_FL                        0x00002000 /* AFS directory */
@@ -3149,15 +2988,15 @@ Index: linux-2.4.20-8/include/linux/ext3_fs.h
        __u8    s_reserved_char_pad;
        __u16   s_reserved_word_pad;
 -      __u32   s_reserved[192];        /* Padding to the end of the block */
-+      /* for snapfs */
 +      __u32   s_default_mount_opts;
 +        __u32   s_first_meta_bg;        /* First metablock group */
 +      __u32   s_mkfs_time;            /* When the filesystem was created */
++      /* for snapfs */
 +      __u32   s_first_cowed_pri_ino;  /* For snapfs,the first cowed primary inode */
 +      __u32   s_last_cowed_pri_ino;     /* last cowed ino in memory */
 +      __u32   s_snaptable_ino;        /* snaptable ino in memory */
 +      __u32   s_last_snap_orphan;     /* SnapFS: start of cowing indirect inode */
-+      __u32   s_reserved[185];        /* Padding to the end of the block,originally 204 */
++      __u32   s_reserved[186];        /* Padding to the end of the block,originally 204 */
  };
  
  #ifdef __KERNEL__
@@ -3173,8 +3012,8 @@ Index: linux-2.4.20-8/include/linux/ext3_fs.h
                                         EXT3_FEATURE_INCOMPAT_RECOVER)
 Index: linux-2.4.20-8/include/linux/ext3_fs_sb.h
 ===================================================================
---- linux-2.4.20-8.orig/include/linux/ext3_fs_sb.h     2004-01-05 10:54:00.000000000 +0800
-+++ linux-2.4.20-8/include/linux/ext3_fs_sb.h  2004-01-09 23:50:20.000000000 +0800
+--- linux-2.4.20-8.orig/include/linux/ext3_fs_sb.h     2004-01-19 22:06:18.000000000 +0800
++++ linux-2.4.20-8/include/linux/ext3_fs_sb.h  2004-01-19 22:10:06.000000000 +0800
 @@ -86,6 +86,13 @@
        wait_queue_head_t s_delete_thread_queue;
        wait_queue_head_t s_delete_waiter_queue;
@@ -3191,8 +3030,8 @@ Index: linux-2.4.20-8/include/linux/ext3_fs_sb.h
  #endif        /* _LINUX_EXT3_FS_SB */
 Index: linux-2.4.20-8/include/linux/ext3_jbd.h
 ===================================================================
---- linux-2.4.20-8.orig/include/linux/ext3_jbd.h       2004-01-05 10:53:59.000000000 +0800
-+++ linux-2.4.20-8/include/linux/ext3_jbd.h    2004-01-09 23:50:20.000000000 +0800
+--- linux-2.4.20-8.orig/include/linux/ext3_jbd.h       2004-01-19 22:06:15.000000000 +0800
++++ linux-2.4.20-8/include/linux/ext3_jbd.h    2004-01-19 22:11:15.000000000 +0800
 @@ -71,6 +71,33 @@
  
  #define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8
@@ -3230,13 +3069,14 @@ Index: linux-2.4.20-8/include/linux/ext3_jbd.h
 
 %diffstat
  fs/ext3/Makefile           |    2 
- fs/ext3/ialloc.c           |    8 
- fs/ext3/inode.c            |    2 
- fs/ext3/ioctl.c            |  103 +
- fs/ext3/snap.c             | 2650 +++++++++++++++++++++++++++++++++++++++++++++
+ fs/ext3/ext3-exports.c     |    3 
+ fs/ext3/ialloc.c           |    7 
+ fs/ext3/inode.c            |    4 
+ fs/ext3/snap.c             | 2577 +++++++++++++++++++++++++++++++++++++++++++++
+ fs/ext3/super.c            |    7 
  include/linux/ext3_fs.h    |   38 
  include/linux/ext3_fs_sb.h |    7 
  include/linux/ext3_jbd.h   |   27 
  include/linux/snap.h       |  266 ++++
9 files changed, 3097 insertions(+), 6 deletions(-)
10 files changed, 2932 insertions(+), 6 deletions(-)