Skip to content

Commit

Permalink
nilfs2: avoid double error caused by nilfs_transaction_end
Browse files Browse the repository at this point in the history
Pekka Enberg pointed out that double error handlings found after
nilfs_transaction_end() can be avoided by separating abort operation:

 OK, I don't understand this. The only way nilfs_transaction_end() can
 fail is if we have NILFS_TI_SYNC set and we fail to construct the
 segment. But why do we want to construct a segment if we don't commit?

 I guess what I'm asking is why don't we have a separate
 nilfs_transaction_abort() function that can't fail for the erroneous
 case to avoid this double error value tracking thing?

This does the separation and renames nilfs_transaction_end() to
nilfs_transaction_commit() for clarification.

Since, some calls of these functions were used just for exclusion control
against the segment constructor, they are replaced with semaphore
operations.

Acked-by: Pekka Enberg <[email protected]>
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 a2e7d2d commit 47420c7
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 75 deletions.
23 changes: 14 additions & 9 deletions fs/nilfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff,
goto out;
err = nilfs_bmap_insert(ii->i_bmap, (unsigned long)blkoff,
(unsigned long)bh_result);
nilfs_transaction_end(inode->i_sb, !err);
if (unlikely(err != 0)) {
if (err == -EEXIST) {
/*
Expand All @@ -100,8 +99,10 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff,
inode->i_ino);
err = -EIO;
}
nilfs_transaction_abort(inode->i_sb);
goto out;
}
nilfs_transaction_commit(inode->i_sb); /* never fails */
/* Error handling should be detailed */
set_buffer_new(bh_result);
map_bh(bh_result, inode->i_sb, 0); /* dbn must be changed
Expand Down Expand Up @@ -203,7 +204,7 @@ static int nilfs_write_begin(struct file *file, struct address_space *mapping,
err = block_write_begin(file, mapping, pos, len, flags, pagep,
fsdata, nilfs_get_block);
if (unlikely(err))
nilfs_transaction_end(inode->i_sb, 0);
nilfs_transaction_abort(inode->i_sb);
return err;
}

Expand All @@ -221,7 +222,7 @@ static int nilfs_write_end(struct file *file, struct address_space *mapping,
copied = generic_write_end(file, mapping, pos, len, copied, page,
fsdata);
nilfs_set_file_dirty(NILFS_SB(inode->i_sb), inode, nr_dirty);
err = nilfs_transaction_end(inode->i_sb, 1);
err = nilfs_transaction_commit(inode->i_sb);
return err ? : copied;
}

Expand Down Expand Up @@ -641,7 +642,7 @@ void nilfs_truncate(struct inode *inode)
nilfs_set_transaction_flag(NILFS_TI_SYNC);

nilfs_set_file_dirty(NILFS_SB(sb), inode, 0);
nilfs_transaction_end(sb, 1);
nilfs_transaction_commit(sb);
/* May construct a logical segment and may fail in sync mode.
But truncate has no return value. */
}
Expand Down Expand Up @@ -669,7 +670,7 @@ void nilfs_delete_inode(struct inode *inode)
/* nilfs_free_inode() marks inode buffer dirty */
if (IS_SYNC(inode))
nilfs_set_transaction_flag(NILFS_TI_SYNC);
nilfs_transaction_end(sb, 1);
nilfs_transaction_commit(sb);
/* May construct a logical segment and may fail in sync mode.
But delete_inode has no return value. */
}
Expand All @@ -679,7 +680,7 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
struct nilfs_transaction_info ti;
struct inode *inode = dentry->d_inode;
struct super_block *sb = inode->i_sb;
int err, err2;
int err;

err = inode_change_ok(inode, iattr);
if (err)
Expand All @@ -691,8 +692,12 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
err = inode_setattr(inode, iattr);
if (!err && (iattr->ia_valid & ATTR_MODE))
err = nilfs_acl_chmod(inode);
err2 = nilfs_transaction_end(sb, 1);
return err ? : err2;
if (likely(!err))
err = nilfs_transaction_commit(sb);
else
nilfs_transaction_abort(sb);

return err;
}

int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode,
Expand Down Expand Up @@ -817,5 +822,5 @@ void nilfs_dirty_inode(struct inode *inode)
nilfs_transaction_begin(inode->i_sb, &ti, 0);
if (likely(inode->i_ino != NILFS_SKETCH_INO))
nilfs_mark_inode_dirty(inode);
nilfs_transaction_end(inode->i_sb, 1); /* never fails */
nilfs_transaction_commit(inode->i_sb); /* never fails */
}
58 changes: 34 additions & 24 deletions fs/nilfs2/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,11 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
nilfs_transaction_begin(inode->i_sb, &ti, 0);
ret = nilfs_cpfile_change_cpmode(
cpfile, cpmode.cm_cno, cpmode.cm_mode);
nilfs_transaction_end(inode->i_sb, !ret);
if (unlikely(ret < 0)) {
nilfs_transaction_abort(inode->i_sb);
return ret;
}
nilfs_transaction_commit(inode->i_sb); /* never fails */
return ret;
}

Expand All @@ -125,7 +129,11 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,

nilfs_transaction_begin(inode->i_sb, &ti, 0);
ret = nilfs_cpfile_delete_checkpoint(cpfile, cno);
nilfs_transaction_end(inode->i_sb, !ret);
if (unlikely(ret < 0)) {
nilfs_transaction_abort(inode->i_sb);
return ret;
}
nilfs_transaction_commit(inode->i_sb); /* never fails */
return ret;
}

Expand All @@ -142,16 +150,17 @@ static int nilfs_ioctl_get_cpinfo(struct inode *inode, struct file *filp,
{
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
struct nilfs_argv argv;
struct nilfs_transaction_info ti;
int ret;

if (copy_from_user(&argv, argp, sizeof(argv)))
return -EFAULT;

nilfs_transaction_begin(inode->i_sb, &ti, 0);
down_read(&nilfs->ns_segctor_sem);
ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
nilfs_ioctl_do_get_cpinfo);
nilfs_transaction_end(inode->i_sb, 0);
up_read(&nilfs->ns_segctor_sem);
if (ret < 0)
return ret;

if (copy_to_user(argp, &argv, sizeof(argv)))
ret = -EFAULT;
Expand All @@ -161,14 +170,13 @@ static int nilfs_ioctl_get_cpinfo(struct inode *inode, struct file *filp,
static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp)
{
struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile;
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
struct nilfs_cpstat cpstat;
struct nilfs_transaction_info ti;
int ret;

nilfs_transaction_begin(inode->i_sb, &ti, 0);
ret = nilfs_cpfile_get_stat(cpfile, &cpstat);
nilfs_transaction_end(inode->i_sb, 0);
down_read(&nilfs->ns_segctor_sem);
ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
up_read(&nilfs->ns_segctor_sem);
if (ret < 0)
return ret;

Expand All @@ -189,16 +197,17 @@ static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp,
{
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
struct nilfs_argv argv;
struct nilfs_transaction_info ti;
int ret;

if (copy_from_user(&argv, argp, sizeof(argv)))
return -EFAULT;

nilfs_transaction_begin(inode->i_sb, &ti, 0);
down_read(&nilfs->ns_segctor_sem);
ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
nilfs_ioctl_do_get_suinfo);
nilfs_transaction_end(inode->i_sb, 0);
up_read(&nilfs->ns_segctor_sem);
if (ret < 0)
return ret;

if (copy_to_user(argp, &argv, sizeof(argv)))
ret = -EFAULT;
Expand All @@ -208,14 +217,13 @@ static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp,
static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
unsigned int cmd, void __user *argp)
{
struct inode *sufile = NILFS_SB(inode->i_sb)->s_nilfs->ns_sufile;
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
struct nilfs_sustat sustat;
struct nilfs_transaction_info ti;
int ret;

nilfs_transaction_begin(inode->i_sb, &ti, 0);
ret = nilfs_sufile_get_stat(sufile, &sustat);
nilfs_transaction_end(inode->i_sb, 0);
down_read(&nilfs->ns_segctor_sem);
ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
up_read(&nilfs->ns_segctor_sem);
if (ret < 0)
return ret;

Expand All @@ -236,16 +244,17 @@ static int nilfs_ioctl_get_vinfo(struct inode *inode, struct file *filp,
{
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
struct nilfs_argv argv;
struct nilfs_transaction_info ti;
int ret;

if (copy_from_user(&argv, argp, sizeof(argv)))
return -EFAULT;

nilfs_transaction_begin(inode->i_sb, &ti, 0);
down_read(&nilfs->ns_segctor_sem);
ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
nilfs_ioctl_do_get_vinfo);
nilfs_transaction_end(inode->i_sb, 0);
up_read(&nilfs->ns_segctor_sem);
if (ret < 0)
return ret;

if (copy_to_user(argp, &argv, sizeof(argv)))
ret = -EFAULT;
Expand Down Expand Up @@ -280,16 +289,17 @@ static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
{
struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
struct nilfs_argv argv;
struct nilfs_transaction_info ti;
int ret;

if (copy_from_user(&argv, argp, sizeof(argv)))
return -EFAULT;

nilfs_transaction_begin(inode->i_sb, &ti, 0);
down_read(&nilfs->ns_segctor_sem);
ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
nilfs_ioctl_do_get_bdescs);
nilfs_transaction_end(inode->i_sb, 0);
up_read(&nilfs->ns_segctor_sem);
if (ret < 0)
return ret;

if (copy_to_user(argp, &argv, sizeof(argv)))
ret = -EFAULT;
Expand Down
5 changes: 4 additions & 1 deletion fs/nilfs2/mdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
brelse(bh);

failed_unlock:
nilfs_transaction_end(sb, !err);
if (likely(!err))
err = nilfs_transaction_commit(sb);
else
nilfs_transaction_abort(sb);
if (writer)
nilfs_put_writer(nilfs);
out:
Expand Down
Loading

0 comments on commit 47420c7

Please sign in to comment.