+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);
+}
+