From 4801dab391279a180ac7601424f79298bdbd0fb3 Mon Sep 17 00:00:00 2001 From: wangdi Date: Wed, 11 Aug 2004 15:37:42 +0000 Subject: [PATCH] 1)add .snap namespace to smfs 2)some cleanup in smfs --- lustre/include/linux/lustre_fsfilt.h | 26 +++-- lustre/include/linux/lustre_idl.h | 3 +- lustre/include/linux/lustre_lite.h | 4 + lustre/include/linux/lustre_smfs.h | 55 +++++++++- lustre/include/linux/lustre_snap.h | 39 +++++++- lustre/include/linux/obd_class.h | 1 - lustre/llite/dir.c | 19 +++- lustre/llite/llite_internal.h | 1 + lustre/llite/llite_lib.c | 5 +- lustre/llite/namei.c | 5 +- lustre/lvfs/fsfilt_smfs.c | 24 ++++- lustre/lvfs/fsfilt_snap_ext3.c | 55 +++++++++- lustre/lvfs/fsfilt_snap_smfs.c | 55 +++++++--- lustre/mdc/mdc_locks.c | 29 +----- lustre/mdc/mdc_request.c | 1 - lustre/mds/handler.c | 24 +++-- lustre/mds/mds_lib.c | 9 ++ lustre/smfs/dir.c | 77 +++++++------- lustre/smfs/file.c | 14 +-- lustre/smfs/smfs_cow.c | 188 +++++++++++++++++++++++++---------- lustre/smfs/smfs_internal.h | 5 +- lustre/smfs/symlink.c | 4 +- 22 files changed, 461 insertions(+), 182 deletions(-) diff --git a/lustre/include/linux/lustre_fsfilt.h b/lustre/include/linux/lustre_fsfilt.h index 002a3f7..5c3f9c5 100644 --- a/lustre/include/linux/lustre_fsfilt.h +++ b/lustre/include/linux/lustre_fsfilt.h @@ -134,26 +134,36 @@ struct fsfilt_operations { int (* fs_is_indirect)(struct inode *inode); struct inode * (* fs_create_indirect)(struct inode *pri, int index, - unsigned int gen, struct inode *parent, + 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); + ino_t (* fs_get_indirect_ino)(struct super_block *sb, ino_t 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_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 inode *inode, void* key, __u32 keylen, - void *val, __u32 *vallen); - int (* fs_get_snap_info)(struct inode *inode, void* key, __u32 keylen, - void *val, __u32 *vallen); + int (* fs_snap_feature)(struct super_block *sb, int feature, + int op); + int (* fs_set_snap_info)(struct inode *inode, void* key, + __u32 keylen, void *val, __u32 *vallen); + int (* fs_get_snap_info)(struct inode *inode, void* key, + __u32 keylen, void *val, __u32 *vallen); int (* fs_set_snap_item)(struct super_block *sb, char *name); + int (* fs_read_dotsnap_dir_page)(struct file *file, char *buf, + size_t count, loff_t *ppos); + int (* fs_dir_ent_size)(char *name); + int (* fs_set_dir_ent)(struct super_block *sb, char *name, + char *buf, int buf_off, int nlen, + size_t count); }; extern int fsfilt_register_ops(struct fsfilt_operations *fs_ops); diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index 8f5bd37..a2d9215 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -515,7 +515,8 @@ struct ll_fid { __u32 generation; __u32 f_type; __u32 mds; - __u32 padding; + __u16 snap_index; + __u16 padding; }; struct mea_old { diff --git a/lustre/include/linux/lustre_lite.h b/lustre/include/linux/lustre_lite.h index b15e74f..20547ce 100644 --- a/lustre/include/linux/lustre_lite.h +++ b/lustre/include/linux/lustre_lite.h @@ -90,6 +90,9 @@ struct ll_inode_info { /* this lock protects s_d_w and p_w_ll */ spinlock_t lli_lock; int lli_send_done_writing; + + int lli_snap_index; + struct list_head lli_pending_write_llaps; struct list_head lli_close_item; @@ -153,6 +156,7 @@ static inline void ll_inode2fid(struct ll_fid *fid, struct inode *inode) mdc_pack_fid(fid, inode->i_ino, inode->i_generation, inode->i_mode & S_IFMT); LASSERT(ll_i2info(inode)); + fid->snap_index = ll_i2info(inode)->lli_snap_index, fid->mds = ll_i2info(inode)->lli_mds; } diff --git a/lustre/include/linux/lustre_smfs.h b/lustre/include/linux/lustre_smfs.h index 8ef548e..fd5e7f2 100644 --- a/lustre/include/linux/lustre_smfs.h +++ b/lustre/include/linux/lustre_smfs.h @@ -27,8 +27,9 @@ #define __LUSTRE_SMFS_H struct snap_inode_info { - int sn_flags; /* the flags indicated inode type */ + int sn_flags; /*the flags indicated inode type */ int sn_gen; /*the inode generation*/ + int sn_index; /*the inode snap_index*/ }; struct smfs_inode_info { struct inode *smi_inode; @@ -367,13 +368,54 @@ static inline void d_unalloc(struct dentry *dentry) dput(dentry); /* this will free the dentry memory */ } +static inline int smfs_get_dentry_name_index(struct dentry *dentry, + struct qstr *str, + int *index) +{ + char *name = (char *)dentry->d_name.name; + unsigned long hash; + unsigned char c; + char *str_name; + int len = 0, name_len = 0; + + name_len = dentry->d_name.len; + if (!name_len) + return 0; + hash = init_name_hash(); + while (name_len--) { + c = *(const unsigned char *)name++; + if (c == ':' || c == '\0') + break; + hash = partial_name_hash(c, hash); + len ++; + } + str->hash = end_name_hash(hash); + OBD_ALLOC(str_name, len + 1); + memcpy(str_name, dentry->d_name.name, len); + str->len = len; + str->name = str_name; + if (index && c == ':') { + *index = simple_strtoul(name, 0, 0); + } + return 0; +} + +static inline void smfs_free_dentry_name(struct qstr *str) +{ + OBD_FREE(str->name, str->len + 1); +} + static inline struct dentry *pre_smfs_dentry(struct dentry *parent_dentry, struct inode *cache_inode, - struct dentry *dentry) + struct dentry *dentry, + int *index) { struct dentry *cache_dentry = NULL; - - cache_dentry = d_alloc(parent_dentry, &dentry->d_name); + struct qstr name; + + smfs_get_dentry_name_index(dentry, &name, index); + cache_dentry = d_alloc(parent_dentry, &name); + smfs_free_dentry_name(&name); if (!cache_dentry) RETURN(NULL); if (!parent_dentry) @@ -451,6 +493,7 @@ static inline int smfs_do_cow(struct inode *inode) return 0; } + /* XXX BUG 3188 -- must return to one set of opcodes */ #define SMFS_TRANS_OP(inode, op) \ { \ @@ -474,4 +517,8 @@ extern int smfs_rec_unpack(struct smfs_proc_args *args, char *record, extern int smfs_post_setup(struct super_block *sb, struct vfsmount *mnt); extern int smfs_post_cleanup(struct super_block *sb); +extern struct inode *smfs_get_inode (struct super_block *sb, ino_t hash, + struct inode *dir, int index); + +extern int is_smfs_sb(struct super_block *sb); #endif /* _LUSTRE_SMFS_H */ diff --git a/lustre/include/linux/lustre_snap.h b/lustre/include/linux/lustre_snap.h index c253979..22169a7 100644 --- a/lustre/include/linux/lustre_snap.h +++ b/lustre/include/linux/lustre_snap.h @@ -165,10 +165,11 @@ struct snap_table { struct snap sntbl_items[0]; }; +#define DOT_NAME_MAX_LEN 32 struct snap_dot_info { - char *dot_name; - int dot_name_len; - int dot_snap_enable; + char *dot_name; + int dot_name_len; + int dot_snap_enable; }; struct snap_info { @@ -180,7 +181,6 @@ struct snap_info { struct snap_table *sntbl; struct dentry *sn_cowed_dentry; struct snap_dot_info *sn_dot_info; - }; extern int smfs_add_snap_item(struct super_block *sb, char *name); @@ -196,4 +196,35 @@ int smfs_cow(struct inode *dir, struct dentry *dentry, int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1, void *data2); struct inode* smfs_cow_get_ind(struct inode *inode, int index); + + +#define DOT_SNAP_NAME ".snap" +#define DOT_SNAP_INDEX 0xffff +static inline int smfs_primary_inode(struct inode *inode) +{ + struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo; + + if (sn_info->sn_index == 0) + return 1; + return 0; +} +static inline int smfs_dotsnap_inode(struct inode *inode) +{ + struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo; + + if (sn_info->sn_index == DOT_SNAP_INDEX) + return 1; + return 0; +} +static inline int smfs_under_dotsnap_inode(struct inode *inode) +{ + struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo; + + if (sn_info->sn_index > 0 && sn_info->sn_index != DOT_SNAP_INDEX) + return 1; + return 0; +} + + + #endif /*_LUSTRE_SNAP_H*/ diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 6b617e0..88f16ff 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -1154,7 +1154,6 @@ static inline int obd_init_ea_size(struct obd_export *exp, int size, int size2) rc = OBP(exp->exp_obd, init_ea_size)(exp, size, size2); RETURN(rc); } - static inline int md_getstatus(struct obd_export *exp, struct ll_fid *fid) { int rc; diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 0943c38..2afe0a6 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include "llite_internal.h" typedef struct ext2_dir_entry_2 ext2_dirent; @@ -347,12 +349,27 @@ int ll_readdir(struct file * filp, void * dirent, filldir_t filldir) if (de->inode) { int over; unsigned char d_type = DT_UNKNOWN; - + + rc = 0; /* no error if we return something */ if (types && de->file_type < EXT2_FT_MAX) 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<inode), d_type); diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index da6bb98..dc21e21 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -52,6 +52,7 @@ 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 906e978..00b305a 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "llite_internal.h" @@ -180,7 +181,6 @@ int lustre_common_fill_super(struct super_block *sb, char *mdc, char *osc) sbi->ll_osc_exp = class_conn2export(&osc_conn); lustre_init_ea_size(sbi); - err = md_getstatus(sbi->ll_mdc_exp, &rootfid); if (err) { CERROR("cannot mds_connect: rc = %d\n", err); @@ -1256,7 +1256,8 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) if (body->valid & OBD_MD_FLSIZE) set_bit(LLI_F_HAVE_MDS_SIZE_LOCK, &lli->lli_flags); - + + lli->lli_snap_index = body->fid1.snap_index; lli->lli_mds = body->mds; inode->i_dev = (kdev_t) body->mds; LASSERT(body->mds < 1000); diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 6761a83..a16814b 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -87,7 +87,10 @@ static int ll_test_inode(struct inode *inode, void *opaque) if (ll_i2info(inode)->lli_mds != md->body->mds) return 0; - +#ifdef CONFIG_SNAPFS + if (ll_i2info(inode)->lli_snap_index != md->body->fid1.snap_index) + return 0; +#endif /* Apply the attributes in 'opaque' to this inode */ ll_update_inode(inode, md); return 1; diff --git a/lustre/lvfs/fsfilt_smfs.c b/lustre/lvfs/fsfilt_smfs.c index 7e4e96b..23267a8 100644 --- a/lustre/lvfs/fsfilt_smfs.c +++ b/lustre/lvfs/fsfilt_smfs.c @@ -76,7 +76,8 @@ static void *fsfilt_smfs_brw_start(int objcount, struct fsfilt_objinfo *fso, return NULL; cache_inode = I2CI(fso->fso_dentry->d_inode); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry, + NULL); if (!cache_dentry) GOTO(exit, rc = ERR_PTR(-ENOMEM)); @@ -170,7 +171,7 @@ static int fsfilt_smfs_setattr(struct dentry *dentry, void *handle, cache_inode = I2CI(dentry->d_inode); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL); if (!cache_dentry) GOTO(exit, rc = -ENOMEM); @@ -395,11 +396,28 @@ static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf, *cache_ppos = *off; pre_smfs_inode(file->f_dentry->d_inode, cache_inode); - +#if CONFIG_SNAPFS + /*readdir page*/ + if (smfs_dotsnap_inode(file->f_dentry->d_inode)) { + struct fsfilt_operations *snapops = + I2SNAPOPS(file->f_dentry->d_inode); + + LASSERT(S_ISDIR(file->f_dentry->d_inode->i_mode)); + + 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, + cache_ppos); + } +#else if (cache_fsfilt->fs_readpage) rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count, cache_ppos); +#endif *off = *cache_ppos; post_smfs_inode(file->f_dentry->d_inode, cache_inode); duplicate_file(file, sfi->c_file); diff --git a/lustre/lvfs/fsfilt_snap_ext3.c b/lustre/lvfs/fsfilt_snap_ext3.c index 29f7c0d..fdb3ec5 100644 --- a/lustre/lvfs/fsfilt_snap_ext3.c +++ b/lustre/lvfs/fsfilt_snap_ext3.c @@ -49,6 +49,7 @@ #include #include #endif +#include #include /* For snapfs in EXT3 flags --- FIXME will find other ways to store it*/ @@ -857,16 +858,24 @@ static int fsfilt_ext3_is_indirect(struct inode *inode) * return value: postive: indirect ino number * negative or 0: error */ -static ino_t fsfilt_ext3_get_indirect_ino(struct inode *primary, int index) +static ino_t fsfilt_ext3_get_indirect_ino(struct super_block *sb, + ino_t primary_ino, int index) { char buf[EXT3_MAX_SNAP_DATA]; + struct inode *primary = NULL; struct snap_ea *snaps; ino_t ino = 0; int err; ENTRY; if (index < 0 || index > EXT3_MAX_SNAPS || !primary) RETURN(0); - + primary = iget(sb, primary_ino); + + if (!primary) { + err = -EIO; + CERROR("attribute read error=%d", err); + GOTO (err_free, ino = err); + } err = ext3_xattr_get(primary, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR, buf, EXT3_MAX_SNAP_DATA); if (err == -ENOATTR) { @@ -880,6 +889,8 @@ static ino_t fsfilt_ext3_get_indirect_ino(struct inode *primary, int index) CDEBUG(D_INODE, "snap ino for %ld at index %d is %lu\n", primary->i_ino, index, ino); err_free: + if (primary) + iput(primary); RETURN(ino); } @@ -1555,7 +1566,44 @@ static int fsfilt_ext3_set_snap_info(struct inode *inode, void *key, } RETURN(-EINVAL); } +static int fsfilt_ext3_dir_ent_size(char *name) +{ + if (name) { + return EXT3_DIR_REC_LEN(strlen(name)); + } + return 0; +} +static int fsfilt_ext3_set_dir_ent(struct super_block *sb, char *name, + char *buf, int buf_off, int nlen, size_t count) +{ + int rc = 0; + ENTRY; + if (buf_off == 0 && nlen == 0) { + struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *)buf; + LASSERT(count == PAGE_CACHE_SIZE); + de->rec_len = count; + de->inode = 0; + RETURN(rc); + } else { + struct ext3_dir_entry_2 *de, *de1; + de = (struct ext3_dir_entry_2 *)(buf + buf_off - nlen); + de1 = (struct ext3_dir_entry_2 *)(buf + buf_off); + int rlen, nlen; + + LASSERT(nlen == EXT3_DIR_REC_LEN_DE(de)); + + rlen = le16_to_cpu(de->rec_len); + de->rec_len = cpu_to_le16(nlen); + + de1->rec_len = cpu_to_le16(rlen - nlen); + de1->name_len = strlen(name); + memcpy (de1->name, name, de->name_len); + nlen = EXT3_DIR_REC_LEN_DE(de1); + RETURN(nlen); + } + +} struct fsfilt_operations fsfilt_ext3_snap_ops = { .fs_type = "ext3_snap", .fs_owner = THIS_MODULE, @@ -1572,8 +1620,11 @@ struct fsfilt_operations fsfilt_ext3_snap_ops = { .fs_copy_block = fsfilt_ext3_copy_block, .fs_set_snap_info = fsfilt_ext3_set_snap_info, .fs_get_snap_info = fsfilt_ext3_get_snap_info, + .fs_dir_ent_size = fsfilt_ext3_dir_ent_size, + .fs_set_dir_ent = fsfilt_ext3_set_dir_ent, }; + static int __init fsfilt_ext3_snap_init(void) { int rc; diff --git a/lustre/lvfs/fsfilt_snap_smfs.c b/lustre/lvfs/fsfilt_snap_smfs.c index 9f5b75e..640d288 100644 --- a/lustre/lvfs/fsfilt_snap_smfs.c +++ b/lustre/lvfs/fsfilt_snap_smfs.c @@ -105,7 +105,8 @@ static struct inode* fsfilt_smfs_get_indirect(struct inode *inode, if (cache_ind_inode && !IS_ERR(cache_ind_inode)){ /*FIXME: get indirect inode set_cow flags*/ - ind_inode = iget4(inode->i_sb, cache_ind_inode->i_ino, NULL, 0); + ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino, + inode, slot); } RETURN(ind_inode); } @@ -194,25 +195,20 @@ static int fsfilt_smfs_is_indirect(struct inode *inode) RETURN(rc); } -static ino_t fsfilt_smfs_get_indirect_ino(struct inode *inode, int index) +static ino_t fsfilt_smfs_get_indirect_ino(struct super_block *sb, ino_t ino, + int index) { - struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode); - struct inode *cache_inode = NULL; + struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt; + struct super_block *csb = S2CSB(sb); 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_indirect_ino) - rc = snap_fsfilt->fs_get_indirect_ino(cache_inode, index); - post_smfs_inode(inode, cache_inode); - + rc = snap_fsfilt->fs_get_indirect_ino(csb, ino, index); + RETURN(rc); } @@ -368,6 +364,40 @@ static int fsfilt_smfs_get_snap_info(struct inode *inode, void *key, RETURN(rc); } + +static int fsfilt_smfs_read_dotsnap_dir_page(struct file *file, char *buf, + size_t count, loff_t *off) +{ + 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; + + /*Get the offset of dir ent*/ + while (size < *off && off_count < stbl->sntbl_count) { + char *name = stbl->sntbl_items[i].sn_name; + size +=snap_cops->fs_dir_ent_size(name); + off_count ++; + } + for (i = off_count; i < stbl->sntbl_count; i++) { + char *name = stbl->sntbl_items[i].sn_name; + rc = snap_cops->fs_set_dir_ent(inode->i_sb, name, buf, buf_off, + rc, count); + if (rc < 0) + break; + + buf_off += rc; + + if (buf_off >= count) + break; + } + if (rc > 0) + rc = 0; + + RETURN(rc); +} + struct fsfilt_operations fsfilt_smfs_snap_ops = { .fs_type = "smfs_snap", .fs_owner = THIS_MODULE, @@ -384,6 +414,7 @@ struct fsfilt_operations fsfilt_smfs_snap_ops = { .fs_copy_block = fsfilt_smfs_copy_block, .fs_set_snap_info = fsfilt_smfs_set_snap_info, .fs_get_snap_info = fsfilt_smfs_get_snap_info, + .fs_read_dotsnap_dir_page = fsfilt_smfs_read_dotsnap_dir_page, }; diff --git a/lustre/mdc/mdc_locks.c b/lustre/mdc/mdc_locks.c index ae07c91..09a709c 100644 --- a/lustre/mdc/mdc_locks.c +++ b/lustre/mdc/mdc_locks.c @@ -36,7 +36,8 @@ #include #include #include -#include +//#include +//#include #include #include "mdc_internal.h" @@ -174,23 +175,6 @@ int mdc_change_cbdata(struct obd_export *exp, struct ll_fid *fid, return 0; } -#if CONFIG_SNAPFS -int mdc_set_clone_info(struct obd_export *exp, struct lustre_msg *msg, - int offset) -{ - struct client_obd *cli_obd = &exp->exp_obd->u.cli; - struct clonefs_info *cl_info; - ENTRY; - - if (cli_obd->cl_clone_info) { - cl_info = (struct clonefs_info *)lustre_msg_buf(msg, offset, - sizeof (*cl_info)); - memcpy(cl_info, cli_obd->cl_clone_info, sizeof(*cl_info)); - } - RETURN(0); -} -#endif - /* We always reserve enough space in the reply packet for a stripe MD, because * we don't know in advance the file type. */ int mdc_enqueue(struct obd_export *exp, @@ -260,15 +244,9 @@ int mdc_enqueue(struct obd_export *exp, if (it->it_op & IT_GETATTR) policy.l_inodebits.bits = MDS_INODELOCK_UPDATE; -#if CONFIG_SNAPFS - size[4] = sizeof(struct clonefs_info); - req = ptlrpc_prep_req(class_exp2cliimp(exp), LDLM_ENQUEUE, 5, - size, NULL); -#else req = ptlrpc_prep_req(class_exp2cliimp(exp), LDLM_ENQUEUE, 4, size, NULL); -#endif if (!req) RETURN(-ENOMEM); @@ -278,9 +256,6 @@ int mdc_enqueue(struct obd_export *exp, /* pack the intended request */ mdc_getattr_pack(req->rq_reqmsg, valid, 2, it->it_flags, data); -#if CONFIG_SNAPFS - mdc_set_clone_info(exp, req->rq_reqmsg, 4); -#endif /* get ready for the reply */ reply_buffers = 3; req->rq_replen = lustre_msg_size(3, repsize); diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 55ec795..7c29799 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -1244,7 +1244,6 @@ struct obd_ops mdc_obd_ops = { .o_connect = client_connect_import, .o_disconnect = client_disconnect_export, .o_iocontrol = mdc_iocontrol, - .o_set_info = mdc_set_info, .o_statfs = mdc_statfs, .o_pin = mdc_pin, .o_unpin = mdc_unpin, diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 27bb918..5bd0496 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -52,10 +52,13 @@ #include #include #include -#include #include #include +#ifdef CONFIG_SNAPFS +#include +#include +#endif #include "mds_internal.h" static int mds_intent_policy(struct ldlm_namespace *ns, @@ -295,8 +298,17 @@ struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid, if (ino == 0) RETURN(ERR_PTR(-ESTALE)); - + +#ifdef CONFIG_SNAPFS + if (is_smfs_sb(mds->mds_sb)) { + snprintf(fid_name, sizeof(fid_name), "0x%lx:%lx", ino, + fid->snap_index); + } else { + snprintf(fid_name, sizeof(fid_name), "0x%lx", ino); + } +#else snprintf(fid_name, sizeof(fid_name), "0x%lx", ino); +#endif CDEBUG(D_DENTRY, "--> mds_fid2dentry: ino/gen %lu/%u, sb %p\n", ino, generation, mds->mds_sb); @@ -883,14 +895,6 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req, CERROR("Can't unpack name\n"); GOTO(cleanup, rc = -EFAULT); } -#if CONFIG_SNAPFS - clone_info = lustre_swab_reqbuf(req, offset + 2, sizeof(*clone_info), - lustre_swab_clonefs_info); - if (clone_info) { - CDEBUG(D_INFO,"getattr name %s clone_info index %d \n", name, - clone_info->clone_index); - } -#endif namesize = req->rq_reqmsg->buflens[offset + 1]; LASSERT (offset == 0 || offset == 2); diff --git a/lustre/mds/mds_lib.c b/lustre/mds/mds_lib.c index ced2a70..81107a1 100644 --- a/lustre/mds/mds_lib.c +++ b/lustre/mds/mds_lib.c @@ -49,6 +49,9 @@ #include #include +#include +#include + void mds_pack_dentry2fid(struct ll_fid *fid, struct dentry *dentry) { fid->id = dentry->d_inum; @@ -67,6 +70,12 @@ void mds_pack_dentry2body(struct mds_body *b, struct dentry *dentry) void mds_pack_inode2fid(struct obd_device *obd, struct ll_fid *fid, struct inode *inode) { +#ifdef CONFIG_SNAPFS + if (is_smfs_sb(inode->i_sb)) { + struct smfs_inode_info *sm_info = I2SMI(inode); + fid->snap_index = sm_info->sm_sninfo.sn_index; + } +#endif fid->id = inode->i_ino; fid->generation = inode->i_generation; fid->f_type = (S_IFMT & inode->i_mode); diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index 0c07e7c..f954063 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -34,8 +34,8 @@ #include #include #include -#include #include +#include #include "smfs_internal.h" @@ -69,8 +69,8 @@ static int smfs_create(struct inode *dir, struct dentry *dentry, lock_kernel(); SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, PRE_HOOK, rc, exit); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); - cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL); + cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL); if (!cache_dentry || !cache_parent) GOTO(exit, rc = -ENOMEM); @@ -87,9 +87,8 @@ static int smfs_create(struct inode *dir, struct dentry *dentry, #endif if (rc) GOTO(exit, rc); - - inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); + + inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0); if (!inode) GOTO(exit, rc = -ENOMEM); @@ -120,21 +119,16 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, struct dentry *cache_parent = NULL; struct dentry *rc = NULL; void *handle = NULL; - int rc2 = 0; + int rc2 = 0, index = 0; ENTRY; if (!(cache_dir = I2CI(dir))) RETURN(ERR_PTR(-ENOENT)); - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, PRE_HOOK, rc2, - exit); - if (rc2) - RETURN(ERR_PTR(rc2)); - /* preparing artificial backing fs dentries. */ - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent); - cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent, NULL); + cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, &index); if (!cache_dentry || !cache_parent) GOTO(exit, rc = ERR_PTR(-ENOMEM)); @@ -142,13 +136,15 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, if (!cache_dir && cache_dir->i_op->lookup) GOTO(exit, rc = ERR_PTR(-ENOENT)); + SMFS_HOOK(dir, dentry, &index, NULL, HOOK_LOOKUP, handle, + PRE_HOOK, rc2, exit); + /* perform lookup in backing fs. */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) rc = cache_dir->i_op->lookup(cache_dir, cache_dentry); #else rc = cache_dir->i_op->lookup(cache_dir, cache_dentry, nd); #endif - if (rc && IS_ERR(rc)) GOTO(exit, rc); @@ -157,8 +153,7 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, dentry->d_inode = cache_inode; GOTO(exit, rc = NULL); } - inode = iget4(dir->i_sb, cache_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); + inode = smfs_get_inode(dir->i_sb, cache_inode->i_ino, dir, index); } else { d_add(dentry, NULL); GOTO(exit, rc); @@ -170,7 +165,7 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, POST_HOOK, rc2, exit); exit: - if (rc2) + if (rc2 < 0) rc = ERR_PTR(rc2); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); @@ -202,14 +197,14 @@ static int smfs_link(struct dentry * old_dentry, SMFS_HOOK(dir, old_dentry, NULL, NULL, HOOK_LINK, handle, PRE_HOOK, rc, exit); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); - cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL); + cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL); if (!cache_parent || !cache_dentry) GOTO(exit, rc = -ENOMEM); cache_old_dentry = pre_smfs_dentry(NULL, cache_old_inode, - old_dentry); + old_dentry, NULL); if (!cache_old_dentry) GOTO(exit, rc = -ENOMEM); @@ -260,8 +255,8 @@ static int smfs_unlink(struct inode * dir, SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_UNLINK, handle, PRE_HOOK, rc, exit); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); - cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry); + cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL); + cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry, NULL); if (!cache_parent || !cache_dentry) GOTO(exit, rc = -ENOMEM); @@ -305,8 +300,8 @@ static int smfs_symlink(struct inode *dir, struct dentry *dentry, SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_SYMLINK, handle, PRE_HOOK, rc, exit); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); - cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL); + cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL); if (!cache_parent || !cache_dentry) GOTO(exit, rc = -ENOMEM); @@ -315,8 +310,8 @@ 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 = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); + + inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0); post_smfs_inode(dir, cache_dir); if (inode) d_instantiate(dentry, inode); @@ -357,8 +352,8 @@ static int smfs_mkdir(struct inode *dir, struct dentry *dentry, SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, PRE_HOOK, rc, exit); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); - cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL); + cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL); if (!cache_parent || !cache_dentry) GOTO(exit, rc = -ENOMEM); @@ -370,9 +365,9 @@ 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); - inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); if (!inode) GOTO(exit, rc = -ENOENT); @@ -412,8 +407,8 @@ static int smfs_rmdir(struct inode *dir, struct dentry *dentry) SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_RMDIR, handle, PRE_HOOK, rc, exit); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); - cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry); + cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL); + cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry, NULL); if (!cache_parent || !cache_dentry) GOTO(exit, rc = -ENOMEM); @@ -464,8 +459,8 @@ static int smfs_mknod(struct inode *dir, struct dentry *dentry, SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, PRE_HOOK, rc, exit); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent); - cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent, NULL); + cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL); if (!cache_parent || !cache_dentry) GOTO(exit, rc = -ENOMEM); @@ -479,8 +474,8 @@ static int smfs_mknod(struct inode *dir, struct dentry *dentry, mode, rdev))) GOTO(exit, rc); - inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); + inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0); + d_instantiate(dentry, inode); pre_smfs_inode(dir, cache_dir); @@ -528,15 +523,15 @@ static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry, SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle, PRE_HOOK, rc, exit); - cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry); + cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry, NULL); cache_old_dentry = pre_smfs_dentry(cache_old_parent, cache_old_inode, - old_dentry); + old_dentry, NULL); if (!cache_old_parent || !cache_old_dentry) GOTO(exit, rc = -ENOMEM); - cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry); + cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry, NULL); cache_new_dentry = pre_smfs_dentry(cache_new_parent, cache_new_inode, - new_dentry); + new_dentry, NULL); if (!cache_new_parent || !cache_new_dentry) GOTO(exit, rc = -ENOMEM); diff --git a/lustre/smfs/file.c b/lustre/smfs/file.c index 45602dd..37e9d63 100644 --- a/lustre/smfs/file.c +++ b/lustre/smfs/file.c @@ -242,7 +242,7 @@ static int smfs_init_cache_file(struct inode *inode, struct file *filp) sfi->magic = SMFS_FILE_MAGIC; - cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry); + cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry, NULL); if (!cache_dentry) GOTO(err_exit, rc = -ENOMEM); @@ -350,7 +350,7 @@ int smfs_fsync(struct file *file, struct dentry *dentry, int datasync) if (!cache_inode) RETURN(-ENOENT); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL); if (!cache_dentry) RETURN(-ENOMEM); @@ -418,7 +418,7 @@ int smfs_setattr(struct dentry *dentry, struct iattr *attr) if (!cache_inode) RETURN(-ENOENT); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL); if (!cache_dentry) RETURN(-ENOMEM); @@ -454,7 +454,7 @@ int smfs_setxattr(struct dentry *dentry, const char *name, const void *value, if (!cache_inode) RETURN(-ENOENT); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL); if (!cache_dentry) RETURN(-ENOMEM); @@ -481,7 +481,7 @@ int smfs_getxattr(struct dentry *dentry, const char *name, void *buffer, if (!cache_inode) RETURN(-ENOENT); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL); if (!cache_dentry) RETURN(-ENOMEM); @@ -507,7 +507,7 @@ ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size) if (!cache_inode) RETURN(-ENOENT); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL); if (!cache_dentry) RETURN(-ENOMEM); @@ -532,7 +532,7 @@ int smfs_removexattr(struct dentry *dentry, const char *name) if (!cache_inode) RETURN(-ENOENT); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL); if (!cache_dentry) RETURN(-ENOMEM); diff --git a/lustre/smfs/smfs_cow.c b/lustre/smfs/smfs_cow.c index f6655bc..8282a82 100644 --- a/lustre/smfs/smfs_cow.c +++ b/lustre/smfs/smfs_cow.c @@ -36,8 +36,8 @@ #include #include -#include #include +#include #include "smfs_internal.h" #define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + size * sizeof(struct snap)) @@ -123,7 +123,6 @@ static int smfs_init_cowed_dir(struct super_block *sb, struct dentry* cowed_dir) snap_info->sn_cowed_dentry = dentry; RETURN(rc); } -#define DOT_SNAP_NAME ".snap" static int smfs_init_dotinfo(struct super_block *sb) { struct snap_info *snap_info = S2SNAPI(sb); @@ -315,27 +314,62 @@ int smfs_cow_cleanup(struct super_block *sb) RETURN(0); } +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; + ENTRY; + + for (i = 0; i < stbl->sntbl_count; i++) { + size += snapops->fs_dir_ent_size(stbl->sntbl_items[i].sn_name); + } + /*FIXME this is only for ext3 dir format, may need fix for other FS*/ + blocks = (size + inode->i_sb->s_blocksize - 1) >> + inode->i_sb->s_blocksize_bits; + + dir_size = blocks * inode->i_sb->s_blocksize; + RETURN(dir_size); + +} /*FIXME Note indirect and primary inode * should be recorgnized here*/ -int smfs_init_snap_inode_info(struct inode *inode, int flags) +int smfs_init_snap_inode_info(struct inode *inode, + struct snap_inode_info *sn_info) { + struct smfs_inode_info *smi = I2SMI(inode); int vallen, rc = 0; ENTRY; - if (SMFS_DO_COW(S2SMI(inode->i_sb)) && - (flags & SM_DO_COW)) { + 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; + + if (smfs_dotsnap_inode(inode)) { + struct snap_table *stbl= S2SNAPI(inode->i_sb)->sntbl; + int size = 0; + /*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_uid = 0; + inode->i_gid = 0; + } else if (SMFS_DO_COW(S2SMI(inode->i_sb)) && + (smi->smi_flags & SM_DO_COW) && + smfs_primary_inode(inode)) { struct snap_inode_info *sni_info = I2SNAPI(inode); struct fsfilt_operations *snapops = I2SNAPOPS(inode); - sni_info->sn_flags = flags; vallen = sizeof(sni_info->sn_gen); - + rc = snapops->fs_get_snap_info(inode, SNAP_GENERATION, strlen(SNAP_GENERATION), &sni_info->sn_gen, &vallen); } RETURN(rc); - } /* latest snap: returns - the index of the latest snapshot before NOW @@ -490,7 +524,7 @@ static int link_cowed_inode(struct inode *inode) LASSERT(dchild->d_inode == inode); GOTO(out_dput, rc = 0); } - tmp = pre_smfs_dentry(NULL, inode, cowed_dir); + tmp = pre_smfs_dentry(NULL, inode, cowed_dir, NULL); /* link() is semanticaly-wrong for S_IFDIR, so we set S_IFREG * for linking and return real mode back then -bzzz */ mode = inode->i_mode; @@ -533,7 +567,7 @@ int snap_do_cow(struct inode *inode, struct dentry *dparent, int del) ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen, dparent->d_inode, del); if(ind && IS_ERR(ind)) { - CERROR("Create ind inode %lu index %d gen %d del %d\n rc%u\n", + 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)); RETURN(PTR_ERR(ind)); @@ -547,6 +581,7 @@ int snap_do_cow(struct inode *inode, struct dentry *dparent, int del) I2SMI(ind)->sm_sninfo.sn_flags = 0; I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen; + I2SMI(ind)->sm_sninfo.sn_index = snap.sn_index; iput(ind); } @@ -751,58 +786,103 @@ exit: RETURN(rc); } EXPORT_SYMBOL(smfs_cow_write); - +/*lookup inode in dotsnap inode */ +static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry) +{ + if (dentry->d_name.len == 1 && + !strcmp(dentry->d_name.name, ".")) { + d_add(dentry, iget(dir->i_sb, dir->i_ino)); + } else if (dentry->d_name.len == 2 && + !strcmp(dentry->d_name.name, "..")) { + struct inode *inode; + struct dentry *dparent = dentry->d_parent; + if (dparent->d_inode) { + inode = iget(dir->i_sb, dparent->d_inode->i_ino); + if (inode) { + if (!is_bad_inode(inode)) + d_add(dentry, inode); + else + iput(inode); + } + } + } else { + /*find the name from the snaptable*/ + struct fsfilt_operations *snapops = I2SNAPOPS(dir); + struct snap_table *table = S2SNAPI(dir->i_sb)->sntbl; + struct inode *inode; + int i = 0, index = -1; + for (i = 0; i < table->sntbl_count; i++) { + char *name = table->sntbl_items[i].sn_name; + if ((dentry->d_name.len == strlen(name)) && + (memcmp(dentry->d_name.name, name, + dentry->d_name.len) == 0)) { + index = table->sntbl_items[i].sn_index; + break; + } + } + if (index != -1) { + CERROR("No such %s in this .snap dir \n", + dentry->d_name.name); + RETURN(-ENOENT); + } + inode = snapops->fs_get_indirect(dir, NULL, index); + d_add(dentry, inode); + } + RETURN(0); +} int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1, void *data2) { struct snap_info *snap_info = S2SNAPI(inode->i_sb); - struct fsfilt_operations *snapops = snap_info->snap_fsfilt; - struct dentry *dparent = dentry->d_parent; - struct clonefs_info *clone_info=(struct clonefs_info*)dparent->d_fsdata; - int rc = 0; - - if (clone_info && clone_info->clone_flags && SM_CLONE_FS) { - struct inode *ind_inode = NULL; - struct inode *cache_ind = NULL; - struct dentry *cache_dentry = NULL; - struct dentry *cache_parent = NULL; - struct inode *cache_inode; - struct dentry *tmp; - rc = 1; - - ind_inode = snapops->fs_get_indirect(inode, NULL, clone_info->clone_index); - if (!ind_inode) - RETURN(-ENOENT); - - if (!(cache_ind = I2CI(ind_inode))) - GOTO(exit, rc = -ENOENT); - - cache_parent=pre_smfs_dentry(NULL, cache_ind, dentry->d_parent); - cache_dentry=pre_smfs_dentry(cache_parent, NULL, dentry); + struct snap_dot_info *dot_info = snap_info->sn_dot_info; + int rc = 0, index = 0; + ENTRY; - tmp = cache_ind->i_op->lookup(cache_ind, cache_dentry); + LASSERT(dot_info != NULL); + LASSERT(data1 != NULL); - if (IS_ERR(tmp)) - GOTO(exit, rc = -ENOENT); - - if ((cache_inode = tmp ? tmp->d_inode : cache_dentry->d_inode)) { - if (IS_ERR(cache_inode)) { - dentry->d_inode = cache_inode; - GOTO(exit, rc = -ENOENT); - } - inode = iget4(inode->i_sb, cache_inode->i_ino, NULL, - &I2SMI(inode)->smi_flags); - } else { - d_add(dentry, NULL); - GOTO(exit, rc = -ENOENT); - } - d_add(dentry, inode); -exit: - iput(ind_inode); - post_smfs_dentry(cache_dentry); - post_smfs_dentry(cache_parent); + index = *(int *)data1; + + if (smfs_primary_inode(inode) && + dentry->d_name.len == dot_info->dot_name_len && + memcmp(dentry->d_name.name, dot_info->dot_name, + strlen(dot_info->dot_name)) == 0) { + struct inode *dot_inode = NULL; + + dot_inode = smfs_get_inode(inode->i_sb, inode->i_ino, inode, + DOT_SNAP_INDEX); + d_add(dentry, dot_inode); + rc = 1; RETURN(rc); + } + if (smfs_dotsnap_inode(inode)) { + rc = smfs_dotsnap_lookup(inode, dentry); + if (rc == 0) + rc = 1; + RETURN(rc); } + if (index > 0) { + /*HERE: will replace ino in dentry->d_name according to index*/ + struct fsfilt_operations *snapops = I2SNAPOPS(inode); + char *name = (char *)dentry->d_name.name; + unsigned long ino, hash, ind_ino; + int len = sizeof(ind_ino); + + ino = simple_strtoul(name, 0, 0); + + ind_ino = snapops->fs_get_indirect_ino(inode->i_sb, ino, index); + + snprintf(name, strlen(name), "0x%lx", ind_ino); + + hash = init_name_hash(); + while (len--) { + unsigned char c; + c = *(const unsigned char *)name++; + if (c == '\0') break; + hash = partial_name_hash(c, hash); + } + dentry->d_name.hash = end_name_hash(hash); + } RETURN(rc); } diff --git a/lustre/smfs/smfs_internal.h b/lustre/smfs/smfs_internal.h index 51f593b..7efefbd 100644 --- a/lustre/smfs/smfs_internal.h +++ b/lustre/smfs/smfs_internal.h @@ -157,6 +157,8 @@ extern int smfs_removexattr(struct dentry *dentry, const char *name); extern int smfs_open(struct inode * inode, struct file * filp); extern int smfs_release(struct inode * inode, struct file * filp); /*inode.c*/ +struct inode *smfs_get_inode(struct super_block *sb, ino_t hash, + struct inode *dir, int index); extern struct super_operations smfs_super_ops; /*symlink.c*/ extern struct inode_operations smfs_sym_iops; @@ -316,7 +318,8 @@ do { \ #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, int flags); +extern int smfs_init_snap_inode_info(struct inode *inode, + struct snap_inode_info *sn_info); #else #define SMFS_PRE_COW(dir, dentry, new_dir, new_dentry, op, name, rc, label) #endif diff --git a/lustre/smfs/symlink.c b/lustre/smfs/symlink.c index 99e839f..b8388f8 100644 --- a/lustre/smfs/symlink.c +++ b/lustre/smfs/symlink.c @@ -48,7 +48,7 @@ static int smfs_readlink(struct dentry *dentry, char *buffer, int buflen) if (!cache_inode) RETURN(-ENOENT); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL); if (!cache_dentry) GOTO(exit, rc = -ENOMEM); if (cache_inode->i_op && cache_inode->i_op->readlink) @@ -69,7 +69,7 @@ static int smfs_follow_link(struct dentry *dentry, struct nameidata *nd) if (!cache_inode) RETURN(-ENOENT); - cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL); if (!cache_dentry) GOTO(exit, rc = -ENOMEM); -- 1.8.3.1