static inline struct dentry *pre_smfs_dentry(struct dentry *parent_dentry,
struct inode *cache_inode,
- struct dentry *dentry,
- int *index)
+ struct dentry *dentry)
{
struct dentry *cache_dentry = NULL;
- struct qstr name;
- smfs_get_dentry_name_index(dentry, &name, index);
- cache_dentry = d_alloc(parent_dentry, &name);
- smfs_free_dentry_name(&name);
+ cache_dentry = d_alloc(parent_dentry, &dentry->d_name);
if (!cache_dentry)
RETURN(NULL);
if (!parent_dentry)
return NULL;
cache_inode = I2CI(fso->fso_dentry->d_inode);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry,
- NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry);
if (!cache_dentry)
GOTO(exit, rc = ERR_PTR(-ENOMEM));
cache_inode = I2CI(dentry->d_inode);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
if (!cache_dentry)
GOTO(exit, rc = -ENOMEM);
struct snap_ea *snaps;
ino_t ino;
struct inode *inode = NULL;
- int rc = 0, index = 0;
+ int rc = 0;
ENTRY;
/* if table is NULL and there is a slot */
if( !table && slot >= 0) {
- index = slot;
- ino = le32_to_cpu(snaps->ino[index]);
+ ino = le32_to_cpu(snaps->ino[slot]);
if(ino)
inode = iget(primary->i_sb, ino);
GOTO(err_free, rc);
}
/* if table is not NULL */
- while (!inode && slot >= 0 && table) {
- index = table[slot];
- ino = le32_to_cpu(snaps->ino[index]);
+ while (!inode && slot >= 0 ) {
+ ino = le32_to_cpu(snaps->ino[slot]);
CDEBUG(D_INODE, "snap inode at slot %d is %lu\n", slot, ino);
if (!ino) {
inode = iget(primary->i_sb, ino);
GOTO(err_free, rc);
}
- if( slot == -1 && table ) {
+ if( slot == -1) {
CDEBUG(D_INODE, "redirector not found, using primary\n");
inode = iget(primary->i_sb, primary->i_ino);
}
static int fsfilt_smfs_read_dotsnap_dir_page(struct file *file, char *buf,
size_t count, loff_t *off)
{
+#if 0
struct inode *inode = file->f_dentry->d_inode;
struct fsfilt_operations *snap_cops = I2SNAPCOPS(inode);
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) {
#else
#warning "still not implement read .snap dir page for fsfilt Wangdi"
#endif
- RETURN(rc);
+ RETURN(0);
}
struct fsfilt_operations fsfilt_smfs_snap_ops = {
lock_kernel();
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
if (!cache_dentry || !cache_parent)
GOTO(exit, rc = -ENOMEM);
if (rc)
GOTO(exit, rc);
- SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode,
- rc, exit);
+ SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, inode, rc, exit);
d_instantiate(dentry, inode);
post_smfs_inode(dir, cache_dir);
struct dentry *cache_parent = NULL;
struct dentry *rc = NULL;
void *handle = NULL;
- int rc2 = 0, index = 0;
+ int rc2 = 0;
ENTRY;
RETURN(ERR_PTR(-ENOENT));
/* preparing artificial backing fs dentries. */
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent, NULL);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, &index);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
if (!cache_dentry || !cache_parent)
GOTO(exit, rc = ERR_PTR(-ENOMEM));
if (!cache_dir && cache_dir->i_op->lookup)
GOTO(exit, rc = ERR_PTR(-ENOENT));
- SMFS_HOOK(dir, dentry, &index, NULL, HOOK_LOOKUP, handle,
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle,
PRE_HOOK, rc2, exit);
/* perform lookup in backing fs. */
dentry->d_inode = cache_inode;
GOTO(exit, rc = NULL);
}
- SMFS_GET_INODE(dir->i_sb, cache_inode, dir, index, inode, rc2,
- exit);
+ SMFS_GET_INODE(dir->i_sb, cache_inode, dir, inode, rc2, exit);
} else {
d_add(dentry, NULL);
GOTO(exit, rc);
SMFS_HOOK(dir, old_dentry, NULL, NULL, HOOK_LINK, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
- cache_old_dentry = pre_smfs_dentry(NULL, cache_old_inode,
- old_dentry, NULL);
+ cache_old_dentry = pre_smfs_dentry(NULL, cache_old_inode, old_dentry);
if (!cache_old_dentry)
GOTO(exit, rc = -ENOMEM);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_UNLINK, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
- cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry, NULL);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_SYMLINK, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
post_smfs_inode(dir, cache_dir);
- SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode,
- rc, exit);
+ SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, inode, rc, exit);
if (inode)
d_instantiate(dentry, inode);
else
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
if (rc)
GOTO(exit, rc);
- SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode,
- rc, exit);
+ SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, inode, rc, exit);
d_instantiate(dentry, inode);
post_smfs_inode(dir, cache_dir);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_RMDIR, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
- cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry, NULL);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent, NULL);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
mode, rdev)))
GOTO(exit, rc);
- SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode,
- rc, exit);
+ SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, inode, rc, exit);
d_instantiate(dentry, inode);
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, NULL);
+ cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry);
cache_old_dentry = pre_smfs_dentry(cache_old_parent, cache_old_inode,
- old_dentry, NULL);
+ old_dentry);
if (!cache_old_parent || !cache_old_dentry)
GOTO(exit, rc = -ENOMEM);
- cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry, NULL);
+ cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry);
cache_new_dentry = pre_smfs_dentry(cache_new_parent, cache_new_inode,
- new_dentry, NULL);
+ new_dentry);
if (!cache_new_parent || !cache_new_dentry)
GOTO(exit, rc = -ENOMEM);
sfi->magic = SMFS_FILE_MAGIC;
- cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry);
if (!cache_dentry)
GOTO(err_exit, rc = -ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
if (!cache_dentry)
RETURN(-ENOMEM);
struct smfs_iget_args *sargs = (struct smfs_iget_args*)opaque;
struct inode *cache_inode = NULL;
- if (sargs)
- cache_inode = iget(S2CSB(inode->i_sb), sargs->s_ino);
- else
- cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino);
+ cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino);
OBD_ALLOC(I2SMI(inode), sizeof(struct smfs_inode_info));
LASSERT(I2SMI(inode));
if (dir)
I2SMI(inode)->smi_flags = I2SMI(dir)->smi_flags;
-#if CONFIG_SNAPFS
- if (SMFS_DO_COW(S2SMI(inode->i_sb))) {
- smfs_init_snap_inode_info(inode, sargs);
- }
-#endif
}
}
static int smfs_test_inode(struct inode *inode, void *opaque)
#endif
{
- if (!opaque)
+ struct smfs_iget_args *sargs = (struct smfs_iget_args*)opaque;
+
+ LASSERT(sargs);
+ if (!sargs)
return 1;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+ if (inode->i_ino != sargs->s_ino)
+ return 0;
+#endif
#ifdef CONFIG_SNAPFS
if (SMFS_DO_COW(S2SMI(inode->i_sb)) &&
!smfs_snap_test_inode(inode, opaque))
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;
}
{
struct super_block *sb;
struct nameidata nd;
- int error = 0;
ENTRY;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
SMFS_SET_REC(smfs_info);
- ost_rec_pack_init(sb);
- mds_rec_pack_init(sb);
+ ost_rec_pack_init(smfs_info);
+ mds_rec_pack_init(smfs_info);
rec_hops = smfs_alloc_hook_ops(KML_HOOK, NULL, smfs_rec_post_hook);
if (!rec_hops) {
RETURN(-ENOMEM);
}
-
- rc = smfs_register_hook_ops(sb, rec_hops);
-
+ rc = smfs_register_hook_ops(smfs_info, rec_hops);
if (rc && rec_hops) {
- smfs_unregister_hook_ops(sb, rec_hops->smh_name);
+ smfs_unregister_hook_ops(smfs_info, rec_hops->smh_name);
smfs_free_hook_ops(rec_hops);
}
RETURN(rc);
}
-int smfs_rec_cleanup(struct super_block *sb)
+int smfs_rec_cleanup(struct smfs_super_info *smfs_info)
{
struct smfs_hook_ops *rec_hops;
int rc = 0;
- rec_hops = smfs_unregister_hook_ops(sb, KML_HOOK);
+ rec_hops = smfs_unregister_hook_ops(smfs_info, KML_HOOK);
smfs_free_hook_ops(rec_hops);
- SMFS_CLEAN_REC(S2SMI(sb));
+ SMFS_CLEAN_REC(smfs_info);
RETURN(rc);
}
return dchild;
}
+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_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;
+
+ 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) >>
+ inode->i_sb->s_blocksize_bits;
+
+ dir_size = blocks * inode->i_sb->s_blocksize;
+ RETURN(dir_size);
+
+}
+
+static int smfs_init_snap_inode_info(struct inode *inode, struct inode *dir, int index)
+{
+ int rc = 0;
+ ENTRY;
+
+ if (dir) {
+ I2SNAPI(inode)->sn_flags = I2SNAPI(dir)->sn_flags;
+ I2SNAPI(inode)->sn_gen = I2SNAPI(dir)->sn_gen;
+ I2SNAPI(inode)->sn_root_ino = I2SNAPI(dir)->sn_root_ino;
+ I2SNAPI(inode)->sn_index = I2SNAPI(inode)->sn_index;
+ } else {
+ I2SNAPI(inode)->sn_flags = 0;
+ I2SNAPI(inode)->sn_gen = 0;
+ }
+
+ I2SNAPI(inode)->sn_index = index;
+
+ if (smfs_dotsnap_inode(inode)) {
+ struct snap_info *snap_info;
+
+ snap_info = smfs_find_snap_info(inode);
+ if (!snap_info) {
+ RETURN(-EIO);
+ }
+ /*init dot_snap inode info*/
+ 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)) &&
+ (I2SMI(inode)->smi_flags & SM_DO_COW) &&
+ smfs_primary_inode(inode)) {
+ struct snap_inode_info *sni_info = I2SNAPI(inode);
+ struct fsfilt_operations *sops = I2SNAPCOPS(inode);
+ int vallen = 0;
+
+ vallen = sizeof(sni_info->sn_gen);
+
+ rc = sops->fs_get_snap_info(I2CI(inode), SNAP_GENERATION,
+ strlen(SNAP_GENERATION),
+ &sni_info->sn_gen, &vallen);
+ }
+ RETURN(rc);
+}
+
#define COWED_NAME_LEN (7 + 8 + 1)
static int smfs_init_cowed_dir(struct snap_info *snap_info, struct dentry* dir)
{
GOTO(exit, snap_info = ERR_PTR(rc));
/*set cow flags for the snap root inode*/
- I2SMI(dentry->d_inode)->smi_flags |= SM_DO_COW;
+ I2SMI(dentry->d_inode)->smi_flags |= SM_DO_COW;
+ I2SNAPI(dentry->d_inode)->sn_root_ino = dentry->d_inode->i_ino;
exit:
if (rc)
OBD_FREE(snap_info, sizeof(struct snap_info));
RETURN(snap_info);
}
+static int smfs_cow_pre(struct inode *dir, struct dentry *dentry, void *new_dir,
+ void *new_dentry, int op);
+
+static int smfs_cow_post(struct inode *dir, struct dentry *dentry, void *new_dir,
+ void *new_dentry, int op);
#define COW_HOOK "cow_hook"
static int smfs_cow_pre_hook(struct inode *inode, struct dentry *dentry,
void *data1, void *data2, int op, void *handle)
int rc = 0;
ENTRY;
- if (smfs_do_cow(inode)) {
- rc = smfs_cow(inode, dentry, data1, data2, op);
+ if (smfs_do_cow(inode)) {
+ /*FIXME:WANGDI, get index from the dentry*/
+ #if 0
+ int index = 0;
+ smfs_get_dentry_name_index(dentry, &name, index);
+ smfs_free_dentry_name(&name);
+ #endif
+ rc = smfs_cow_pre(inode, dentry, data1, data2, op);
}
RETURN(rc);
}
+static int smfs_cow_post_hook(struct inode *inode, struct dentry *dentry,
+ void *data1, void *data2, int op, void *handle)
+{
+ int rc = 0;
+ ENTRY;
+
+ if (smfs_do_cow(inode)) {
+ rc = smfs_cow_post(inode, dentry, data1, data2, op);
+ }
+ RETURN(rc);
+}
+
int smfs_cow_init(struct super_block *sb)
{
struct smfs_super_info *smfs_info = S2SMI(sb);
SMFS_SET_COW(smfs_info);
- cow_hops = smfs_alloc_hook_ops(COW_HOOK, smfs_cow_pre_hook, NULL);
+ cow_hops = smfs_alloc_hook_ops(COW_HOOK, smfs_cow_pre_hook,
+ smfs_cow_post_hook);
if (!cow_hops) {
RETURN(-ENOMEM);
}
struct dentry *dentry;
root_inode = smfs_get_inode(sb, root_ino, NULL, 0);
- dentry = pre_smfs_dentry(NULL, root_inode, tmp,
- NULL);
+ smfs_init_snap_inode_info(root_inode, NULL, 0);
+ dentry = pre_smfs_dentry(NULL, root_inode, tmp);
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));
+ list_add(&snap_info->sni_list,
+ &(S2SNAPI(sb)->snap_list));
}
}
exit:
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_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;
-
- 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) >>
- inode->i_sb->s_blocksize_bits;
-
- dir_size = blocks * inode->i_sb->s_blocksize;
- RETURN(dir_size);
-
-}
int smfs_snap_test_inode(struct inode *inode, void *args)
{
struct smfs_iget_args *sargs = (struct smfs_iget_args*)args;
dir = sargs->s_inode;
- if (dir){
- if (I2SNAPI(inode)->sn_index != I2SNAPI(dir)->sn_index)
- return 0;
- } else {
+ if (sargs->s_index > 0) {
if (I2SNAPI(inode)->sn_index != sargs->s_index)
- return 0;
+ return 0;
+ }else {
+ if (dir && I2SNAPI(inode)->sn_index != I2SNAPI(dir)->sn_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 smfs_iget_args *args)
-{
- struct inode *dir;
- int vallen, rc = 0;
- ENTRY;
-
- 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_info *snap_info;
-
- snap_info = smfs_find_snap_info(inode);
- if (!snap_info) {
- RETURN(-EIO);
- }
- /*init dot_snap inode info*/
- 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)) &&
- (I2SMI(inode)->smi_flags & SM_DO_COW) &&
- smfs_primary_inode(inode)) {
- struct snap_inode_info *sni_info = I2SNAPI(inode);
- struct fsfilt_operations *sops = I2SNAPCOPS(inode);
-
- vallen = sizeof(sni_info->sn_gen);
-
- rc = sops->fs_get_snap_info(I2CI(inode), SNAP_GENERATION,
- strlen(SNAP_GENERATION),
- &sni_info->sn_gen, &vallen);
- }
- RETURN(rc);
-}
/* latest snap: returns
- the index of the latest snapshot before NOW
- hence it returns 0 in case all the volume snapshots lie in the future
LASSERT(dchild->d_inode == inode);
GOTO(out_dput, rc = 0);
}
- tmp = pre_smfs_dentry(NULL, inode, cowed_dir, NULL);
+ tmp = pre_smfs_dentry(NULL, inode, cowed_dir);
/* 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;
{
struct fsfilt_operations *snapops = I2SNAPCOPS(inode);
struct snap snap;
- struct inode *ind = NULL, *cache_ind = NULL;
- ino_t ind_ino;
+ struct inode *cache_ind = NULL;
ENTRY;
if (!snapops || !snapops->fs_create_indirect)
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(cache_ind));
- RETURN(PTR_ERR(ind));
+ RETURN(PTR_ERR(cache_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*/
- 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;
- I2SMI(ind)->sm_sninfo.sn_index = snap.sn_index;
-
- iput(ind);
+ if (!SMFS_DO_INODE_COWED(inode)) {
+ /*insert the inode to cowed inode*/
+ SMFS_SET_INODE_COWED(inode);
+ link_cowed_inode(inode);
}
RETURN(0);
}
CERROR("Can not find cino %lu inode\n", cino);
RETURN(-ENOENT);
}
+ smfs_init_snap_inode_info(inode, dir, index);
d_add(dentry, inode);
}
RETURN(0);
dot_inode = smfs_get_inode(inode->i_sb, inode->i_ino, inode,
DOT_SNAP_INDEX);
+ smfs_init_snap_inode_info(dot_inode, inode, DOT_SNAP_INDEX);
d_add(dentry, dot_inode);
rc = 1;
RETURN(rc);
typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry,
void *new_dir, void *new_dentry);
-static cow_funcs smfs_cow_funcs[HOOK_MAX + 1] = {
+static cow_funcs smfs_cow_pre_funcs[HOOK_MAX + 1] = {
[HOOK_CREATE] smfs_cow_create,
[HOOK_LOOKUP] smfs_cow_lookup,
[HOOK_LINK] smfs_cow_link,
[HOOK_SETATTR] smfs_cow_setattr,
[HOOK_WRITE] smfs_cow_write,
};
+int smfs_cow_lookup_post(struct inode *dir, struct dentry *dentry, void *data1,
+ void *data2)
+{
+ struct inode *inode = dentry->d_inode;
+ struct fsfilt_operations *sops = I2SNAPCOPS(inode);
+ int index = I2SNAPI(dir)->sn_index;
+ ENTRY;
+
+ LASSERT(inode);
+
+ if (index > 0) {
+ struct inode *cache_ind = NULL;
+
+ cache_ind = sops->fs_get_indirect(I2CI(inode), NULL, index);
+ if (cache_ind->i_ino != I2CI(inode)->i_ino) {
+ struct inode *ind_inode = NULL;
+
+ ind_inode = smfs_get_inode(dir->i_sb, cache_ind->i_ino,
+ dir, index);
+ /*replace the ind_inode here*/
+ list_del_init(&dentry->d_alias);
+ iput(inode);
+ d_instantiate(dentry, ind_inode);
+ }
+ }
+ inode = dentry->d_inode;
+
+ smfs_init_snap_inode_info(inode, dir, index);
+
+ RETURN(0);
+}
+
+static cow_funcs smfs_cow_post_funcs[HOOK_MAX + 1] = {
+ [HOOK_CREATE] NULL,
+ [HOOK_LOOKUP] smfs_cow_lookup_post,
+ [HOOK_LINK] NULL,
+ [HOOK_UNLINK] NULL,
+ [HOOK_SYMLINK] NULL,
+ [HOOK_MKDIR] NULL,
+ [HOOK_RMDIR] NULL,
+ [HOOK_MKNOD] NULL,
+ [HOOK_RENAME] NULL,
+ [HOOK_SETATTR] NULL,
+ [HOOK_WRITE] NULL,
+};
+
+static int smfs_cow_pre(struct inode *dir, struct dentry *dentry, void *new_dir,
+ void *new_dentry, int op)
+{
+ if (smfs_cow_pre_funcs[op]) {
+ return smfs_cow_pre_funcs[op](dir, dentry, new_dir, new_dentry);
+ }
+ return 0;
+}
-int smfs_cow(struct inode *dir, struct dentry *dentry, void *new_dir,
- void *new_dentry, int op)
+static int smfs_cow_post(struct inode *dir, struct dentry *dentry, void *new_dir,
+ void *new_dentry, int op)
{
- if (smfs_cow_funcs[op]) {
- return smfs_cow_funcs[op](dir, dentry, new_dir, new_dentry);
+ if (smfs_cow_post_funcs[op]) {
+ return smfs_cow_post_funcs[op](dir, dentry, new_dir, new_dentry);
}
return 0;
}
GOTO(label, rc); \
} while(0) \
-#define SMFS_GET_INODE(sb, cache_inode, dir, index, inode, rc, label) \
+#define SMFS_GET_INODE(sb, cache_inode, dir, inode, rc, label) \
do { \
LASSERT(cache_inode); \
- inode = smfs_get_inode(sb, cache_inode->i_ino, dir, index); \
+ inode = smfs_get_inode(sb, cache_inode->i_ino, dir, 0); \
iput(cache_inode); \
if (!inode) \
GOTO(label, rc = -ENOENT); \
#if CONFIG_SNAPFS
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)
{
struct option *opt_value = NULL;
char *pos;
- int opt_len = 0;
LASSERT(opts && flags);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
if (!cache_dentry)
GOTO(exit, rc = -ENOMEM);
if (cache_inode->i_op && cache_inode->i_op->readlink)
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
if (!cache_dentry)
GOTO(exit, rc = -ENOMEM);