return ret;
 }
 
-static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 cno,
+static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
                                          struct nilfs_cpinfo *ci, size_t nci)
 {
        struct buffer_head *bh;
        struct nilfs_cpfile_header *header;
        struct nilfs_checkpoint *cp;
-       __u64 curr, next;
+       __u64 curr = *cnop, next;
        unsigned long curr_blkoff, next_blkoff;
        void *kaddr;
        int n, ret;
 
        down_read(&NILFS_MDT(cpfile)->mi_sem);
 
-       if (cno == 0) {
+       if (curr == 0) {
                ret = nilfs_cpfile_get_header_block(cpfile, &bh);
                if (ret < 0)
                        goto out;
                        ret = 0;
                        goto out;
                }
-       } else
-               curr = cno;
+       } else if (unlikely(curr == ~(__u64)0)) {
+               ret = 0;
+               goto out;
+       }
+
        curr_blkoff = nilfs_cpfile_get_blkoff(cpfile, curr);
        ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 0, &bh);
        if (ret < 0)
                nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n]);
                next = le64_to_cpu(cp->cp_snapshot_list.ssl_next);
                if (next == 0) {
-                       curr = next;
+                       curr = ~(__u64)0; /* Terminator */
                        n++;
                        break;
                }
        }
        kunmap_atomic(kaddr, KM_USER0);
        brelse(bh);
+       *cnop = curr;
        ret = n;
 
  out:
  * @ci:
  * @nci:
  */
-ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile,
-                               __u64 cno, int mode,
+
+ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode,
                                struct nilfs_cpinfo *ci, size_t nci)
 {
        switch (mode) {
        case NILFS_CHECKPOINT:
-               return nilfs_cpfile_do_get_cpinfo(cpfile, cno, ci, nci);
+               return nilfs_cpfile_do_get_cpinfo(cpfile, *cnop, ci, nci);
        case NILFS_SNAPSHOT:
-               return nilfs_cpfile_do_get_ssinfo(cpfile, cno, ci, nci);
+               return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, ci, nci);
        default:
                return -EINVAL;
        }
 
 static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
                                 struct nilfs_argv *argv, int dir,
                                 ssize_t (*dofunc)(struct the_nilfs *,
-                                                  int, int,
+                                                  __u64 *, int,
                                                   void *, size_t, size_t))
 {
        void *buf;
        size_t maxmembs, total, n;
        ssize_t nr;
        int ret, i;
+       __u64 pos, ppos;
 
        if (argv->v_nmembs == 0)
                return 0;
 
        ret = 0;
        total = 0;
+       pos = argv->v_index;
        for (i = 0; i < argv->v_nmembs; i += n) {
                n = (argv->v_nmembs - i < maxmembs) ?
                        argv->v_nmembs - i : maxmembs;
                        ret = -EFAULT;
                        break;
                }
-               nr = (*dofunc)(nilfs, argv->v_index + i, argv->v_flags, buf,
-                              argv->v_size, n);
+               ppos = pos;
+               nr = (*dofunc)(nilfs, &pos, argv->v_flags, buf, argv->v_size,
+                              n);
                if (nr < 0) {
                        ret = nr;
                        break;
                        break;
                }
                total += nr;
+               if ((size_t)nr < n)
+                       break;
+               if (pos == ppos)
+                       pos += n;
        }
        argv->v_nmembs = total;
 
 }
 
 static ssize_t
-nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, int index, int flags,
+nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
                          void *buf, size_t size, size_t nmembs)
 {
-       return nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, index, flags, buf,
+       return nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
                                       nmembs);
 }
 
 }
 
 static ssize_t
-nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, int index, int flags,
+nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
                          void *buf, size_t size, size_t nmembs)
 {
-       return nilfs_sufile_get_suinfo(nilfs->ns_sufile, index, buf, nmembs);
+       return nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, nmembs);
 }
 
 static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp,
 }
 
 static ssize_t
-nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, int index, int flags,
+nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
                         void *buf, size_t size, size_t nmembs)
 {
        return nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, nmembs);
 }
 
 static ssize_t
-nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, int index, int flags,
+nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
                          void *buf, size_t size, size_t nmembs)
 {
        struct inode *dat = nilfs_dat_inode(nilfs);
 }
 
 static ssize_t
-nilfs_ioctl_do_move_blocks(struct the_nilfs *nilfs, int index, int flags,
+nilfs_ioctl_do_move_blocks(struct the_nilfs *nilfs, __u64 *posp, int flags,
                           void *buf, size_t size, size_t nmembs)
 {
        struct inode *inode;
 }
 
 static ssize_t
-nilfs_ioctl_do_delete_checkpoints(struct the_nilfs *nilfs, int index,
+nilfs_ioctl_do_delete_checkpoints(struct the_nilfs *nilfs, __u64 *posp,
                                  int flags, void *buf, size_t size,
                                  size_t nmembs)
 {
 }
 
 static ssize_t
-nilfs_ioctl_do_free_vblocknrs(struct the_nilfs *nilfs, int index, int flags,
+nilfs_ioctl_do_free_vblocknrs(struct the_nilfs *nilfs, __u64 *posp, int flags,
                              void *buf, size_t size, size_t nmembs)
 {
        int ret = nilfs_dat_freev(nilfs_dat_inode(nilfs), buf, nmembs);
 }
 
 static ssize_t
-nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, int index, int flags,
-                                void *buf, size_t size, size_t nmembs)
+nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, __u64 *posp,
+                                int flags, void *buf, size_t size,
+                                size_t nmembs)
 {
        struct inode *dat = nilfs_dat_inode(nilfs);
        struct nilfs_bmap *bmap = NILFS_I(dat)->i_bmap;
 }
 
 static ssize_t
-nilfs_ioctl_do_free_segments(struct the_nilfs *nilfs, int index, int flags,
+nilfs_ioctl_do_free_segments(struct the_nilfs *nilfs, __u64 *posp, int flags,
                             void *buf, size_t size, size_t nmembs)
 {
        struct nilfs_sb_info *sbi = nilfs_get_writer(nilfs);