Skip to content

Commit

Permalink
nilfs2: fix improper return values of nilfs_get_cpinfo ioctl
Browse files Browse the repository at this point in the history
A few tool developers gave me requests for fixing inconvenient return
value of nilfs_get_cpinfo() ioctl; if the requested mode is NILFS_SNAPSHOT
and the specified start entry is not a snapshot, the ioctl unnaturally
returns one as the number of acquired snapshot item.

In addition, the ioctl function returns an ENOENT error for checkpoints
within blocks deleted by garbage collection.

These behaviors require corrections for programs which enumerate
snapshots.  This resolves the inconvenience by changing the return values
to zero for the above cases.

Signed-off-by: Ryusuke Konishi <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
konis authored and torvalds committed Apr 7, 2009
1 parent b028fcf commit 7fa10d2
Showing 1 changed file with 18 additions and 12 deletions.
30 changes: 18 additions & 12 deletions fs/nilfs2/cpfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
__u64 curr = *cnop, next;
unsigned long curr_blkoff, next_blkoff;
void *kaddr;
int n, ret;
int n = 0, ret;

down_read(&NILFS_MDT(cpfile)->mi_sem);

Expand All @@ -455,27 +455,33 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,

curr_blkoff = nilfs_cpfile_get_blkoff(cpfile, curr);
ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 0, &bh);
if (ret < 0)
if (unlikely(ret < 0)) {
if (ret == -ENOENT)
ret = 0; /* No snapshots (started from a hole block) */
goto out;
}
kaddr = kmap_atomic(bh->b_page, KM_USER0);
for (n = 0; n < nci; n++) {
cp = nilfs_cpfile_block_get_checkpoint(
cpfile, curr, bh, kaddr);
nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n]);
next = le64_to_cpu(cp->cp_snapshot_list.ssl_next);
if (next == 0) {
curr = ~(__u64)0; /* Terminator */
n++;
while (n < nci) {
cp = nilfs_cpfile_block_get_checkpoint(cpfile, curr, bh, kaddr);
curr = ~(__u64)0; /* Terminator */
if (unlikely(nilfs_checkpoint_invalid(cp) ||
!nilfs_checkpoint_snapshot(cp)))
break;
}
nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n++]);
next = le64_to_cpu(cp->cp_snapshot_list.ssl_next);
if (next == 0)
break; /* reach end of the snapshot list */

next_blkoff = nilfs_cpfile_get_blkoff(cpfile, next);
if (curr_blkoff != next_blkoff) {
kunmap_atomic(kaddr, KM_USER0);
brelse(bh);
ret = nilfs_cpfile_get_checkpoint_block(cpfile, next,
0, &bh);
if (ret < 0)
if (unlikely(ret < 0)) {
WARN_ON(ret == -ENOENT);
goto out;
}
kaddr = kmap_atomic(bh->b_page, KM_USER0);
}
curr = next;
Expand Down

0 comments on commit 7fa10d2

Please sign in to comment.