Commit 014049a1 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2:
  nilfs2: check size of array structured data exchanged via ioctls
  nilfs2: fix lock order reversal in nilfs_clean_segments ioctl
  nilfs2: fix possible circular locking for get information ioctls
  nilfs2: ensure to clear dirty state when deleting metadata file block
  nilfs2: fix circular locking dependency of writer mutex
  nilfs2: fix possible recovery failure due to block creation without writer
parents c98861f7 83aca8f4
This diff is collapsed.
......@@ -77,19 +77,22 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
void *))
{
struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs;
struct nilfs_sb_info *writer = NULL;
struct super_block *sb = inode->i_sb;
struct nilfs_transaction_info ti;
struct buffer_head *bh;
int err;
if (!sb) {
writer = nilfs_get_writer(nilfs);
if (!writer) {
/*
* Make sure this function is not called from any
* read-only context.
*/
if (!nilfs->ns_writer) {
WARN_ON(1);
err = -EROFS;
goto out;
}
sb = writer->s_super;
sb = nilfs->ns_writer->s_super;
}
nilfs_transaction_begin(sb, &ti, 0);
......@@ -127,8 +130,6 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
err = nilfs_transaction_commit(sb);
else
nilfs_transaction_abort(sb);
if (writer)
nilfs_put_writer(nilfs);
out:
return err;
}
......@@ -299,7 +300,7 @@ int nilfs_mdt_delete_block(struct inode *inode, unsigned long block)
int err;
err = nilfs_bmap_delete(ii->i_bmap, block);
if (likely(!err)) {
if (!err || err == -ENOENT) {
nilfs_mdt_mark_dirty(inode);
nilfs_mdt_forget_block(inode, block);
}
......
......@@ -236,7 +236,8 @@ extern int nilfs_sync_file(struct file *, struct dentry *, int);
/* ioctl.c */
long nilfs_ioctl(struct file *, unsigned int, unsigned long);
int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, void __user *);
int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *,
void **);
/* inode.c */
extern struct inode *nilfs_new_inode(struct inode *, int);
......
......@@ -128,7 +128,8 @@ void nilfs_forget_buffer(struct buffer_head *bh)
lock_buffer(bh);
clear_buffer_nilfs_volatile(bh);
if (test_clear_buffer_dirty(bh) && nilfs_page_buffers_clean(page))
clear_buffer_dirty(bh);
if (nilfs_page_buffers_clean(page))
__nilfs_clear_page_dirty(page);
clear_buffer_uptodate(bh);
......
......@@ -407,6 +407,7 @@ void nilfs_dispose_segment_list(struct list_head *head)
}
static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
struct nilfs_sb_info *sbi,
struct nilfs_recovery_info *ri)
{
struct list_head *head = &ri->ri_used_segments;
......@@ -421,6 +422,7 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
segnum[2] = ri->ri_segnum;
segnum[3] = ri->ri_nextnum;
nilfs_attach_writer(nilfs, sbi);
/*
* Releasing the next segment of the latest super root.
* The next segment is invalidated by this recovery.
......@@ -459,10 +461,10 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
nilfs->ns_pseg_offset = 0;
nilfs->ns_seg_seq = ri->ri_seq + 2;
nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0];
return 0;
failed:
/* No need to recover sufile because it will be destroyed on error */
nilfs_detach_writer(nilfs, sbi);
return err;
}
......@@ -728,7 +730,7 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs,
goto failed;
if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) {
err = nilfs_prepare_segment_for_recovery(nilfs, ri);
err = nilfs_prepare_segment_for_recovery(nilfs, sbi, ri);
if (unlikely(err)) {
printk(KERN_ERR "NILFS: Error preparing segments for "
"recovery.\n");
......
......@@ -2589,7 +2589,8 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head)
}
}
int nilfs_clean_segments(struct super_block *sb, void __user *argp)
int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
void **kbufs)
{
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct nilfs_sc_info *sci = NILFS_SC(sbi);
......@@ -2606,7 +2607,7 @@ int nilfs_clean_segments(struct super_block *sb, void __user *argp)
err = nilfs_init_gcdat_inode(nilfs);
if (unlikely(err))
goto out_unlock;
err = nilfs_ioctl_prepare_clean_segments(nilfs, argp);
err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs);
if (unlikely(err))
goto out_unlock;
......
......@@ -222,7 +222,8 @@ extern int nilfs_construct_segment(struct super_block *);
extern int nilfs_construct_dsync_segment(struct super_block *, struct inode *,
loff_t, loff_t);
extern void nilfs_flush_segment(struct super_block *, ino_t);
extern int nilfs_clean_segments(struct super_block *, void __user *);
extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *,
void **);
extern int nilfs_segctor_add_segments_to_be_freed(struct nilfs_sc_info *,
__u64 *, size_t);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment