+static int smfs_cow_readdir_pre(struct inode *dir, void *de, void *data1,
+ void *data2)
+{
+ struct file *filp = (struct file*)de;
+ void *dirent = data1;
+ filldir_t filldir = (filldir_t)data2;
+ struct snap_info *snap_info = NULL;
+
+ if (smfs_under_dotsnap_inode(dir))
+ RETURN(0);
+
+ snap_info = smfs_find_snap_info(dir);
+
+ if (!snap_info) {
+ CDEBUG(D_INFO, "can not find snap info for ino %lu\n",
+ dir->i_ino);
+ RETURN(-EINVAL);
+ }
+
+ if (smfs_primary_inode(dir)) {
+ if (filp->f_pos == 0) {
+ struct snap_dot_info *dot = snap_info->sni_dot_info;
+ if (filldir(dirent, dot->dot_name, dot->dot_name_len,
+ filp->f_pos, -1, 0)) {
+ CERROR("fill .snap error \n");
+ RETURN(-EINVAL);
+ }
+ } else {
+ filp->f_pos -= 1;
+ }
+ } else if (smfs_dotsnap_inode(dir)) {
+ struct snap_table *table = snap_info->sni_table;
+ int i = 0;
+
+ if (filp->f_pos < 0)
+ RETURN(-EINVAL);
+
+ if ((filp->f_pos == 0) && filldir(dirent, ".", 1,
+ filp->f_pos++,
+ dir->i_ino, 0) < 0)
+ RETURN(-EIO);
+ if ((filp->f_pos == 1) && filldir(dirent, "..", 2,
+ filp->f_pos++,
+ dir->i_ino, 0) < 0)
+ RETURN(-EIO);
+
+ for (i = filp->f_pos - 2; i < table->sntbl_count; i++,
+ filp->f_pos++) {
+ int slot = table->sntbl_count-i;
+
+ if (filldir(dirent, table->sntbl_items[slot].sn_name,
+ strlen(table->sntbl_items[slot].sn_name),
+ filp->f_pos, dir->i_ino, 0))
+ break;
+
+ }
+ RETURN(1);
+ }
+
+ RETURN(0);
+}
+
+
+typedef int (*cow_funcs)(struct inode *dir, void *dentry, void *new_dir,
+ void *new_dentry);