struct snap_info *snap_info = S2SNAPI(sb);
struct snap_table *snap_table = NULL;
struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
- int rc = 0, size, table_size, vallen;
+ struct dentry *d_root = snap_info->snap_root;
+ int rc = 0, size, table_size, vallen, i;
ENTRY;
/*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) {
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;
+ }
/*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) {
}
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) {
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);
}
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);
}
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);
}
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;
/* 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) {
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*/
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);
}
}
struct snap_table *table = snap_info->sntbl;
long blocks[2]={-1,-1};
int index = 0, i, rc = 0;
- size_t count = *(size_t *)data1;
- loff_t pos = *(loff_t*)data2;
+ size_t count;
+ loff_t pos;
ENTRY;
- LASSERT(count);
- LASSERT(pos);
+ LASSERT(data1);
+ LASSERT(data2);
+
+ count = *(size_t *)data1;
+ pos = *(loff_t*)data2;
down(&inode->i_sem);
}
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,