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