X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsmfs%2Fsmfs_cow.c;fp=lustre%2Fsmfs%2Fsmfs_cow.c;h=8282a82f82333b80e2b54777e22f8cf149a6b83d;hb=4801dab391279a180ac7601424f79298bdbd0fb3;hp=f6655bcbea2fbda06404fa7e358da82ad9b99ebf;hpb=96f0134a78f9dd931798abef97fb176676111a44;p=fs%2Flustre-release.git 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); }