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, ...@@ -77,19 +77,22 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
void *)) void *))
{ {
struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs; struct the_nilfs *nilfs = NILFS_MDT(inode)->mi_nilfs;
struct nilfs_sb_info *writer = NULL;
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
struct buffer_head *bh; struct buffer_head *bh;
int err; int err;
if (!sb) { 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; err = -EROFS;
goto out; goto out;
} }
sb = writer->s_super; sb = nilfs->ns_writer->s_super;
} }
nilfs_transaction_begin(sb, &ti, 0); nilfs_transaction_begin(sb, &ti, 0);
...@@ -127,8 +130,6 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block, ...@@ -127,8 +130,6 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
err = nilfs_transaction_commit(sb); err = nilfs_transaction_commit(sb);
else else
nilfs_transaction_abort(sb); nilfs_transaction_abort(sb);
if (writer)
nilfs_put_writer(nilfs);
out: out:
return err; return err;
} }
...@@ -299,7 +300,7 @@ int nilfs_mdt_delete_block(struct inode *inode, unsigned long block) ...@@ -299,7 +300,7 @@ int nilfs_mdt_delete_block(struct inode *inode, unsigned long block)
int err; int err;
err = nilfs_bmap_delete(ii->i_bmap, block); err = nilfs_bmap_delete(ii->i_bmap, block);
if (likely(!err)) { if (!err || err == -ENOENT) {
nilfs_mdt_mark_dirty(inode); nilfs_mdt_mark_dirty(inode);
nilfs_mdt_forget_block(inode, block); nilfs_mdt_forget_block(inode, block);
} }
......
...@@ -236,7 +236,8 @@ extern int nilfs_sync_file(struct file *, struct dentry *, int); ...@@ -236,7 +236,8 @@ extern int nilfs_sync_file(struct file *, struct dentry *, int);
/* ioctl.c */ /* ioctl.c */
long nilfs_ioctl(struct file *, unsigned int, unsigned long); 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 */ /* inode.c */
extern struct inode *nilfs_new_inode(struct inode *, int); extern struct inode *nilfs_new_inode(struct inode *, int);
......
...@@ -128,7 +128,8 @@ void nilfs_forget_buffer(struct buffer_head *bh) ...@@ -128,7 +128,8 @@ void nilfs_forget_buffer(struct buffer_head *bh)
lock_buffer(bh); lock_buffer(bh);
clear_buffer_nilfs_volatile(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); __nilfs_clear_page_dirty(page);
clear_buffer_uptodate(bh); clear_buffer_uptodate(bh);
......
...@@ -407,6 +407,7 @@ void nilfs_dispose_segment_list(struct list_head *head) ...@@ -407,6 +407,7 @@ void nilfs_dispose_segment_list(struct list_head *head)
} }
static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
struct nilfs_sb_info *sbi,
struct nilfs_recovery_info *ri) struct nilfs_recovery_info *ri)
{ {
struct list_head *head = &ri->ri_used_segments; struct list_head *head = &ri->ri_used_segments;
...@@ -421,6 +422,7 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, ...@@ -421,6 +422,7 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
segnum[2] = ri->ri_segnum; segnum[2] = ri->ri_segnum;
segnum[3] = ri->ri_nextnum; segnum[3] = ri->ri_nextnum;
nilfs_attach_writer(nilfs, sbi);
/* /*
* Releasing the next segment of the latest super root. * Releasing the next segment of the latest super root.
* The next segment is invalidated by this recovery. * The next segment is invalidated by this recovery.
...@@ -459,10 +461,10 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, ...@@ -459,10 +461,10 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
nilfs->ns_pseg_offset = 0; nilfs->ns_pseg_offset = 0;
nilfs->ns_seg_seq = ri->ri_seq + 2; nilfs->ns_seg_seq = ri->ri_seq + 2;
nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0]; nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0];
return 0;
failed: failed:
/* No need to recover sufile because it will be destroyed on error */ /* No need to recover sufile because it will be destroyed on error */
nilfs_detach_writer(nilfs, sbi);
return err; return err;
} }
...@@ -728,7 +730,7 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs, ...@@ -728,7 +730,7 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs,
goto failed; goto failed;
if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) { 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)) { if (unlikely(err)) {
printk(KERN_ERR "NILFS: Error preparing segments for " printk(KERN_ERR "NILFS: Error preparing segments for "
"recovery.\n"); "recovery.\n");
......
...@@ -2589,7 +2589,8 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head) ...@@ -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_sb_info *sbi = NILFS_SB(sb);
struct nilfs_sc_info *sci = NILFS_SC(sbi); struct nilfs_sc_info *sci = NILFS_SC(sbi);
...@@ -2606,7 +2607,7 @@ int nilfs_clean_segments(struct super_block *sb, void __user *argp) ...@@ -2606,7 +2607,7 @@ int nilfs_clean_segments(struct super_block *sb, void __user *argp)
err = nilfs_init_gcdat_inode(nilfs); err = nilfs_init_gcdat_inode(nilfs);
if (unlikely(err)) if (unlikely(err))
goto out_unlock; goto out_unlock;
err = nilfs_ioctl_prepare_clean_segments(nilfs, argp); err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs);
if (unlikely(err)) if (unlikely(err))
goto out_unlock; goto out_unlock;
......
...@@ -222,7 +222,8 @@ extern int nilfs_construct_segment(struct super_block *); ...@@ -222,7 +222,8 @@ extern int nilfs_construct_segment(struct super_block *);
extern int nilfs_construct_dsync_segment(struct super_block *, struct inode *, extern int nilfs_construct_dsync_segment(struct super_block *, struct inode *,
loff_t, loff_t); loff_t, loff_t);
extern void nilfs_flush_segment(struct super_block *, ino_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 *, extern int nilfs_segctor_add_segments_to_be_freed(struct nilfs_sc_info *,
__u64 *, size_t); __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