Whamcloud - gitweb
update from HEAD
authortianying <tianying>
Wed, 28 Jan 2004 08:32:41 +0000 (08:32 +0000)
committertianying <tianying>
Wed, 28 Jan 2004 08:32:41 +0000 (08:32 +0000)
lustre/kernel_patches/patches/snapfs_core-2.4.20.patch
lustre/snapfs/clonefs.c
lustre/snapfs/dir.c
lustre/snapfs/file.c
lustre/snapfs/inode.c

index 3cc6d9b..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-19 23:24:39.000000000 +0800
-@@ -0,0 +1,2583 @@
++++ 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,6 +46,7 @@ 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
 +       #define snap_debug(f, a...)                             \
 +       do {                                                    \
@@ -227,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;
@@ -241,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
@@ -515,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;
@@ -673,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;
 +      }
@@ -804,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.
@@ -826,6 +820,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      if (dst->i_ino == src->i_ino)
 +              return 0;
 +
++      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);
@@ -857,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);
 +
-+      truncate_inode_pages(src->i_mapping, 0);
 +
 +      return SNAP_ERROR(err);
 +}
@@ -1261,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)
 +{
@@ -1287,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
@@ -1487,9 +1481,11 @@ 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;
@@ -1526,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;
 +                      }
 +              }
@@ -1564,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
@@ -1581,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;
 +}
 +
@@ -1934,19 +1940,22 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +      }
 +      /* 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;
@@ -1959,25 +1968,7 @@ 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))  
 +                              continue;
@@ -1985,10 +1976,14 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +                              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, atomic_read(&ind->i_count));
@@ -2093,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);
++              double_down(&pri->i_sem, &tmp->i_sem);
 +              ext3_migrate_data(handle, tmp, pri);
-+              snap_double_unlock(pri, tmp);
++              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);
++      
++      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);
@@ -2589,8 +2583,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c
 +
 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-13 00:10:14.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 \
@@ -2602,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-18 01:48: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. 
@@ -2613,10 +2607,19 @@ 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-16 20:48:29.000000000 +0800
+--- 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;
  }
@@ -2633,8 +2636,8 @@ Index: linux-2.4.20-8/fs/ext3/ialloc.c
   * 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-05 10:54:03.000000000 +0800
-+++ linux-2.4.20-8/fs/ext3/super.c     2004-01-18 01:40:10.000000000 +0800
+--- 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));
@@ -2649,10 +2652,24 @@ Index: linux-2.4.20-8/fs/ext3/super.c
        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-13 00:10:14.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>
@@ -2922,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-16 20:45:09.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 */
@@ -2995,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-13 00:10:14.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;
@@ -3013,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-13 00:10:14.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
@@ -3052,13 +3069,14 @@ Index: linux-2.4.20-8/include/linux/ext3_jbd.h
 
 %diffstat
  fs/ext3/Makefile           |    2 
+ fs/ext3/ext3-exports.c     |    3 
  fs/ext3/ialloc.c           |    7 
- fs/ext3/inode.c            |    2 
- fs/ext3/snap.c             | 2583 +++++++++++++++++++++++++++++++++++++++++++++
+ 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, 2934 insertions(+), 5 deletions(-)
10 files changed, 2932 insertions(+), 6 deletions(-)
 
index b4f136c..2292c49 100644 (file)
@@ -422,19 +422,17 @@ struct address_space_operations clonefs_file_address_ops = {
 
 static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 {
-       int res;
        struct inode * cache_inode;
        struct inode * old_inode;
+       int rc = -ENOENT;
 
        ENTRY;
 
        cache_inode = clonefs_get_inode(dentry->d_inode); 
 
-       res = -ENOENT;
-
-       if ( ! cache_inode ) {
+       if (!cache_inode) {
                CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-               RETURN(res);    
+               RETURN(rc);     
        }
        
        /* XXX: shall we allocate a new dentry ? 
@@ -446,8 +444,8 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
        /* set dentry inode to cache inode */
        dentry->d_inode = cache_inode;
 
-       if ( cache_inode->i_op->readlink ) {
-               res = cache_inode->i_op->readlink(dentry, buf, len); 
+       if (cache_inode->i_op->readlink) {
+               rc = cache_inode->i_op->readlink(dentry, buf, len); 
        }else {
                CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino);
        }
@@ -457,21 +455,21 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 
        iput(cache_inode);
 
-       RETURN(res);
+       RETURN(rc);
 }
 
 static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
 {
        struct inode * cache_inode;
        struct inode * old_inode;
-       int    res;
+       int    rc = -ENOENT;
 
        ENTRY;
 
        cache_inode = clonefs_get_inode(dentry->d_inode); 
-       if ( ! cache_inode ) {
+       if (!cache_inode) {
                CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-               RETURN(-ENOENT);        
+               RETURN(rc);     
        }
 
        /* XXX: shall we allocate a new dentry ? 
@@ -483,8 +481,8 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
        /* set dentry inode to cache inode */
        dentry->d_inode = cache_inode;
 
-       if ( cache_inode->i_op->follow_link ) {
-               res = cache_inode->i_op->follow_link(dentry, nd); 
+       if (cache_inode->i_op->follow_link) {
+               rc = cache_inode->i_op->follow_link(dentry, nd); 
        }
 
        /* restore the old inode */
@@ -492,16 +490,103 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
 
        iput(cache_inode);
 
-       RETURN(res);
+       RETURN(rc);
 }
+static ssize_t
+clonefs_getxattr(struct dentry *dentry, const char *name,
+                 void *buffer, size_t size)
+{
+       struct inode * cache_inode;
+       struct inode * old_inode;
+       int    rc = -ENOENT;
+
+       ENTRY;
+
+       cache_inode = clonefs_get_inode(dentry->d_inode); 
+       if (!cache_inode) {
+               CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
+               RETURN(rc);     
+       }
+
+       /* XXX: shall we allocate a new dentry ? 
+               The following is safe for ext2, etc. because ext2_follow_link 
+               only use the inode info */
 
+       /* save the old dentry inode */ 
+       old_inode = dentry->d_inode;
+       /* set dentry inode to cache inode */
+       dentry->d_inode = cache_inode;
+
+       if (cache_inode->i_op->getxattr) {
+               rc = cache_inode->i_op->getxattr(dentry, name, buffer, size); 
+       }
+
+       /* restore the old inode */
+       dentry->d_inode = old_inode;
+
+       iput(cache_inode);
+
+       RETURN(rc);
+}
+static ssize_t
+clonefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+       struct inode * cache_inode;
+       struct inode * old_inode;
+       int    rc = -ENOENT;
+
+       ENTRY;
+
+       cache_inode = clonefs_get_inode(dentry->d_inode); 
+       if (!cache_inode) {
+               CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
+               RETURN(rc);     
+       }
+
+       /* XXX: shall we allocate a new dentry ? 
+               The following is safe for ext2, etc. because ext2_follow_link 
+               only use the inode info */
+
+       /* save the old dentry inode */ 
+       old_inode = dentry->d_inode;
+       /* set dentry inode to cache inode */
+       dentry->d_inode = cache_inode;
+
+       if (cache_inode->i_op->listxattr) {
+               rc = cache_inode->i_op->listxattr(dentry, buffer, size); 
+       }
+
+       /* restore the old inode */
+       dentry->d_inode = old_inode;
+
+       iput(cache_inode);
+
+       RETURN(rc);
+
+}
 struct inode_operations clonefs_symlink_inode_ops =
 {
        /*FIXME later getxattr, listxattr, 
         * other method need to be replaced too 
         * */  
-       readlink:       clonefs_readlink,   /* readlink */              
-       follow_link:    clonefs_follow_link,/* follow_link */             
+       readlink:       clonefs_readlink,       /* readlink */              
+       follow_link:    clonefs_follow_link,    /* follow_link */             
+       getxattr:       clonefs_getxattr,       /* get xattr */
+        listxattr:      clonefs_listxattr,      /* list xattr */
 };
 
 
+int clonefs_mounted(struct snap_cache *cache, int index)
+{
+       struct snap_clone_info *clone_sb;
+       struct list_head *list, *end;
+
+       end = list = &cache->cache_clone_list;
+       
+       list_for_each_entry(clone_sb, list, clone_list_entry) {
+               if (clone_sb->clone_index == index)
+                       return 1;       
+       }       
+       return 0;       
+}
+
index 4db0908..d139d20 100644 (file)
@@ -37,10 +37,13 @@ static ino_t get_parent_ino(struct inode * inode)
 
 static void d_unadd_iput(struct dentry *dentry)
 {
+       spin_lock(&dcache_lock);
        list_del(&dentry->d_alias);
        INIT_LIST_HEAD(&dentry->d_alias);
        list_del(&dentry->d_hash);
        INIT_LIST_HEAD(&dentry->d_hash);
+       spin_unlock(&dcache_lock);
+       
        iput(dentry->d_inode);
        dentry->d_inode = NULL;
 }
@@ -76,7 +79,8 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 
                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);
+               CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n", 
+                      snap->i_ino, snap->i_mode);
                d_add(dentry, snap);
                RETURN(NULL);
        }
@@ -87,10 +91,14 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
        }
 
        rc = iops->lookup(dir, dentry);
-       if ( rc || !dentry->d_inode) {
+       if (rc || !dentry->d_inode || 
+            is_bad_inode(dentry->d_inode) ||
+           IS_ERR(dentry->d_inode)) {
                RETURN(NULL);
        }
-       
+
+       CDEBUG(D_INODE, "cache inode ino %lu, mode %o\n", 
+              dentry->d_inode->i_ino, dentry->d_inode->i_mode);
        /*
         * If we are under dotsnap, we need save extra data into
         * dentry->d_fsdata:  For dir, we only need _this_ snapshot's index; 
@@ -160,13 +168,13 @@ static int currentfs_create(struct inode *dir, struct dentry *dentry, int mode)
        }
 
        cache = snap_find_cache(dir->i_dev);
-       if ( !cache ) { 
+       if (!cache) { 
                RETURN(-EINVAL);
        }
 
        handle = snap_trans_start(cache, dir, SNAP_OP_CREATE);
 
-       if ( snap_needs_cow(dir) != -1 ) {
+       if (snap_needs_cow(dir) != -1) {
                CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 1);
                if ((snap_do_cow(dir, get_parent_ino(dir), 0))) {
@@ -242,7 +250,12 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                 CERROR("Error in currentfs_mkdir, dentry->d_inode is NULL\n");
         }
 
-       snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 3);
+       set_filter_ops(cache, dentry->d_inode);
+       init_filter_data(dentry->d_inode, 0); 
+       
+       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:
        snap_trans_commit(cache, handle);
@@ -320,8 +333,11 @@ static int currentfs_symlink(struct inode *dir, struct dentry *dentry,
 
        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);
        
+       set_filter_ops(cache, dentry->d_inode);
+       init_filter_data(dentry->d_inode, 0); 
+       
+       snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3);
 exit:
        snap_trans_commit(cache, handle);
        RETURN(rc);
@@ -360,6 +376,9 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 
        snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 2);
        rc = iops->mknod(dir, dentry, mode, rdev);
+       
+       set_filter_ops(cache, dentry->d_inode);
+       init_filter_data(dentry->d_inode, 0); 
        snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 3);
        
        /* XXX do we need to set the correct snap_{*}_iops */
@@ -380,7 +399,6 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
        off_t   i_size = 0;
        ino_t ino = 0;
        int keep_inode = 0;
-//     struct dentry_operations *save_dop = NULL;
        void *handle = NULL;
 
        ENTRY;
@@ -416,23 +434,10 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
        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 (dir, get_parent_ino(dir), SNAP_CREATE_IND_DEL_PRI);
+               snap_do_cow (dentry->d_inode, get_parent_ino(dentry->d_inode), 
+                            SNAP_CREATE_IND_DEL_PRI);
                keep_inode = 1;
        }
-#if 0
-       if ( keep_inode ) {     
-                       printk("set up dentry ops, before %p\n",dentry->d_op);
-               save_dop = dentry->d_op;
-
-               filter_setup_dentry_ops(cache->cache_filter,
-                                dentry->d_op, &currentfs_dentry_ops);
-               dentry->d_op = filter_c2udops(cache->cache_filter);
-
-                       printk("set up dentry ops, after %p\n",dentry->d_op);
-
-       }
-
-#endif
 
        if( keep_inode && dentry->d_inode ) {
                ino = dentry->d_inode->i_ino;
@@ -445,31 +450,20 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
        rc = iops->rmdir(dir, dentry);
        snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 5);
 
-       /* XXX : check this */
-#if 0
-       if ( keep_inode ) {
-               dentry->d_op = save_dop;
-               printk("restore dentry ops, now at %p\n",dentry->d_op);
-       }
-
-#endif
-
        if( keep_inode && ino) {
-               inode = iget ( dir->i_sb, ino);
+               inode = iget (dir->i_sb, ino);
                if( inode) {
 //                     inode->i_ctime = i_ctime;
                        inode->i_nlink = i_nlink;
                        inode->i_size = i_size;
                        mark_inode_dirty(inode);
                        iput( inode);
-#ifdef CONFIG_SNAPFS_EXT3
                        /*
                         * In Ext3, rmdir() will put this inode into
                         * orphan list, we must remove it out. It's ugly!!
                         */
                        if( cache->cache_type == FILTER_FS_EXT3 )
                                ext3_orphan_del(handle, inode);
-#endif
                        snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 6);
                }
        }
@@ -698,5 +692,8 @@ struct inode_operations currentfs_dir_iops = {
        rmdir:          currentfs_rmdir,
        unlink:         currentfs_unlink,
        rename:         currentfs_rename,
-       lookup:         currentfs_lookup
+       lookup:         currentfs_lookup,
+       removexattr:    currentfs_removexattr,
+       setattr:        currentfs_setattr,
+       setxattr:       currentfs_setxattr,
 };
index 25eea66..a8a8860 100644 (file)
@@ -43,7 +43,7 @@ static int copy_back_page(struct inode *dst,
        char *kaddr_src, *kaddr_dst;
         struct snap_cache *cache;
        struct address_space_operations *c_aops;
-       struct page *src_page, *dst_page;
+       struct page *src_page = NULL, *dst_page = NULL;
        unsigned long index, offset, bytes;
        int    err = 0;
        ENTRY;
@@ -96,6 +96,8 @@ static int copy_back_page(struct inode *dst,
        flush_dcache_page(dst_page);
 
        err = c_aops->commit_write(NULL, dst_page, offset, offset + bytes);
+       CDEBUG(D_SNAP, "copy back pages %p index %lu src %lu dst %lu \n",
+              dst_page, dst_page->index, src->i_ino, dst->i_ino); 
        if (err) 
                goto unlock_dst_page; 
        err = 1;
@@ -132,28 +134,36 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
         if ( !cache ) 
                 RETURN(-EINVAL);
 
+       down(&inode->i_sem);
+
         if ( snap_needs_cow(inode) != -1 ) {
                 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) 
-                RETURN(-EINVAL);
-
+        if (!fops || !fops->write) { 
+                up(&inode->i_sem); 
+               RETURN(-EINVAL);
+       }
         if (filp->f_flags & O_APPEND)
                 pos = inode->i_size;
         else {
                 pos = *ppos;
-                if (pos != *ppos)
+                if (pos != *ppos){
+                       up(&inode->i_sem); 
                         RETURN(-EINVAL);
+               }
         }
-       if (pos & PAGE_CACHE_MASK) {
+       
+       CDEBUG(D_SNAP, "write offset %lld count %u \n", pos, count);
+       
+       if (pos & (PAGE_CACHE_SIZE - 1)) {
                start[0] = pos & PAGE_CACHE_MASK;
                end[0] = pos;
        }
        pos += count - 1;
-       if ((pos+1) & PAGE_CACHE_MASK) {
+       if ((pos+1) & (PAGE_CACHE_SIZE - 1)) {
                start[1] = pos;  
                end[1] = PAGE_CACHE_ALIGN(pos);
        }
@@ -161,7 +171,9 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
        if (((start[0] >> PAGE_CACHE_SHIFT) == (start[1] >> PAGE_CACHE_SHIFT)) ||
            pos > inode->i_size) 
                start[1] = -1;
-       
+
+       CDEBUG(D_SNAP, "copy back start[0] %ld end[0] %ld start[1] %ld end[1] %ld \n",
+              start[0], end[0], start[1], end[1]);     
        for (i = 0; i < 2; i++) {
                if (start[i] == -1) 
                        continue;
@@ -189,11 +201,14 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
                        if (result < 0) {
                                iput(cache_inode);
                                rc = result;
+                               up(&inode->i_sem);
                                goto exit;
                        }
                                iput(cache_inode);
                }
        }
+       
+        up(&inode->i_sem); 
        rc = fops->write(filp, buf, count, ppos);
 exit:
         RETURN(rc);
@@ -246,7 +261,6 @@ static int currentfs_readpage(struct file *file, struct page *page)
        table = &snap_tables[cache->cache_snap_tableno];
 
         for (slot = table->tbl_count - 1; slot >= 1; slot--) {
-               cache_inode = NULL;
                 index = table->snap_items[slot].index;
                cache_inode = snap_get_indirect(inode, NULL, index);
 
@@ -259,12 +273,19 @@ static int currentfs_readpage(struct file *file, struct page *page)
                 if (!search_older && c_aops->bmap(cache_inode->i_mapping, block)) 
                         break;
                 iput(cache_inode);
+               cache_inode = NULL;
         }
        if (pri_inode) iput(pri_inode);
 
-       if (!cache_inode )  
-               RETURN(-EINVAL);
-
+       if (!cache_inode) {
+               CDEBUG(D_SNAP, "block %lu is a hole of inode %lu \n", 
+                      block, inode->i_ino);
+               memset(kmap(page), 0, PAGE_CACHE_SIZE);
+               flush_dcache_page(page);
+               GOTO(exit, rc = 0);
+       }
+       CDEBUG(D_INODE, "readpage ino %lu icount %d \n", cache_inode->i_ino, 
+              atomic_read(&cache_inode->i_count));
        down(&cache_inode->i_sem);
 
        /*Here we have changed a file to read,
@@ -284,13 +305,14 @@ static int currentfs_readpage(struct file *file, struct page *page)
                GOTO(exit_release, rc = -EIO);
 
        memcpy(kmap(page), kmap(cache_page), PAGE_CACHE_SIZE);
+       flush_dcache_page(page);
 
        kunmap(cache_page);
        page_cache_release(cache_page);
 
        up(&cache_inode->i_sem);
        iput(cache_inode);
-       
+exit:  
        kunmap(page);
        SetPageUptodate(page);
        UnlockPage(page);
@@ -315,6 +337,8 @@ struct file_operations currentfs_file_fops = {
 };
                                                                                                                                                                                                      
 struct inode_operations currentfs_file_iops = {
-       revalidate:     NULL,
+       setattr:        currentfs_setattr,
+       setxattr:       currentfs_setxattr,
+       removexattr:    currentfs_removexattr,  
 };
 
index 25619a8..97bfd46 100644 (file)
@@ -64,6 +64,8 @@ void init_filter_data(struct inode *inode,
                return;
        }
        snapops = filter_c2csnapops(cache->cache_filter);
+
+       if (inode->i_filterdata) return;
        
        inode->i_filterdata = (struct filter_inode_info *) \
                              kmem_cache_alloc(filter_info_cache, SLAB_KERNEL);
@@ -104,7 +106,95 @@ void set_filter_ops(struct snap_cache *cache, struct inode *inode)
                       inode->i_ino, inode->i_op);
        }
 }
+int currentfs_setxattr(struct dentry *dentry, const char *name, 
+                      const void *value, size_t size, int flags)
+{
+        struct snap_cache      *cache;
+       struct inode            *inode = dentry->d_inode;
+       struct inode_operations *iops;
+       int    rc;
+
+       ENTRY;
+       cache = snap_find_cache(inode->i_dev);
+       if (!cache) {
+               CERROR("currentfs_setxattr: cannot find cache\n");
+               RETURN(-EINVAL);
+       }
+
+       iops = filter_c2cfiops(cache->cache_filter);
+       if (!iops || !iops->setxattr) {
+               RETURN(-EINVAL);                
+       }
+        if ( snap_needs_cow(inode) != -1 ) {
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+       }
+
+       rc = iops->setxattr(dentry, name, value, size, flags);
+
+       RETURN(rc);
+}
+int currentfs_removexattr(struct dentry *dentry, const char *name)
+{
+        struct snap_cache      *cache;
+       struct inode            *inode = dentry->d_inode;
+       struct inode_operations *iops;
+       int    rc;
+
+       ENTRY;
+       cache = snap_find_cache(inode->i_dev);
+       if (!cache) {
+               CERROR("currentfs_setxattr: cannot find cache\n");
+               RETURN(-EINVAL);
+       }
+
+       iops = filter_c2cfiops(cache->cache_filter);
+       if (!iops || !iops->removexattr) {
+               RETURN(-EINVAL);                
+       }
+        
+       if (snap_needs_cow(inode) != -1) {
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+       }
+       rc = iops->removexattr(dentry, name);
+
+       RETURN(rc);
+}
+
+int currentfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+        struct snap_cache      *cache;
+       struct inode            *inode = dentry->d_inode;
+       struct inode_operations *iops;
+       int    rc;
+
+       ENTRY;
+       cache = snap_find_cache(inode->i_dev);
+       if (!cache) {
+               CERROR("currentfs_setxattr: cannot find cache\n");
+               RETURN(-EINVAL);
+       }
 
+       iops = filter_c2cfiops(cache->cache_filter);
+       if (!iops || !iops->setattr) {
+               RETURN(-EINVAL);                
+       }
+        if ( snap_needs_cow(inode) != -1 ) {
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+       }
+
+       rc = iops->setattr(dentry, attr);
+
+       RETURN(rc);
+}
 /* Superblock operations. */
 static void currentfs_read_inode(struct inode *inode)
 {
@@ -113,7 +203,6 @@ static void currentfs_read_inode(struct inode *inode)
 
        if( !inode ) 
                return;
-
        CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
 
        cache = snap_find_cache(inode->i_dev);
@@ -131,10 +220,14 @@ static void currentfs_read_inode(struct inode *inode)
        if(filter_c2csops(cache->cache_filter))
                filter_c2csops(cache->cache_filter)->read_inode(inode);
 
+       CDEBUG(D_INODE, "read_inode ino %lu icount %d \n", 
+              inode->i_ino, atomic_read(&inode->i_count));
        set_filter_ops(cache, inode);
        /*init filter_data struct 
         * FIXME flag should be set future*/
        init_filter_data(inode, 0); 
+       CDEBUG(D_INODE, "read_inode ino %lu icount %d \n", 
+              inode->i_ino, atomic_read(&inode->i_count));
        return; 
 }
 
@@ -217,3 +310,8 @@ struct super_operations currentfs_super_ops = {
        put_super:      currentfs_put_super,
        clear_inode:    currentfs_clear_inode,
 };
+
+
+
+
+