diff --git a/lustre/lvfs/fsfilt_smfs.c b/lustre/lvfs/fsfilt_smfs.c index 2624159f77a52cdb8270af47f97b55eb832ee0d9..af36a3b865d4ec5c4aa21d335256b460c84da015 100644 --- a/lustre/lvfs/fsfilt_smfs.c +++ b/lustre/lvfs/fsfilt_smfs.c @@ -340,7 +340,27 @@ fsfilt_smfs_getpage(struct inode *inode, long int index) if (!cache_fsfilt->fs_getpage) RETURN(ERR_PTR(-ENOSYS)); - +#if CONFIG_SNAPFS + if (SMFS_DO_COW(S2SMI(inode->i_sb))) { + struct address_space_operations *aops = + cache_inode->i_mapping->a_ops; + if (aops->bmap(cache_inode->i_mapping, index)) { + struct inode *ind_inode = NULL; + struct inode *cache_ind = NULL; + struct page *page = NULL; + + ind_inode = smfs_cow_get_ind(inode, index); + if (!ind_inode) { + RETURN(ERR_PTR(-EIO)); + } + cache_ind = I2CI(ind_inode); + /*FIXME cow inode should be bottom fs inode */ + page = cache_fsfilt->fs_getpage(cache_ind, index); + iput(ind_inode); + RETURN(page); + } + } +#endif return cache_fsfilt->fs_getpage(cache_inode, index); } diff --git a/lustre/lvfs/fsfilt_snap_ext3.c b/lustre/lvfs/fsfilt_snap_ext3.c index ff03082993cfd3fccab6c1118db7c0091be2da73..11485c87c225eb80447a37578ef2325a53b1c140 100644 --- a/lustre/lvfs/fsfilt_snap_ext3.c +++ b/lustre/lvfs/fsfilt_snap_ext3.c @@ -334,27 +334,27 @@ static int ext3_copy_reg_block(struct inode *dst, struct inode *src, int blk) if (dst_page == NULL) GOTO(src_page_unlock, rc = -ENOMEM); kmap(dst_page); - - /*FIXME: should use mapping ops or block_prepare_write to prepare the block*/ - rc = block_prepare_write(dst_page, 0, PAGE_CACHE_SIZE, ext3_get_block); - if (rc) { - CERROR("inode %lu, prepare write rc=%d \n", dst->i_ino, rc); - GOTO(dst_page_unlock, rc); - } - - memcpy(page_address(dst_page), page_address(src_page), PAGE_CACHE_SIZE); - - generic_commit_write(NULL, dst_page, 0, PAGE_CACHE_SIZE); + rc = dst->i_mapping->a_ops->prepare_write(NULL, dst_page, 0, + PAGE_CACHE_SIZE - 1); + if (rc) + GOTO(dst_page_unlock, rc = -EFAULT); + memcpy(page_address(dst_page), page_address(src_page), PAGE_CACHE_SIZE); + + flush_dcache_page(dst_page); + + rc = dst->i_mapping->a_ops->commit_write(NULL, dst_page, 0, + PAGE_CACHE_SIZE - 1); + if (!rc) + rc = 1; dst_page_unlock: - kunmap(dst_page); - UnlockPage(dst_page); - page_cache_release(dst_page); + kunmap(dst_page); + UnlockPage(dst_page); + page_cache_release(dst_page); src_page_unlock: - kunmap(src_page); - page_cache_release(src_page); - - RETURN(rc); + kunmap(src_page); + page_cache_release(src_page); + RETURN(rc); } static int ext3_copy_dir_block(struct inode *dst, struct inode *src, int blk) { diff --git a/lustre/smfs/smfs_cow.c b/lustre/smfs/smfs_cow.c index e3ca33731711db9f113f720e7f4544e1ce289d78..3c68a244a7dd27184945080b3dc8c537b495f720 100644 --- a/lustre/smfs/smfs_cow.c +++ b/lustre/smfs/smfs_cow.c @@ -646,6 +646,33 @@ exit: } EXPORT_SYMBOL(smfs_cow_write); +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);