diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-04-06 19:01:55 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 08:31:19 -0700 |
commit | 1f5abe7e7dbcd83e73212c6cb135a6106cea6a0b (patch) | |
tree | f80e97297d5badebd31bbb17003d76a4ea30453a /fs/nilfs2/ioctl.c | |
parent | 2c2e52fc4fca251e68f90821c9ff5cb18be4df58 (diff) |
nilfs2: replace BUG_ON and BUG calls triggerable from ioctl
Pekka Enberg advised me:
> It would be nice if BUG(), BUG_ON(), and panic() calls would be
> converted to proper error handling using WARN_ON() calls. The BUG()
> call in nilfs_cpfile_delete_checkpoints(), for example, looks to be
> triggerable from user-space via the ioctl() system call.
This will follow the comment and keep them to a minimum.
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nilfs2/ioctl.c')
-rw-r--r-- | fs/nilfs2/ioctl.c | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index cfb27892ffe8..108d281ebca5 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -489,14 +489,14 @@ nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, __u64 *posp, ret = nilfs_mdt_mark_block_dirty(dat, bdescs[i].bd_offset); if (ret < 0) { - BUG_ON(ret == -ENOENT); + WARN_ON(ret == -ENOENT); return ret; } } else { ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset, bdescs[i].bd_level); if (ret < 0) { - BUG_ON(ret == -ENOENT); + WARN_ON(ret == -ENOENT); return ret; } } @@ -519,7 +519,8 @@ nilfs_ioctl_do_free_segments(struct the_nilfs *nilfs, __u64 *posp, int flags, struct nilfs_sb_info *sbi = nilfs_get_writer(nilfs); int ret; - BUG_ON(!sbi); + if (unlikely(!sbi)) + return -EROFS; ret = nilfs_segctor_add_segments_to_be_freed( NILFS_SC(sbi), buf, nmembs); nilfs_put_writer(nilfs); @@ -539,6 +540,7 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, void __user *argp) { struct nilfs_argv argv[5]; + const char *msg; int dir, ret; if (copy_from_user(argv, argp, sizeof(argv))) @@ -546,31 +548,50 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, dir = _IOC_WRITE; ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], dir); - if (ret < 0) - goto out_move_blks; + if (ret < 0) { + msg = "cannot read source blocks"; + goto failed; + } ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], dir); - if (ret < 0) - goto out_del_cps; + if (ret < 0) { + /* + * can safely abort because checkpoints can be removed + * independently. + */ + msg = "cannot delete checkpoints"; + goto failed; + } ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], dir); - if (ret < 0) - goto out_free_vbns; + if (ret < 0) { + /* + * can safely abort because DAT file is updated atomically + * using a copy-on-write technique. + */ + msg = "cannot delete virtual blocks from DAT file"; + goto failed; + } ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], dir); - if (ret < 0) - goto out_free_vbns; + if (ret < 0) { + /* + * can safely abort because the operation is nondestructive. + */ + msg = "cannot mark copying blocks dirty"; + goto failed; + } ret = nilfs_ioctl_free_segments(nilfs, &argv[4], dir); - if (ret < 0) - goto out_free_segs; - + if (ret < 0) { + /* + * can safely abort because this operation is atomic. + */ + msg = "cannot set segments to be freed"; + goto failed; + } return 0; - out_free_segs: - BUG(); /* XXX: not implemented yet */ - out_free_vbns: - BUG();/* XXX: not implemented yet */ - out_del_cps: - BUG();/* XXX: not implemented yet */ - out_move_blks: + failed: nilfs_remove_all_gcinode(nilfs); + printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d\n", + msg, ret); return ret; } |