X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsmfs%2Fsmfs_cow.c;h=a041bf943bf34c7c13d3bdb682967d8d6fed46a2;hb=b78fa3298cb39307feb014711373b45992ed60e3;hp=e3ca33731711db9f113f720e7f4544e1ce289d78;hpb=385fc946aca3a4cf0f1c8b2bb612457c63403877;p=fs%2Flustre-release.git diff --git a/lustre/smfs/smfs_cow.c b/lustre/smfs/smfs_cow.c index e3ca337..a041bf9 100644 --- a/lustre/smfs/smfs_cow.c +++ b/lustre/smfs/smfs_cow.c @@ -46,6 +46,7 @@ static int smfs_init_snaptabe(struct super_block *sb) 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; @@ -54,7 +55,7 @@ static int smfs_init_snaptabe(struct super_block *sb) /*Initialized table */ /*get the maxsize of snaptable*/ vallen = sizeof(int); - rc = snapops->fs_get_snap_info(sb, NULL, MAX_SNAPTABLE_COUNT, + rc = snapops->fs_get_snap_info(d_root->d_inode, MAX_SNAPTABLE_COUNT, strlen(MAX_SNAPTABLE_COUNT), &size, &vallen); if (size == 0) { @@ -79,7 +80,7 @@ static int smfs_init_snaptabe(struct super_block *sb) snap_table->sntbl_items[i].sn_index = -1; } /*get snaptable info*/ - rc = snapops->fs_get_snap_info(sb, NULL, SNAPTABLE_INFO, + rc = snapops->fs_get_snap_info(d_root->d_inode, SNAPTABLE_INFO, strlen(SNAPTABLE_INFO), snap_table, &table_size); if (rc < 0) { @@ -124,14 +125,9 @@ static int smfs_init_cowed_dir(struct super_block *sb, struct dentry* cowed_dir) } int smfs_start_cow(struct super_block *sb) { - struct smfs_super_info *smfs_info = S2SMI(sb); int rc = 0; ENTRY; - OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info)); - - if (!smfs_info->smsi_snap_info) - RETURN(-ENOMEM); /*init snap fsfilt operations*/ if (!S2SNAPI(sb)->snap_cache_fsfilt) { @@ -192,8 +188,6 @@ int smfs_stop_cow(struct super_block *sb) table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); OBD_FREE(snap_info->sntbl, table_size); } - if (snap_info) - OBD_FREE(snap_info, sizeof(*snap_info)); RETURN(rc); } @@ -206,13 +200,23 @@ int smfs_cow_init(struct super_block *sb) SMFS_SET_COW(smfs_info); + OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info)); + + if (!smfs_info->smsi_snap_info) + RETURN(-ENOMEM); + RETURN(rc); } int smfs_cow_cleanup(struct super_block *sb) { + + struct snap_info *snap_info = S2SNAPI(sb); + ENTRY; SMFS_CLEAN_COW(S2SMI(sb)); + if (snap_info) + OBD_FREE(snap_info, sizeof(*snap_info)); RETURN(0); } @@ -231,7 +235,7 @@ int smfs_init_snap_inode_info(struct inode *inode, int flags) sni_info->sn_flags = flags; vallen = sizeof(sni_info->sn_gen); - rc = snapops->fs_get_snap_info(NULL, inode, SNAP_GENERATION, + rc = snapops->fs_get_snap_info(inode, SNAP_GENERATION, strlen(SNAP_GENERATION), &sni_info->sn_gen, &vallen); } @@ -299,6 +303,7 @@ int smfs_add_snap_item(struct super_block *sb, char *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; @@ -321,7 +326,7 @@ int smfs_add_snap_item(struct super_block *sb, char *name) /* Wrote the whole snap_table to disk */ table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); - rc = snapops->fs_set_snap_info(sb, NULL, SNAPTABLE_INFO, + rc = snapops->fs_set_snap_info(d_root->d_inode, SNAPTABLE_INFO, strlen(SNAPTABLE_INFO), snap_table, &table_size); if (rc) { @@ -432,18 +437,24 @@ int snap_do_cow(struct inode *inode, struct dentry *dparent, int del) snap_last(inode->i_sb, &snap); ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen, dparent->d_inode, del); - if(!ind) - RETURN(-EINVAL); - if (!SMFS_DO_INODE_COWED(inode)) { - /*insert the inode to cowed inode*/ - SMFS_SET_INODE_COWED(inode); - link_cowed_inode(inode); + if(ind && IS_ERR(ind)) { + CERROR("Create ind inode %lu index %d gen %d del %d\n rc%d\n", + inode->i_ino, snap.sn_index, snap.sn_gen, del, + PTR_ERR(ind)); + RETURN(PTR_ERR(ind)); + } + if (ind) { + if (!SMFS_DO_INODE_COWED(inode)) { + /*insert the inode to cowed inode*/ + SMFS_SET_INODE_COWED(inode); + link_cowed_inode(inode); + } + + I2SMI(ind)->sm_sninfo.sn_flags = 0; + I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen; + + iput(ind); } - - I2SMI(ind)->sm_sninfo.sn_flags = 0; - I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen; - - iput(ind); RETURN(0); } /*Dir inode will do cow*/ @@ -458,8 +469,8 @@ int smfs_cow_create(struct inode *dir, struct dentry *dentry, CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); LASSERT(dentry->d_parent && dentry->d_parent->d_parent); dparent = dentry->d_parent->d_parent; - if ((snap_do_cow(dir, dparent, 0))) { - CERROR("Do cow error\n"); + if ((rc = snap_do_cow(dir, dparent, 0))) { + CERROR("Do cow error %d\n", rc); RETURN(-EINVAL); } } @@ -646,16 +657,100 @@ exit: } EXPORT_SYMBOL(smfs_cow_write); +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); + + tmp = cache_ind->i_op->lookup(cache_ind, cache_dentry); + + 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); + RETURN(rc); + } + RETURN(rc); +} + +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; + int slot; + + ENTRY; + 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); + + if (!cache_inode ) continue; + + if (aops->bmap(cache_inode->i_mapping, block)) + RETURN(cache_inode); + iput(cache_inode); + } + + RETURN(NULL); +} +EXPORT_SYMBOL(smfs_cow_get_ind); + typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry, void *new_dir, void *new_dentry); -static cow_funcs smfs_cow_funcs[REINT_MAX + 1] = { + +static cow_funcs smfs_cow_funcs[REINT_MAX + 2] = { [REINT_SETATTR] smfs_cow_setattr, [REINT_CREATE] smfs_cow_create, [REINT_LINK] smfs_cow_link, [REINT_UNLINK] smfs_cow_unlink, [REINT_RENAME] smfs_cow_rename, [REINT_WRITE] smfs_cow_write, + [SNAP_LOOKUP] smfs_cow_lookup, }; int smfs_cow(struct inode *dir, struct dentry *dentry, void *new_dir,