return -EINVAL;
}
- /* cannot delete the latest checkpoint */
- if (start == nilfs_mdt_cno(cpfile) - 1)
- return -EPERM;
-
down_write(&NILFS_MDT(cpfile)->mi_sem);
ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh);
if (ret < 0) {
if (ret != -ENOENT)
- goto out_header;
+ break;
/* skip hole */
ret = 0;
continue;
continue;
printk(KERN_ERR "%s: cannot delete block\n",
__func__);
- goto out_header;
+ break;
}
}
kunmap_atomic(kaddr, KM_USER0);
}
- out_header:
brelse(header_bh);
out_sem:
struct nilfs_cpinfo ci;
__u64 tcno = cno;
ssize_t nci;
- int ret;
nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, sizeof(ci), 1);
if (nci < 0)
return nci;
else if (nci == 0 || ci.ci_cno != cno)
return -ENOENT;
-
- /* cannot delete the latest checkpoint nor snapshots */
- ret = nilfs_cpinfo_snapshot(&ci);
- if (ret < 0)
- return ret;
- else if (ret > 0 || cno == nilfs_mdt_cno(cpfile) - 1)
- return -EPERM;
+ else if (nilfs_cpinfo_snapshot(&ci))
+ return -EBUSY;
return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1);
}
void *kaddr;
int ret;
- if (cno == 0)
- return -ENOENT; /* checkpoint number 0 is invalid */
+ /* CP number is invalid if it's zero or larger than the
+ largest exist one.*/
+ if (cno == 0 || cno >= nilfs_mdt_cno(cpfile))
+ return -ENOENT;
down_read(&NILFS_MDT(cpfile)->mi_sem);
ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh);
goto out;
kaddr = kmap_atomic(bh->b_page, KM_USER0);
cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
- ret = nilfs_checkpoint_snapshot(cp);
+ if (nilfs_checkpoint_invalid(cp))
+ ret = -ENOENT;
+ else
+ ret = nilfs_checkpoint_snapshot(cp);
kunmap_atomic(kaddr, KM_USER0);
brelse(bh);
case NILFS_CHECKPOINT:
/*
* Check for protecting existing snapshot mounts:
- * bd_mount_sem is used to make this operation atomic and
+ * ns_mount_mutex is used to make this operation atomic and
* exclusive with a new mount job. Though it doesn't cover
* umount, it's enough for the purpose.
*/
- down(&nilfs->ns_bdev->bd_mount_sem);
if (nilfs_checkpoint_is_mounted(nilfs, cno, 1)) {
/* Current implementation does not have to protect
plain read-only mounts since they are exclusive
ret = -EBUSY;
} else
ret = nilfs_cpfile_clear_snapshot(cpfile, cno);
- up(&nilfs->ns_bdev->bd_mount_sem);
return ret;
case NILFS_SNAPSHOT:
return nilfs_cpfile_set_snapshot(cpfile, cno);