return ret;
 }
 
+/**
+ * nilfs_cpfile_create_checkpoint - create a checkpoint entry on cpfile
+ * @cpfile: checkpoint file inode
+ * @cno:    number of checkpoint to set up
+ *
+ * This function creates a checkpoint with the number specified by @cno on
+ * cpfile.  If the specified checkpoint entry already exists due to a past
+ * failure, it will be reused without returning an error.
+ * In either case, the buffer of the block containing the checkpoint entry
+ * and the cpfile inode are made dirty for inclusion in the write log.
+ *
+ * Return: 0 on success, or the following negative error code on failure.
+ * * %-ENOMEM  - Insufficient memory available.
+ * * %-EIO     - I/O error (including metadata corruption).
+ * * %-EROFS   - Read only filesystem
+ */
+int nilfs_cpfile_create_checkpoint(struct inode *cpfile, __u64 cno)
+{
+       struct buffer_head *header_bh, *cp_bh;
+       struct nilfs_cpfile_header *header;
+       struct nilfs_checkpoint *cp;
+       void *kaddr;
+       int ret;
+
+       if (WARN_ON_ONCE(cno < 1))
+               return -EIO;
+
+       down_write(&NILFS_MDT(cpfile)->mi_sem);
+       ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
+       if (unlikely(ret < 0)) {
+               if (ret == -ENOENT) {
+                       nilfs_error(cpfile->i_sb,
+                                   "checkpoint creation failed due to metadata corruption.");
+                       ret = -EIO;
+               }
+               goto out_sem;
+       }
+       ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 1, &cp_bh);
+       if (unlikely(ret < 0))
+               goto out_header;
+
+       kaddr = kmap_local_page(cp_bh->b_page);
+       cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
+       if (nilfs_checkpoint_invalid(cp)) {
+               /* a newly-created checkpoint */
+               nilfs_checkpoint_clear_invalid(cp);
+               if (!nilfs_cpfile_is_in_first(cpfile, cno))
+                       nilfs_cpfile_block_add_valid_checkpoints(cpfile, cp_bh,
+                                                                kaddr, 1);
+               kunmap_local(kaddr);
+
+               kaddr = kmap_local_page(header_bh->b_page);
+               header = nilfs_cpfile_block_get_header(cpfile, header_bh,
+                                                      kaddr);
+               le64_add_cpu(&header->ch_ncheckpoints, 1);
+               kunmap_local(kaddr);
+               mark_buffer_dirty(header_bh);
+       } else {
+               kunmap_local(kaddr);
+       }
+
+       /* Force the buffer and the inode to become dirty */
+       mark_buffer_dirty(cp_bh);
+       brelse(cp_bh);
+       nilfs_mdt_mark_dirty(cpfile);
+
+out_header:
+       brelse(header_bh);
+
+out_sem:
+       up_write(&NILFS_MDT(cpfile)->mi_sem);
+       return ret;
+}
+
 /**
  * nilfs_cpfile_put_checkpoint - put a checkpoint
  * @cpfile: inode of checkpoint file
 
 int nilfs_cpfile_get_checkpoint(struct inode *, __u64, int,
                                struct nilfs_checkpoint **,
                                struct buffer_head **);
+int nilfs_cpfile_create_checkpoint(struct inode *cpfile, __u64 cno);
 void nilfs_cpfile_put_checkpoint(struct inode *, __u64, struct buffer_head *);
 int nilfs_cpfile_delete_checkpoints(struct inode *, __u64, __u64);
 int nilfs_cpfile_delete_checkpoint(struct inode *, __u64);
 
        nilfs_mdt_clear_dirty(nilfs->ns_dat);
 }
 
-static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)
-{
-       struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
-       struct buffer_head *bh_cp;
-       struct nilfs_checkpoint *raw_cp;
-       int err;
-
-       /* XXX: this interface will be changed */
-       err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, nilfs->ns_cno, 1,
-                                         &raw_cp, &bh_cp);
-       if (likely(!err)) {
-               /*
-                * The following code is duplicated with cpfile.  But, it is
-                * needed to collect the checkpoint even if it was not newly
-                * created.
-                */
-               mark_buffer_dirty(bh_cp);
-               nilfs_mdt_mark_dirty(nilfs->ns_cpfile);
-               nilfs_cpfile_put_checkpoint(
-                       nilfs->ns_cpfile, nilfs->ns_cno, bh_cp);
-       } else if (err == -EINVAL || err == -ENOENT) {
-               nilfs_error(sci->sc_super,
-                           "checkpoint creation failed due to metadata corruption.");
-               err = -EIO;
-       }
-       return err;
-}
-
 static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci)
 {
        struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
                        break;
                nilfs_sc_cstage_inc(sci);
                /* Creating a checkpoint */
-               err = nilfs_segctor_create_checkpoint(sci);
+               err = nilfs_cpfile_create_checkpoint(nilfs->ns_cpfile,
+                                                    nilfs->ns_cno);
                if (unlikely(err))
                        break;
                fallthrough;