Whamcloud - gitweb
Update snapfs
authorwangdi <wangdi>
Mon, 5 Jul 2004 11:04:03 +0000 (11:04 +0000)
committerwangdi <wangdi>
Mon, 5 Jul 2004 11:04:03 +0000 (11:04 +0000)
1)some fix in fsfilt_snap_ext3 and fsfilt_snap_smfs.
2)add smfs_cow.c in smfs.
3)remove snapfs in Makefile.in and configure.in

15 files changed:
lnet/utils/debug.c
lustre/Makefile.in
lustre/autoMakefile.am
lustre/configure.in
lustre/include/linux/lustre_fsfilt.h
lustre/include/linux/lustre_smfs.h
lustre/include/linux/lustre_snap.h [new file with mode: 0644]
lustre/lvfs/fsfilt_snap_ext3.c
lustre/lvfs/fsfilt_snap_smfs.c
lustre/portals/utils/debug.c
lustre/smfs/Makefile.in
lustre/smfs/dir.c
lustre/smfs/smfs_cow.c [new file with mode: 0644]
lustre/smfs/smfs_internal.h
lustre/smfs/super.c

index 67d8edc..9ce7528 100644 (file)
@@ -545,9 +545,11 @@ static struct mod_paths {
         {"lov", "lustre/lov"},
         {"lmv", "lustre/lmv"},
         {"fsfilt_ext3", "lustre/lvfs"},
+        {"fsfilt_snap_ext3", "lustre/lvfs"},
         {"fsfilt_extN", "lustre/lvfs"},
         {"fsfilt_reiserfs", "lustre/lvfs"},
         {"fsfilt_smfs", "lustre/lvfs"},
+        {"fsfilt_snap_smfs", "lustre/lvfs"},
         {"ptlbd", "lustre/ptlbd"},
         {"mgmt_svc", "lustre/mgmt"},
         {"mgmt_cli", "lustre/mgmt"},
index 311435d..7a9e460 100644 (file)
@@ -23,6 +23,5 @@ ifeq ($(PATCHLEVEL),4)
 subdir-m += ptlbd
 endif # PATCHLEVEL = 4
 
-@SNAPFS_TRUE@subdir-m += snapfs
 
 @INCLUDE_RULES@
index a664117..a706178 100644 (file)
@@ -6,7 +6,7 @@
 AUTOMAKE_OPTIONS = foreign
 
 SUBDIRS = . include portals ldiskfs lvfs obdclass lov ldlm ptlrpc      \
-       obdecho osc mdc lmv  mds obdfilter ost llite cobd ptlbd snapfs smfs cmobd \
+       obdecho osc mdc lmv  mds obdfilter ost llite cobd ptlbd smfs cmobd \
        liblustre doc utils tests conf scripts
 
 EXTRA_DIST = BUGS FDL Rules.in kernel_patches kernel-tests/Makefile    \
index d667270..762e489 100644 (file)
@@ -143,8 +143,12 @@ AC_ARG_ENABLE([snapfs],
        AC_HELP_STRING([--enable-snapfs],
                        [build snapfs]),
        [],[enable_snapfs='no'])
+
 AC_MSG_RESULT([$enable_snapfs])
 AM_CONDITIONAL(SNAPFS, test x$enable_snapfs = xyes)
+if test x$enable_snapfs = xyes ; then
+       AC_DEFINE(CONFIG_SNAPFS, 1, [enable snap support])
+fi
 
 sinclude(portals/build.m4)
 sinclude(portals/archdep.m4)
@@ -239,9 +243,6 @@ scripts/lustre.spec
 scripts/version_tag.pl
 smfs/Makefile
 smfs/autoMakefile
-snapfs/Makefile
-snapfs/autoMakefile
-snapfs/utils/Makefile
 cmobd/Makefile
 cmobd/autoMakefile
 tests/Makefile
index 43c3123..204004e 100644 (file)
@@ -58,8 +58,8 @@ struct fsfilt_operations {
         int     (* fs_iocontrol)(struct inode *inode, struct file *file,
                                  unsigned int cmd, unsigned long arg);
         int     (* fs_set_md)(struct inode *inode, void *handle, void *md,
-                              int size);
-        int     (* fs_get_md)(struct inode *inode, void *md, int size);
+                              int size, int flags);
+        int     (* fs_get_md)(struct inode *inode, void *md, int size, int flags);
 
         /* this method is needed to make IO operation fsfilt nature depend. */
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
@@ -126,6 +126,32 @@ struct fsfilt_operations {
                                      char *, int, unsigned long, unsigned long,
                                      unsigned);
         int     (* fs_del_dir_entry)(struct obd_device *, struct dentry *);
+        /*snap operations*/
+        int     (* fs_is_redirector)(struct inode *inode);
+        int     (* fs_is_indirect)(struct inode *inode);
+        
+        struct inode * (* fs_create_indirect)(struct inode *pri, int index,
+                                              unsigned int gen, struct inode *parent,
+                                              int del);
+        struct inode * (* fs_get_indirect)(struct inode *pri, int *table,
+                                          int slot);
+        ino_t   (* fs_get_indirect_ino)(struct inode *pri, int index);
+        int     (* fs_destroy_indirect)(struct inode *pri, int index,
+                                        struct inode *next_ind);
+        int     (* fs_restore_indirect)(struct inode *pri, int index);
+        int     (* fs_iterate)(struct super_block *sb,
+                              int (*repeat)(struct inode *inode, void *priv),
+                              struct inode **start, void *priv, int flag);
+        int     (* fs_copy_block)(struct inode *dst, struct inode *src, int blk);
+        int     (* fs_set_indirect)(struct inode *pri, int index,
+                                    ino_t ind_ino, ino_t parent_ino);
+        int     (* fs_snap_feature)(struct super_block *sb, int feature, int op);
+        int     (* fs_set_snap_info)(struct super_block *sb, struct inode *inode, 
+                                     void* key, __u32 keylen, void *val, 
+                                     __u32 *vallen); 
+        int     (* fs_get_snap_info)(struct super_block *sb, struct inode *inode,
+                                     void* key, __u32 keylen, void *val, 
+                                     __u32 *vallen); 
 };
 
 extern int fsfilt_register_ops(struct fsfilt_operations *fs_ops);
@@ -175,6 +201,10 @@ extern void fsfilt_put_ops(struct fsfilt_operations *fs_ops);
 #define KML_CACHE_LINK          0x39
 #define KML_CACHE_NOOP          0x3f
 
+/*for fsfilt set md ea*/
+#define LMV_EA  1
+#define LOV_EA  0
+
 static inline void *
 fsfilt_start_ops(struct fsfilt_operations *ops, struct inode *inode,
                  int op, struct obd_trans_info *oti, int logs)
@@ -335,19 +365,18 @@ static inline int fsfilt_setup(struct obd_device *obd,
                 return obd->obd_fsops->fs_setup(obd, fs);
         return 0;
 }
-
 static inline int
 fsfilt_set_md(struct obd_device *obd, struct inode *inode,
-              void *handle, void *md, int size)
+              void *handle, void *md, int size, int flags)
 {
-        return obd->obd_fsops->fs_set_md(inode, handle, md, size);
+        return obd->obd_fsops->fs_set_md(inode, handle, md, size, flags);
 }
 
 static inline int
 fsfilt_get_md(struct obd_device *obd, struct inode *inode,
-              void *md, int size)
+              void *md, int size, int flags)
 {
-        return obd->obd_fsops->fs_get_md(inode, md, size);
+        return obd->obd_fsops->fs_get_md(inode, md, size, flags);
 }
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
index dfa3096..738eb6f 100644 (file)
@@ -1,9 +1,40 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (C) 2001-2003 Cluster File Systems, Inc. <info@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *   smfs data structures.
+ *   See also lustre_idl.h for wire formats of requests.
+ *
+ */
+
 #ifndef __LUSTRE_SMFS_H
 #define __LUSTRE_SMFS_H
 
+struct snap_inode_info {
+       int sn_flags;           /* the flags indicated inode type */
+       int sn_gen;             /*the inode generation*/
+};
+
 struct smfs_inode_info {
         struct inode *smi_inode;
         __u32  smi_flags;
+       struct snap_inode_info sm_sninfo;
 };
 
 struct journal_operations {
@@ -40,6 +71,7 @@ struct mds_kml_pack_info {
         int mpi_size[4];
         int mpi_total_size;
 };
+
 struct smfs_super_info {
         struct super_block       *smsi_sb;
         struct vfsmount          *smsi_mnt;         /* mount the cache kern */
@@ -54,9 +86,10 @@ struct smfs_super_info {
         char                     *smsi_cache_ftype; /* cache file system type */
         char                     *smsi_ftype;       /* file system type */
        struct obd_export        *smsi_exp;         /* file system obd exp */
-        smfs_pack_rec_func   smsi_pack_rec[PACK_MAX]; /* sm_pack_rec type ops */
-        __u32                     smsi_flags;       /* flags */
-        __u32                     smsi_ops_check;
+       struct snap_info         *smsi_snap_info;    /* snap table cow */
+        smfs_pack_rec_func      smsi_pack_rec[PACK_MAX]; /* sm_pack_rec type ops */
+        __u32                    smsi_flags;       /* flags */
+        __u32                    smsi_ops_check;
 };
 
 #define SMFS_FILE_TYPE "smfs"
@@ -104,6 +137,9 @@ struct fs_extent{
                         (inode->i_sb->s_fs_info))->sm_cache_fsfilt)
 #endif
 
+#define I2SNAPOPS(inode) ((S2SMI(inode->i_sb))->smsi_snap_info->snap_cache_fsfilt) 
+
+#define S2SNAPI(sb) (S2SMI(sb)->smsi_snap_info)
 #define F2SMFI(file) ((struct smfs_file_info *)((file->private_data)))
 #define F2CF(file) (((struct smfs_file_info *) ((file->private_data)))->c_file)
 #define SIZE2BLKS(size, inode) ((size + (I2CI(inode)->i_blksize)) >> (I2CI(inode)->i_blkbits))
@@ -113,7 +149,8 @@ struct fs_extent{
 #define SM_INIT_REC             0x2
 #define SM_CACHE_HOOK           0x4
 #define SM_OVER_WRITE           0x8
-#define SM_DIRTY_WRITE         0x10
+#define SM_DIRTY_WRITE          0x10
+#define SM_DO_COW              0x20
 
 #define SMFS_DO_REC(smfs_info) (smfs_info->smsi_flags & SM_DO_REC)
 #define SMFS_SET_REC(smfs_info) (smfs_info->smsi_flags |= SM_DO_REC)
@@ -143,6 +180,13 @@ struct fs_extent{
 #define SMFS_SET_INODE_DIRTY_WRITE(inode) (I2SMI(inode)->smi_flags |= SM_DIRTY_WRITE)
 #define SMFS_CLEAN_INODE_DIRTY_WRITE(inode) (I2SMI(inode)->smi_flags &= ~SM_DIRTY_WRITE)
 
+#define SMFS_DO_COW(smfs_info) (smfs_info->smsi_flags & SM_DO_COW)
+#define SMFS_SET_COW(smfs_info) (smfs_info->smsi_flags |= SM_DO_COW)
+#define SMFS_CLEAN_COW(smfs_info) (smfs_info->smsi_flags &= ~SM_DO_COW)
+
+#define SMFS_SET_INODE_COW(inode) (I2SMI(inode)->smi_flags |= SM_DO_COW)
+#define SMFS_DO_INODE_COW(inode) (I2SMI(inode)->smi_flags & SM_DO_COW)
+#define SMFS_CLEAN_INODE_COW(inode) (I2SMI(inode)->smi_flags &= ~SM_DO_COW)
 
 #define LVFS_SMFS_BACK_ATTR "lvfs_back_attr"
 
@@ -358,7 +402,6 @@ static inline int lookup_by_path(char *path, int flags, struct nameidata *nd)
 }
 
 /*FIXME there should be more conditions in this check*/
-
 static inline int smfs_do_rec(struct inode *inode)
 {
         struct super_block *sb = inode->i_sb;
@@ -369,6 +412,7 @@ static inline int smfs_do_rec(struct inode *inode)
                 return 1;
         return 0;
 }
+
 static inline int smfs_cache_hook(struct inode *inode)
 {
         struct smfs_super_info  *smfs_info = I2CSB(inode);
@@ -379,6 +423,17 @@ static inline int smfs_cache_hook(struct inode *inode)
         else
                 return 0;
 }
+
+static inline int smfs_do_cow(struct inode *inode)
+{
+        struct super_block *sb = inode->i_sb;
+        struct smfs_super_info *smfs_info = S2SMI(sb);
+
+        if (SMFS_DO_COW(smfs_info) && SMFS_DO_INODE_COW(inode))
+                return 1;
+        return 0;
+}
+
 /* XXX BUG 3188 -- must return to one set of opcodes */
 #define SMFS_TRANS_OP(inode, op)                \
 {                                               \
@@ -398,5 +453,7 @@ extern int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa);
 extern int smfs_rec_md(struct inode *inode, void * lmm, int lmm_size);
 extern int smfs_rec_unpack(struct smfs_proc_args *args, char *record,
                            char **pbuf, int *opcode);
+       
+int smfs_cow(struct inode *dir, struct dentry *dentry, int op);
 
 #endif /* _LUSTRE_SMFS_H */
diff --git a/lustre/include/linux/lustre_snap.h b/lustre/include/linux/lustre_snap.h
new file mode 100644 (file)
index 0000000..3962a52
--- /dev/null
@@ -0,0 +1,172 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (C) 2001-2003 Cluster File Systems, Inc. <info@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * SNAP data structures.
+ * See also lustre_idl.h for wire formats of requests.
+ *
+ */
+/* maximum number of snapshots available for users */
+
+#ifndef __LUSTRE_SNAP_H
+#define __LUSTRE_SNAP_H
+
+#define MAX_SNAPS       20
+#define SNAP_ATTR       "@snap"
+struct snap_ea{
+        int   generation;
+        ino_t prev_ino;
+        ino_t next_ino;
+        ino_t ino[MAX_SNAPS+1]; /* including current snapshot */
+        ino_t parent_ino[MAX_SNAPS+1];
+};
+#define MAX_SNAP_DATA (sizeof(struct snap_ea))
+
+/*
+ * Check if the EA @name is Snap EA or not.
+ * Snap EA includes the SNAP_ATTR, SNAP_NEW_INO_ATTR and DISK_SNAP_META_ATTR
+ */
+
+#define IS_SNAP_EA(name) ( (!strcmp((name), SNAP_ATTR)) ||             \
+                          (!strcmp((name), DISK_SNAP_META_ATTR)))
+
+
+/* file system features */
+#define SNAP_FEATURE_COMPAT_SNAPFS              0x0010
+#define SNAP_FEATURE_COMPAT_BLOCKCOW            0x0020
+
+/* constants for snap_feature operations */
+#define SNAP_CLEAR_FEATURE     0x0
+#define SNAP_SET_FEATURE       0x1
+#define SNAP_HAS_FEATURE       0x2
+
+/* snap flags for inode, within 1 byte range, each occupy 1 bit */
+#define SNAP_INO_MAGIC 0x88            /* magic for snap inode */
+#define SNAP_COW_FLAG  0x01            /* snap redirected inode */
+#define SNAP_DEL_FLAG  0x02            /* snap deleted inode */
+#define SNAP_TABLE_FLAG        0x04            /* snap table inode */
+#define SNAP_PRI_FLAG  0x08            /* primary inode */
+
+/* no snapfs attributes for get_indirect_ino */
+#define ENOSNAPATTR    320
+
+/* constants used by iterator */
+#define SNAP_ITERATE_ALL_INODE          0x0
+#define SNAP_ITERATE_COWED_INODE        0x1
+
+/* constants used by create_indirect */
+#define SNAP_CREATE_IND_NORMAL         0x0
+#define        SNAP_CREATE_IND_DEL_PRI         0x1
+
+/* the data structure represent in the xfs_dinode.pad
+       offset  0:      magic   (1 byte)
+       offset  1:      flag    (1 byte)
+       offset  2:      gen     (4 bytes)
+       offset  6:      unused
+ */
+#define SIZEOF_MAGIC           1
+#define SIZEOF_FLAG            1
+#define SIZEOF_GENERATION      4
+
+#define MAGIC_OFFSET           0
+#define FLAG_OFFSET            1
+#define GENERATION_OFFSET      2
+
+#define SNAP_GET_DINODE_MAGIC(dinode)  \
+               (((__u8*)(dinode)->di_pad)[MAGIC_OFFSET])
+#define SNAP_SET_DINODE_MAGIC(dinode)  \
+               ((__u8*)(dinode)->di_pad)[MAGIC_OFFSET] = (SNAP_INO_MAGIC)
+#define SNAP_GET_DINODE_FLAG(dinode)   \
+               (((__u8*)(dinode)->di_pad)[FLAG_OFFSET])
+#define SNAP_SET_DINODE_FLAG(dinode, flag)     \
+               (((__u8*)(dinode)->di_pad)[FLAG_OFFSET] |= (flag))
+#define SNAP_CLEAR_DINODE_FLAG(dinode, flag)   \
+               (((__u8*)(dinode)->di_pad)[FLAG_OFFSET] &= ~(flag))
+#define SNAP_GET_DINODE_GEN(dinode)    \
+               (le32_to_cpu(*(__u32*)(&((__u8*)(dinode)->di_pad)[GENERATION_OFFSET])))
+#define SNAP_SET_DINODE_GEN(dinode, gen)       \
+               *(__u32*)(&((__u8*)(dinode)->di_pad)[GENERATION_OFFSET]) = cpu_to_le32(gen)
+#define SNAP_VERSION(a,b,c)             \
+                (((a & 0xFF) << 16) | ((b & 0xFF) << 8) | (c & 0xFF))
+#define SNAP_VERSION_MAJOR(v)           \
+                ((v >> 16) & 0xFF)
+#define SNAP_VERSION_MINOR(v)           \
+                ((v >> 8) & 0xFF)
+#define SNAP_VERSION_REL(v)             \
+                (v & 0xFF)
+                                                                                                                                                                                                     
+                                                                                                                                                                                                     
+#define EXT3_EA_TRANS_BLOCKS            EXT3_DATA_TRANS_BLOCKS
+#define EXT3_SETMETA_TRANS_BLOCKS       EXT3_DATA_TRANS_BLOCKS
+#define EXT3_NEWINODE_TRANS_BLOCKS      10
+#define SNAP_INSERTLIST_TRANS_BLOCKS    (2 * EXT3_EA_TRANS_BLOCKS + 1)
+#define SNAP_DELETELIST_TRANS_BLOCKS    (2 * EXT3_EA_TRANS_BLOCKS + 2)
+#define SNAP_COPYBLOCK_TRANS_BLOCKS     (EXT3_DATA_TRANS_BLOCKS)
+#define SNAP_MIGRATEDATA_TRANS_BLOCKS   2
+#define SNAP_SETIND_TRANS_BLOCKS        (SNAP_INSERTLIST_TRANS_BLOCKS + 1)
+#define SNAP_ADDORPHAN_TRANS_BLOCKS     2
+#define SNAP_REMOVEORPHAN_TRANS_BLOCKS  1
+#define SNAP_RESTOREORPHAN_TRANS_BLOCKS (EXT3_EA_TRANS_BLOCKS + \
+                                         SNAP_DELETELIST_TRANS_BLOCKS + \
+                                         EXT3_NEWINODE_TRANS_BLOCKS + \
+                                         2 * SNAP_MIGRATEDATA_TRANS_BLOCKS)
+#define SNAP_BIGCOPY_TRANS_BLOCKS       (2 * EXT3_DATA_TRANS_BLOCKS)
+#define SNAP_CREATEIND_TRANS_BLOCKS     (EXT3_NEWINODE_TRANS_BLOCKS + \
+                                         SNAP_MIGRATEDATA_TRANS_BLOCKS + \
+                                         SNAP_SETIND_TRANS_BLOCKS + \
+                                         SNAP_BIGCOPY_TRANS_BLOCKS + 3)
+#define SNAP_MIGRATEBLK_TRANS_BLOCKS    2
+#define SNAP_DESTROY_TRANS_BLOCKS       (SNAP_DELETELIST_TRANS_BLOCKS + \
+                                         EXT3_EA_TRANS_BLOCKS + 2)
+#define SNAP_RESTORE_TRANS_BLOCKS       (EXT3_NEWINODE_TRANS_BLOCKS + \
+                                         2 * SNAP_MIGRATEDATA_TRANS_BLOCKS + 1)
+/*Snap Table*/
+#define SNAP_MAX               32      
+#define SNAP_MAX_TABLES        32      
+#define SNAP_MAX_NAMELEN       64
+
+#define MAX_SNAPTABLE_COUNT     "MAXSnapCount"
+#define SNAP_TABLE_MAGIC       0x19760218
+#define SNAPTABLE_INFO          "snaptable"
+#define SNAP_GENERATION         "snap_generation"
+struct snap {
+        time_t          sn_time;
+        unsigned int    sn_index;
+        unsigned int    sn_gen;
+        unsigned int    sn_flags;
+        char    name[SNAP_MAX_NAMELEN];
+};
+
+struct snap_table {
+       unsigned int    sntbl_magic;
+       unsigned int    sntbl_count;
+       unsigned int    sntbl_max_count;
+       unsigned int    sntbl_generation;
+       struct  snap    sntbl_items[0];
+};
+
+struct snap_info {
+        struct fsfilt_operations *snap_fsfilt;  
+        struct fsfilt_operations *snap_cache_fsfilt;  
+       struct semaphore         sntbl_sema;
+       spinlock_t               sntbl_lock;
+        struct snap_table        *sntbl;
+};
+
+#endif /*_LUSTRE_SNAP_H*/
index 0d68a45..b183bf6 100644 (file)
@@ -56,7 +56,7 @@
 #define EXT3_DEL_FL                     0x00200000 /* inode is deleting in snapshot */
 
 #define EXT3_SNAP_ATTR "@snap"
-#define EXT3_SNAP_GENERATION_ATTR "@snap_generation"
+#define EXT3_SNAP_GENERATION "@snap_generation"
 #define EXT3_MAX_SNAPS 20
 #define EXT3_MAX_SNAP_DATA (sizeof(struct snap_ea))
 #define EXT3_SNAP_INDEX EXT3_XATTR_INDEX_LUSTRE
@@ -69,6 +69,8 @@
 
 #define EXT3_FEATURE_COMPAT_SNAPFS             0x0010
 #define EXT3_FEATURE_COMPAT_BLOCKCOW           0x0020
+/*snaptable info for EXT3*/
+#define EXT3_SNAPTABLE_EA       "@snaptable"
                                                                                                                                                                                                      
 /* NOTE: these macros are close dependant on the structure of snap ea */
 #define SNAP_CNT_FROM_SIZE(size)       ((((size)-sizeof(ino_t)*2)/2)/sizeof(ino_t))
@@ -232,7 +234,7 @@ out_unlock:
        return err;
 }
 
-static int fsfilt_ext3_set_generation(struct inode *inode, unsigned long gen)
+static int ext3_set_generation(struct inode *inode, unsigned long gen)
 {
         handle_t *handle;
         int err = 0;
@@ -243,7 +245,7 @@ static int fsfilt_ext3_set_generation(struct inode *inode, unsigned long gen)
                 RETURN(-EINVAL);
 
         err = ext3_xattr_set(handle, inode, EXT3_SNAP_INDEX, 
-                             EXT3_SNAP_GENERATION_ATTR,
+                             EXT3_SNAP_GENERATION,
                              (char*)&gen, sizeof(int), 0);
         if (err < 0) {
                 CERROR("ino %lu, set_ext_attr err %d\n", inode->i_ino, err);
@@ -253,26 +255,6 @@ static int fsfilt_ext3_set_generation(struct inode *inode, unsigned long gen)
         ext3_journal_stop(handle, inode);
         RETURN(0);
 }
-                                                                                                                                                                                                     
-static int fsfilt_ext3_get_generation(struct inode *inode)
-{
-        int err, gen;
-        ENTRY;
-
-        err = ext3_xattr_get(inode, EXT3_SNAP_INDEX, EXT3_SNAP_GENERATION_ATTR,
-                             (char*)&gen, sizeof(gen));
-        if (err < 0) {
-                if (err == -ENODATA) {
-                        RETURN(0);
-                } else {
-                        CERROR("can not get generation from %lu \n", 
-                               inode->i_ino);
-                        RETURN(err);
-                }
-        }
-
-        RETURN(gen);
-}
 
 /*
  * Copy inode metadata from one inode to another, excluding blocks and size.
@@ -624,7 +606,7 @@ static struct inode* fsfilt_ext3_create_indirect(struct inode *pri, int index,
        CDEBUG(D_INODE, "got new inode %lu\n", ind->i_ino);
        ind->i_rdev = pri->i_rdev;
        ind->i_op = pri->i_op;
-       fsfilt_ext3_set_generation(ind, (unsigned long)gen);
+       ext3_set_generation(ind, (unsigned long)gen);
        /* If we are deleting the primary inode, we want to ensure that it is
         * written to disk with a non-zero link count, otherwise the next iget
         * and iput will mark the inode as free (which we don't want, we want
@@ -1455,231 +1437,72 @@ static int fsfilt_ext3_iterate(struct super_block *sb,
        }
 }
 
-static int find_snap_meta_index(
-       struct table_snap_meta_data *snap_meta,
-       char                        *name)
-{
-       int i;
-
-       /* table max length is null*/
-       for( i = 0; i < TABLE_ITEM_COUNT; i++){
-               /*compare name Max name Length 15*/
-               if (snap_meta->array[i].name[0]){
-                       if(!strncmp(snap_meta->array[i].name, name, strlen(name)))
-                               return i;
-               }
-       }
-       return -1; /* can not find */
-}
-
-int set_snap_meta_index(
-       struct table_snap_meta_data *snap_meta,
-       char                        *name,
-       int                          size)
+static int fsfilt_ext3_get_snap_info(struct super_block *sb,struct inode *inode,
+                                     void *key, __u32 keylen, void *val, 
+                                     __u32 *vallen) 
 {
-       int i;
-
-       for( i = 0; i < TABLE_ITEM_COUNT; i++){
-               /*compare name Max name Length 15*/
-               if (! snap_meta->array[i].name[0]){
-                       strcpy(snap_meta->array[i].name, name);
-                       snap_meta->count ++;
-                       snap_meta->array[i].start = i * TABLE_ITEM_SIZE + 1;
-                       snap_meta->array[i].len   = size;
-                       return i;
-               }
-       }
-       return -1; /* can not find */
-}
-
-static int fsfilt_ext3_get_meta_attr(struct super_block *sb, char* name, 
-                                     char* buf, int *size)
-{
-        struct inode                   *inode;
-       struct buffer_head              *bh = NULL;
-       struct table_snap_meta_data     *s_attr;
-       unsigned long                   map_len = 0,  left_size;
-        int                            i, error = 0, index = 0;
-        ino_t                          ino;
-        ENTRY;        
-       
-       ino = SB_SNAPTABLE_INO(sb);     
-       if (ino == 0){
-               CERROR("No table file \n");
-               RETURN(-ENODATA);
-       } 
-
-       inode = iget(sb, ino);
-        if(!inode || is_bad_inode(inode)){
-                CERROR("unable to get table ino %lu\n", ino);
-                GOTO(out_iput, error = -ENOENT);
-       }
-       /*read the table from the table inode*/
-       bh = ext3_bread(NULL, inode, 0, 0, &error);
-       if (!bh) {
-               CERROR("read table ino %lu, error %d\n", ino, error);
-                GOTO(out_iput, error = -ENODATA);
-       }
-       s_attr = (struct table_snap_meta_data *)(bh->b_data);
-       index = find_snap_meta_index(s_attr, name);
-       if (index < 0) {
-               CDEBUG(D_INFO, "not exit %s meta attr of table ino %lu \n", 
-                      name, inode->i_ino);
-               GOTO(out_iput, error = 0);
-       }
-       if (!buf || *size < s_attr->array[index].len) {
-               /*return the size of this meta attr */
-               error = s_attr->array[index].len;               
-               GOTO(out_iput, error);
-       }
-       map_len = (s_attr->array[index].len + sb->s_blocksize - 1) 
-                  >> sb->s_blocksize_bits;     
-       left_size = *size;
-       for(i = 0; i < map_len; i++) {
-               struct buffer_head *array_bh = NULL;
-
-               array_bh = ext3_bread(NULL, inode, 
-                                     s_attr->array[index].start + i,
-                                     0, &error);
-               if (!array_bh) {
-                       CERROR("ino %lu read snap attr offset %d error %d \n",
-                              inode->i_ino, (s_attr->array[index].start + i), 
-                               error);
-                       GOTO(out_iput, error);
-               }
-               if (left_size >= sb->s_blocksize) 
-                       memcpy(buf, array_bh->b_data, sb->s_blocksize);
-               else
-                       memcpy(buf, array_bh->b_data, left_size);
-               left_size -= sb->s_blocksize;
-               brelse(array_bh);
-       }
-       *size = s_attr->array[index].len;
-out_iput:
-       brelse(bh);
-       iput(inode);
+        int rc = 0;
+        ENTRY;
 
-       RETURN(error);
+        if (!vallen || !val) {
+                CERROR("val and val_size is 0!\n");
+                RETURN(-EFAULT);
+        }
+        if (keylen >= strlen(MAX_SNAPTABLE_COUNT) 
+            && strcmp(key, MAX_SNAPTABLE_COUNT) == 0) {
+                /*FIXME should get it from the EA_size*/
+               *((__u32 *)val) = EXT3_MAX_SNAPS; 
+               *vallen = sizeof(int);
+               RETURN(rc);
+        } else if (keylen >= strlen(SNAPTABLE_INFO) 
+                   && strcmp(key, SNAPTABLE_INFO) == 0) {
+                rc = ext3_xattr_get(sb->s_root->d_inode, EXT3_SNAP_INDEX, 
+                                    EXT3_SNAPTABLE_EA, val, *vallen); 
+                RETURN(rc);
+        } else if (keylen >= strlen(SNAP_GENERATION) 
+                   && strcmp(key, SNAP_GENERATION) == 0) {
+                
+                rc = ext3_xattr_get(inode, EXT3_SNAP_INDEX,EXT3_SNAP_GENERATION,
+                                    (char *)val, *vallen);
+                RETURN(rc);
+        } 
+        RETURN(-EINVAL);
 } 
 
-static int fsfilt_ext3_set_meta_attr(struct super_block *sb, char* name, 
-                                    char* buf, int size)
+static int fsfilt_ext3_set_snap_info(struct super_block *sb,struct inode *inode, 
+                                     void *key, __u32 keylen, void *val, 
+                                     __u32 *vallen)
 {
-        struct inode                   *inode = NULL;
-        handle_t                       *handle = NULL;
-       struct  buffer_head             *bh = NULL;
-       struct table_snap_meta_data     *s_attr = NULL;
-       unsigned long                   ino;
-        int                            i, index = 0, error = 0;
-       unsigned long                   new_len = 0, left_size; 
-        
+        int rc = 0;
         ENTRY;
-               
-       ino = SB_SNAPTABLE_INO(sb);
-      
-       if (ino == 0 && !buf) {
-               CDEBUG(D_INODE, "no table ino \n");
-               RETURN(0);
-       }
-       
-       handle = ext3_journal_start(sb->s_root->d_inode, 
-                                    2 * EXT3_SETMETA_TRANS_BLOCKS);
-       if(!handle)
-               RETURN(-EINVAL);
-
-       if (ino == 0) {
-               /*create table inode update table ino*/
-               inode = ext3_new_inode(handle, sb->s_root->d_inode, (int)S_IFREG, 0);
-               if (!inode)
-                       RETURN(-EINVAL);
-               lock_super(sb);
-               ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-               SB_SNAPTABLE_INO(sb) = inode->i_ino;
-               ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-               sb->s_dirt = 1;
-               unlock_super(sb);
+        
+        if (!vallen || !val) {
+                CERROR("val and val_size is 0!\n");
+                RETURN(-EFAULT);
+        }
 
-       } else {
-               inode = iget(sb, ino);
-               if (!inode || !inode->i_nlink || is_bad_inode(inode)) {
-                       CERROR("unable to get table ino %lu\n", ino);
-                       GOTO(exit, error = -ENOENT);
-               }
-       }
-       /*read the table from the table inode,
-        * If can not find the block just create it*/
-       bh = ext3_bread(handle, inode, 0, 1, &error);
-       if (!bh) {
-               CERROR("read table ino %lu, error %d\n", ino, error);
-               GOTO(exit, error = -ENODATA);
-       }
-       s_attr = (struct table_snap_meta_data *)(bh->b_data);
-       index = find_snap_meta_index(s_attr, name);
-       if (index < 0 && !buf) {        
-               CDEBUG(D_INODE, "%s meta attr of table ino %lu do not exist\n", 
-                      name, inode->i_ino);
-               brelse(bh);
-               GOTO(exit, error = 0);
-       }
-       if (!buf) {
-               CDEBUG(D_INODE, "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
-                */
-               ext3_journal_get_write_access(handle, bh);
-               memset(s_attr->array[index].name, 0, TABLE_ITEM_NAME_SIZE);
-               s_attr->array[index].len = 0;
-               s_attr->count --;
-               ext3_journal_dirty_metadata(handle, bh);
-               brelse(bh);
-               GOTO(exit, error);
-       }
-       new_len = (size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
-       /*find the place to put this attr in that index*/
-       ext3_journal_get_write_access(handle, bh);
-       if (index < 0){
-               index = set_snap_meta_index(s_attr, name, size);
-               if (index < 0){
-                       CERROR("table full of ino %lu \n", inode->i_ino);
-                       brelse(bh);
-                       GOTO(exit, error = index);
-               }
-       }
-       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++) {
-               struct buffer_head *array_bh = NULL;
-               
-               array_bh = ext3_bread(handle, inode, 
-                                     s_attr->array[index].start + i, 1, &error);
-               if (!array_bh) {
-                       CERROR("inode %lu Can not get the block of attr %s\n",  
-                               inode->i_ino, name);
-                       brelse(array_bh);
-                       GOTO(exit, error = -ENOSPC);
-               }
-               ext3_journal_get_write_access(handle, array_bh);
-               if (left_size > inode->i_sb->s_blocksize)       
-                       memcpy(array_bh->b_data, buf, inode->i_sb->s_blocksize);
-               else
-                       memcpy(array_bh->b_data, buf, left_size);
-               ext3_journal_dirty_metadata(handle, array_bh);
-               left_size -= inode->i_sb->s_blocksize;
-               brelse(array_bh);
-       }
-exit:
-        if (handle)
-               ext3_journal_stop(handle, sb->s_root->d_inode); 
-       iput(inode);
-       RETURN(error);
+        if (keylen >= strlen(SNAPTABLE_INFO) 
+            && strcmp(key, SNAPTABLE_INFO) == 0) {
+                struct inode *inode = sb->s_root->d_inode;
+                handle_t *handle;
+                handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
+                if( !handle )
+                        RETURN(-EINVAL);
+                rc = ext3_xattr_set(handle, inode, EXT3_SNAP_INDEX, 
+                                    EXT3_SNAPTABLE_EA, val, *vallen, 0); 
+               ext3_journal_stop(handle,inode);
+                
+                RETURN(rc);
+        } else if (keylen >= strlen(SNAP_GENERATION) 
+                   && strcmp(key, SNAP_GENERATION) == 0) {
+                rc = ext3_set_generation(inode, *(int*)val);
+                
+                RETURN(rc); 
+        }
+        RETURN(-EINVAL);
 }
 
-
 struct fsfilt_operations fsfilt_ext3_snap_ops = {
         .fs_type                = "ext3_snap",
         .fs_owner               = THIS_MODULE,
@@ -1690,14 +1513,12 @@ struct fsfilt_operations fsfilt_ext3_snap_ops = {
        .fs_is_redirector       = fsfilt_ext3_is_redirector,
        .fs_is_indirect         = fsfilt_ext3_is_indirect,
         .fs_get_indirect_ino    = fsfilt_ext3_get_indirect_ino,
-        .fs_set_generation      = fsfilt_ext3_set_generation,
-        .fs_get_generation      = fsfilt_ext3_get_generation,
         .fs_destroy_indirect    = fsfilt_ext3_destroy_indirect,
         .fs_restore_indirect    = fsfilt_ext3_restore_indirect,
         .fs_iterate             = fsfilt_ext3_iterate,
         .fs_copy_block          = fsfilt_ext3_copy_block,
-        .fs_set_meta_attr       = fsfilt_ext3_set_meta_attr,
-        .fs_get_meta_attr       = fsfilt_ext3_get_meta_attr,
+        .fs_set_snap_info       = fsfilt_ext3_set_snap_info,
+        .fs_get_snap_info       = fsfilt_ext3_get_snap_info,
 };
 
 static int __init fsfilt_ext3_snap_init(void)
index 2d74ae4..bd300f4 100644 (file)
@@ -137,7 +137,7 @@ static int fsfilt_smfs_set_indirect(struct inode *inode, int index,
 static int fsfilt_smfs_snap_feature(struct super_block *sb, int feature, 
                                     int op)
 {
-        struct fsfilt_operations *snap_fsfilt = S2SMI(sb)->sm_snap_fsfilt;
+        struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
         struct super_block       *csb = S2CSB(sb);
         int                      rc = -EIO;
         
@@ -215,50 +215,6 @@ static ino_t fsfilt_smfs_get_indirect_ino(struct inode *inode, int index)
         
         RETURN(rc);
 }
-static int fsfilt_smfs_set_generation(struct inode *inode, 
-                                      unsigned long new_gen)
-{
-        struct fsfilt_operations *snap_fsfilt = I2SNAPOPS(inode);
-        struct inode *cache_inode = NULL;
-        int    rc = -EIO;
-        ENTRY;
-
-        if (snap_fsfilt == NULL)
-                RETURN(rc);
-
-        cache_inode = I2CI(inode);
-        if (!cache_inode)
-                RETURN(rc);
-
-        pre_smfs_inode(inode, cache_inode);
-        if (snap_fsfilt->fs_set_generation)
-                rc = snap_fsfilt->fs_set_generation(cache_inode, new_gen);
-        post_smfs_inode(inode, cache_inode);
-        
-        RETURN(rc);
-}
-
-static int fsfilt_smfs_get_generation(struct inode *inode)
-{
-        struct fsfilt_operations *snap_fsfilt = I2SNAPOPS(inode);
-        struct inode *cache_inode = NULL;
-        int    rc = -EIO;
-        ENTRY;
-
-        if (snap_fsfilt == NULL)
-                RETURN(rc);
-
-        cache_inode = I2CI(inode);
-        if (!cache_inode)
-                RETURN(rc);
-
-        pre_smfs_inode(inode, cache_inode);
-        if (snap_fsfilt->fs_get_generation)
-                rc = snap_fsfilt->fs_get_generation(cache_inode);
-        post_smfs_inode(inode, cache_inode);
-        
-        RETURN(rc);
-}
 
 static int fsfilt_smfs_destroy_indirect(struct inode *inode, int index,
                                         struct inode *next_ind)
@@ -318,7 +274,7 @@ static int fsfilt_smfs_iterate(struct super_block *sb,
                                int (*repeat)(struct inode *inode, void *priv),
                                struct inode **start, void *priv, int flag)
 {
-        struct fsfilt_operations *snap_fsfilt = S2SMI(sb)->sm_snap_fsfilt;
+        struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
         struct super_block       *csb = S2CSB(sb);
         int                      rc = -EIO;
         ENTRY;
@@ -366,38 +322,56 @@ static int fsfilt_smfs_copy_block(struct inode *dst, struct inode *src, int blk)
         RETURN(rc); 
 }
 
-static int fsfilt_smfs_set_meta_attr(struct super_block *sb, char *name,
-                                     char *buf, int size)
+static int fsfilt_smfs_set_snap_info(struct super_block *sb,struct inode *inode, 
+                                     void* key, __u32 keylen, void *val, 
+                                     __u32 *vallen)
 {
-        struct fsfilt_operations *snap_fsfilt = S2SMI(sb)->sm_snap_fsfilt;
-        struct super_block       *csb = S2CSB(sb);
+        struct super_block     *csb = NULL;
+        struct inode           *cache_inode = NULL;  
+        struct fsfilt_operations *snap_fsfilt = NULL; 
         int                      rc = -EIO;
         
+        if (sb) {
+                csb = S2CSB(sb);
+                snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
+        } else if (inode) {
+                cache_inode = I2CI(inode);
+                snap_fsfilt = I2SNAPOPS(inode);
+        }
+
         if (snap_fsfilt == NULL)
                 RETURN(rc);
-        if (!csb)
-                RETURN(rc);
         
-        if (snap_fsfilt->fs_set_meta_attr)
-                rc = snap_fsfilt->fs_set_meta_attr(csb, name, buf, size);
+        if (snap_fsfilt->fs_set_snap_info)
+                rc = snap_fsfilt->fs_set_snap_info(csb, cache_inode, key, 
+                                                   keylen, val, vallen);
 
         RETURN(rc);
 }
 
-static int fsfilt_smfs_get_meta_attr(struct super_block *sb, char *name,
-                                     char *buf, int *size)
+static int fsfilt_smfs_get_snap_info(struct super_block *sb, struct inode *inode,
+                                     void *key, __u32 keylen, void *val,
+                                     __u32 *vallen)
 {
-        struct fsfilt_operations *snap_fsfilt = S2SMI(sb)->sm_snap_fsfilt;
-        struct super_block       *csb = S2CSB(sb);
+        struct super_block     *csb = NULL;
+        struct inode           *cache_inode = NULL;  
+        struct fsfilt_operations *snap_fsfilt = NULL; 
         int                      rc = -EIO;
         
+        if (sb) {
+                csb = S2CSB(sb);
+                snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
+        } else if (inode) {
+                cache_inode = I2CI(inode);
+                snap_fsfilt = I2SNAPOPS(inode);
+        }
+      
         if (snap_fsfilt == NULL)
                 RETURN(rc);
-        if (!csb)
-                RETURN(rc);
-        
-        if (snap_fsfilt->fs_get_meta_attr)
-                rc = snap_fsfilt->fs_get_meta_attr(csb, name, buf, size);
+       
+        if (snap_fsfilt->fs_get_snap_info)
+                rc = snap_fsfilt->fs_get_snap_info(csb, cache_inode, key, 
+                                                   keylen, val, vallen);
 
         RETURN(rc);
 }
@@ -412,14 +386,12 @@ struct fsfilt_operations fsfilt_smfs_snap_ops = {
        .fs_is_redirector       = fsfilt_smfs_is_redirector,
        .fs_is_indirect         = fsfilt_smfs_is_indirect,
         .fs_get_indirect_ino    = fsfilt_smfs_get_indirect_ino,
-        .fs_set_generation      = fsfilt_smfs_set_generation,
-        .fs_get_generation      = fsfilt_smfs_get_generation,
         .fs_destroy_indirect    = fsfilt_smfs_destroy_indirect,
         .fs_restore_indirect    = fsfilt_smfs_restore_indirect,
         .fs_iterate             = fsfilt_smfs_iterate,
         .fs_copy_block          = fsfilt_smfs_copy_block,
-        .fs_set_meta_attr       = fsfilt_smfs_set_meta_attr,
-        .fs_get_meta_attr       = fsfilt_smfs_get_meta_attr,
+        .fs_set_snap_info       = fsfilt_smfs_set_snap_info,
+        .fs_get_snap_info       = fsfilt_smfs_get_snap_info,
 };
 
 
index 67d8edc..9ce7528 100644 (file)
@@ -545,9 +545,11 @@ static struct mod_paths {
         {"lov", "lustre/lov"},
         {"lmv", "lustre/lmv"},
         {"fsfilt_ext3", "lustre/lvfs"},
+        {"fsfilt_snap_ext3", "lustre/lvfs"},
         {"fsfilt_extN", "lustre/lvfs"},
         {"fsfilt_reiserfs", "lustre/lvfs"},
         {"fsfilt_smfs", "lustre/lvfs"},
+        {"fsfilt_snap_smfs", "lustre/lvfs"},
         {"ptlbd", "lustre/ptlbd"},
         {"mgmt_svc", "lustre/mgmt"},
         {"mgmt_cli", "lustre/mgmt"},
index 8dda735..8586c58 100644 (file)
@@ -1,6 +1,6 @@
 MODULES := smfs
 smfs-objs := super.o options.o inode.o cache.o cache_space.o dir.o ioctl.o
 smfs-objs += sysctl.o file.o symlink.o sm_fs.o kml.o journal.o smfs_llog.o
-smfs-objs += mds_kml.o ost_kml.o
-
+smfs-objs += mds_kml.o ost_kml.o 
+@SNAPFS_TRUE@smfs-objs += smfs_cow.o 
 @INCLUDE_RULES@
index 89acd05..4a3c943 100644 (file)
@@ -67,7 +67,7 @@ static int smfs_create(struct inode *dir, struct dentry *dentry,
 
         SMFS_CACHE_HOOK_PRE(CACHE_HOOK_CREATE, handle, dir);
 
-         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+        cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
 
         lock_kernel();
@@ -76,6 +76,8 @@ static int smfs_create(struct inode *dir, struct dentry *dentry,
 
         pre_smfs_inode(dir, cache_dir);
 
+        SMFS_PRE_COW(dir, dentry, REINT_CREATE, "create", rc, exit);
+
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
         if (cache_dir && cache_dir->i_op->create)
                 rc = cache_dir->i_op->create(cache_dir, cache_dentry,
@@ -98,6 +100,7 @@ static int smfs_create(struct inode *dir, struct dentry *dentry,
         post_smfs_inode(dir, cache_dir);
 
         /*Do KML post hook*/
+
         SMFS_KML_POST(dir, dentry, NULL, NULL, REINT_CREATE,
                       "create", rc, exit);
         SMFS_CACHE_HOOK_POST(CACHE_HOOK_CREATE, handle, dir, dentry,
@@ -133,7 +136,7 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry,
 
         handle = smfs_trans_start(dir, KML_CACHE_NOOP, NULL);
         if (IS_ERR(handle))
-                       RETURN(ERR_PTR(-ENOSPC));
+                RETURN(ERR_PTR(-ENOSPC));
 
         SMFS_CACHE_HOOK_PRE(CACHE_HOOK_LOOKUP, handle, dir);
 
diff --git a/lustre/smfs/smfs_cow.c b/lustre/smfs/smfs_cow.c
new file mode 100644 (file)
index 0000000..5b611fb
--- /dev/null
@@ -0,0 +1,318 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (C) 2004 Cluster File Systems, Inc.
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_SM
+
+#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/smp_lock.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_idl.h>
+#include <linux/lustre_fsfilt.h>
+
+#include <linux/lustre_snap.h>
+#include <linux/lustre_smfs.h>
+
+#include "smfs_internal.h"
+#define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + size * sizeof(struct snap)) 
+static int smfs_init_snaptabe(struct super_block *sb)
+{
+        struct snap_info         *snap_info = S2SNAPI(sb);     
+       struct fsfilt_operations *snapops;
+        int                      rc = 0, size, table_size, vallen;
+        
+        ENTRY;
+
+        init_MUTEX(&snap_info->sntbl_sema);
+        /*Initialized table */
+        /*get the maxsize of snaptable*/
+        vallen = sizeof(int);
+        rc = snapops->fs_get_snap_info(sb, NULL, MAX_SNAPTABLE_COUNT,
+                                       strlen(MAX_SNAPTABLE_COUNT), &size, 
+                                       &vallen);
+        if (size == 0) {
+                CERROR("the Max snaptable count should not be zero\n");
+                RETURN(-EINVAL);
+        }
+        
+        table_size = SNAPTABLE_SIZE(size);
+
+        OBD_ALLOC(snap_info->sntbl, table_size);
+
+        if (!snap_info->sntbl) {
+                CERROR("No MEM\n");
+                RETURN(-ENOMEM);
+        }
+        /*get snaptable info*/
+        rc = snapops->fs_get_snap_info(sb, NULL, SNAPTABLE_INFO, 
+                                       strlen(SNAPTABLE_INFO), 
+                                       snap_info->sntbl, &table_size);       
+       
+        if (rc < 0) {
+                if (rc == -ENOATTR) {
+                        snap_info->sntbl->sntbl_count = 1;
+                        CDEBUG(D_INFO, "No snaptable here\n");
+                        RETURN(0);
+                } else {
+                        CERROR("Can not retrive the snaptable from this filesystem\n");
+                        OBD_FREE(snap_info->sntbl, table_size);
+                        RETURN(rc); 
+                }
+        } 
+        if (le32_to_cpu(snap_info->sntbl->sntbl_magic) != SNAP_TABLE_MAGIC) {
+                CERROR("On disk snaptable is not right \n");
+                OBD_FREE(snap_info->sntbl, table_size);
+                RETURN(-EIO);
+        }
+        snap_info->sntbl->sntbl_max_count = size;
+        
+        return 0;
+}
+
+int smfs_cow_init(struct super_block *sb)
+{
+        struct smfs_super_info *smfs_info = S2SMI(sb);
+        struct inode *inode = sb->s_root->d_inode;
+        int rc = 0;
+
+        SMFS_SET_COW(smfs_info);
+        SMFS_SET_INODE_COW(inode);
+      
+        OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
+     
+        if (!smfs_info->smsi_snap_info) 
+                RETURN(-ENOMEM);
+        
+        /*init snap fsfilt operations*/
+        if (!S2SNAPI(sb)->snap_cache_fsfilt) {
+                char *snap_cache_ftype = NULL;
+                int   tmp = strlen(S2SMI(sb)->smsi_cache_ftype) + strlen("_snap");
+                
+                OBD_ALLOC(snap_cache_ftype, tmp + 1);  
+                sprintf(snap_cache_ftype, "%s_snap", S2SMI(sb)->smsi_cache_ftype);
+                S2SNAPI(sb)->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
+                OBD_FREE(snap_cache_ftype, tmp + 1);
+                if (!S2SNAPI(sb)->snap_cache_fsfilt) {
+                        CERROR("Can not get %s fsfilt ops needed by snap\n",
+                               snap_cache_ftype);
+                        RETURN(-EINVAL);
+                }
+        }
+        if (!S2SNAPI(sb)->snap_fsfilt) {
+                char *snap_ftype = NULL;
+                int   tmp = strlen(S2SMI(sb)->smsi_ftype) + strlen("_snap");
+                
+                OBD_ALLOC(snap_ftype, tmp + 1);  
+                sprintf(snap_ftype, "%s_snap", S2SMI(sb)->smsi_ftype);
+                S2SNAPI(sb)->snap_fsfilt = fsfilt_get_ops(snap_ftype);
+                OBD_FREE(snap_ftype, tmp + 1);
+                if (!S2SNAPI(sb)->snap_fsfilt) {
+                        CERROR("Can not get %s fsfilt ops needed by snap\n",
+                               snap_ftype);
+                        RETURN(-EINVAL);
+                }
+        }
+        rc = smfs_init_snaptabe(sb); 
+        
+        RETURN(rc);
+}
+
+int smfs_cow_cleanup(struct super_block *sb)
+{
+        struct smfs_super_info *smfs_info = S2SMI(sb);
+        struct snap_info       *snap_info = S2SNAPI(sb);       
+        struct inode *inode = sb->s_root->d_inode;
+        int rc = 0;
+        ENTRY;
+
+        SMFS_CLEAN_COW(smfs_info);
+        SMFS_CLEAN_INODE_COW(inode);
+
+        if (snap_info->sntbl) {
+                int table_size = SNAPTABLE_SIZE(snap_info->sntbl->sntbl_max_count);
+                OBD_FREE(snap_info->sntbl, table_size);
+        }
+        if (snap_info) 
+               OBD_FREE(snap_info, sizeof(*snap_info)); 
+        
+        RETURN(rc);
+}
+
+/* latest snap: returns 
+   -  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 super_block *sb, struct snap *snap)
+{
+       struct snap_info *snap_info = S2SNAPI(sb);
+       struct snap_table *table = snap_info->sntbl;
+        time_t now = CURRENT_TIME;
+       int i ;
+
+       ENTRY;
+       /* start at the highest index in the superblock snaptime array */ 
+       i = table->sntbl_count - 1;
+
+       snap->sn_index = table->sntbl_items[i].sn_index;
+       snap->sn_time = table->sntbl_items[i].sn_time;
+       snap->sn_gen = table->sntbl_items[i].sn_gen;
+       CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
+              snap->sn_index, snap->sn_time, now);
+        EXIT;
+       return;
+}
+
+/*
+ * Note: this function should be differnet with snap_do_cow.
+ * In smfs_do_cow, we check the EA for whether do cow for that inode.
+ * In smfs_needs_cow, we check whether we do need to do cow. 
+ */
+int smfs_needs_cow(struct inode *inode)
+{
+       struct smfs_inode_info  *smi_info = I2SMI(inode); 
+        struct snap_inode_info *snap_info = NULL;
+        struct snap snap;
+       int index = -1;
+       ENTRY;
+
+       snap_info = &(smi_info->sm_sninfo);
+       
+        snap_last(inode->i_sb, &snap);
+       /* decision .... if the snapshot is more recent than the object,
+        * then any change to the object should cause a COW.
+        */
+       if (snap_info->sn_gen < snap.sn_gen ) 
+               index = snap.sn_index;
+
+       CDEBUG(D_INFO, "snap_needs_cow, ino %lu , get index %d\n",
+              inode->i_ino, index);
+
+       RETURN(index);
+} /* snap_needs_cow */
+
+/*
+ * Make a copy of the data and plug a redirector in between if there
+ * is no redirector yet.
+ */
+int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
+{
+        struct snap_info *snap_info = S2SNAPI(inode->i_sb);    
+       struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
+        struct snap snap;
+       struct inode *ind = NULL;
+
+       ENTRY;
+
+       if (!snapops || !snapops->fs_create_indirect) 
+               RETURN(-EINVAL);
+
+       snap_last(inode->i_sb, &snap);
+       ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen, 
+                                          dparent->d_inode, del);
+       if(!ind)
+               RETURN(-EINVAL);
+
+        I2SMI(ind)->sm_sninfo.sn_flags = 0;
+        I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen;
+        
+        iput(ind);
+        RETURN(0);
+}
+
+int smfs_cow_create(struct inode *dir, struct dentry *dentry)
+{
+        int rc = 0;
+        ENTRY;
+
+        if (smfs_needs_cow(dir) != -1) {
+               CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
+               if ((smfs_cow(dir, dentry->d_parent, 0))) {
+                       CERROR("Do cow error\n");
+                       RETURN(-EINVAL);
+               }
+       }
+        RETURN(rc);
+}
+
+int smfs_cow_setattr(struct inode *dir, struct dentry *dentry)
+{
+        int rc = 0;
+        ENTRY;
+        
+        RETURN(rc);
+}
+
+int smfs_cow_link(struct inode *dir, struct dentry *dentry)
+{
+        int rc = 0;
+        ENTRY;
+        
+        RETURN(rc);
+}
+
+int smfs_cow_unlink(struct inode *dir, struct dentry *dentry)
+{
+        int rc = 0;
+        ENTRY;
+        
+        RETURN(rc);
+}
+
+int smfs_cow_rename(struct inode *dir, struct dentry *dentry)
+{
+        int rc = 0;
+        ENTRY;
+        
+        RETURN(rc);
+}
+
+int smfs_cow_write(struct inode *dir, struct dentry *dentry)
+{
+        int rc = 0;
+        ENTRY;
+        
+        RETURN(rc);
+}
+
+typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry);
+
+static cow_funcs smfs_cow_funcs[REINT_MAX + 1] = {
+        [REINT_SETATTR] smfs_cow_setattr,
+        [REINT_CREATE]  smfs_cow_create,
+        [REINT_LINK]    smfs_cow_link,
+        [REINT_UNLINK]  smfs_cow_unlink,
+        [REINT_RENAME]  smfs_cow_rename,
+        [REINT_WRITE]   smfs_cow_write,
+};
+
+int smfs_cow(struct inode *dir, struct dentry *dentry, int op)
+{
+        return smfs_cow_funcs[op](dir, dentry);
+}
+
index 2c02100..541afbf 100644 (file)
@@ -196,7 +196,9 @@ extern int smfs_llog_add_rec(struct smfs_super_info * sinfo, void *data,
 /*ioctl.c*/
 extern int init_smfs_psdev(void);
 extern void smfs_cleanup_psdev(void);
+/*smfs_cow.c */
 
+extern int smfs_cow_init(struct super_block *sb);
 /* cache_space.c */
 extern int do_cache_manage;
 struct cache_purge_queue {
@@ -306,6 +308,21 @@ static inline int get_active_entry(struct inode *dir, __u64 *active_entry)
                         GOTO(label, rc);                                \
         }                                                               \
 }
+#if CONFIG_SNAP
+/*snap macros*/
+#define SMFS_PRE_COW(dir, dentry, op, name, rc, label)                  \
+do {                                                                    \
+        if (smfs_do_cow(dir) && !rc) {                                  \
+                CDEBUG(D_INODE, "Do %s snap post for dir %lu \n",       \
+                              name, dir->i_ino);                        \
+                rc = smfs_cow(dir, dentry, op);                         \
+                if (rc)                                                 \
+                        GOTO(label, rc);                                \
+        }                                                               \
+} while(0)
+#else
+#define SMFS_PRE_COW(dir, dentry, op, name, rc, label)                 
+#endif 
 
 #endif /*__KERNEL*/
 #endif /* __LINUX_SMFS_H */
index 55d316a..b92eaf7 100644 (file)
@@ -46,7 +46,8 @@
 #include "smfs_internal.h"
 
 static char *smfs_options(char *data, char **devstr, char **namestr,
-                          int *kml, int *cache, char **opts, int *iopen_nopriv)
+                          int *kml, int *cache, char **opts, int *iopen_nopriv,
+                          int *cow)
 {
         char *pos;
         struct option *opt_value = NULL;
@@ -70,6 +71,8 @@ static char *smfs_options(char *data, char **devstr, char **namestr,
                 } else if (!strcmp(opt_value->opt, "iopen_nopriv")) {
                         if (iopen_nopriv != NULL)
                                 *iopen_nopriv = 1;
+                } else if (!strcmp(opt_value->opt, "snap")) {
+                                *cow = 1;
                 } else {
                         break;
                 }
@@ -249,7 +252,7 @@ static int smfs_fill_super(struct super_block *sb,
 
         int iopen_nopriv = 0;
         struct inode *root_inode = NULL;
-        int err = 0, do_rec = 0, cache_hook = 0;
+        int err = 0, do_rec = 0, cache_hook = 0, do_cow = 0;
         char *devstr = NULL, *typestr = NULL, *opts = NULL;
 
         ENTRY;
@@ -262,7 +265,7 @@ static int smfs_fill_super(struct super_block *sb,
         /* read and validate passed options. */
         cache_data = smfs_options(data, &devstr, &typestr,
                                   &do_rec, &cache_hook, &opts,
-                                  &iopen_nopriv);
+                                  &iopen_nopriv, &do_cow);
 
         if (*cache_data)
                 CWARN("smfs_fill_super(): options parsing stoped at "
@@ -280,7 +283,7 @@ static int smfs_fill_super(struct super_block *sb,
 
         if (do_rec) smfs_rec_init(sb);
         if (cache_hook) cache_space_hook_init(sb);
-
+        
         dget(S2CSB(sb)->s_root);
         root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
         root_inode = iget(sb, root_ino);
@@ -294,13 +297,9 @@ static int smfs_fill_super(struct super_block *sb,
                 sm_umount_cache(sb);
                 GOTO(out_err, err=-EINVAL);
         }
-
-        sb->s_root = d_alloc_root(root_inode);
-
-        if (!sb->s_root) {
-                sm_umount_cache(sb);
-                GOTO(out_err, err = -EINVAL);
-        }
+#if CONFIG_SNAP
+        if (do_cow) smfs_cow_init(sb);
+#endif
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
         CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",