diff options
Diffstat (limited to 'fs/nilfs2/segment.c')
| -rw-r--r-- | fs/nilfs2/segment.c | 526 | 
1 files changed, 194 insertions, 332 deletions
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 687d090cea3..a1a191634ab 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -104,8 +104,7 @@ struct nilfs_sc_operations {  static void nilfs_segctor_start_timer(struct nilfs_sc_info *);  static void nilfs_segctor_do_flush(struct nilfs_sc_info *, int);  static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *); -static void nilfs_dispose_list(struct nilfs_sb_info *, struct list_head *, -			       int); +static void nilfs_dispose_list(struct the_nilfs *, struct list_head *, int);  #define nilfs_cnt32_gt(a, b)   \  	(typecheck(__u32, a) && typecheck(__u32, b) && \ @@ -182,7 +181,6 @@ int nilfs_transaction_begin(struct super_block *sb,  			    struct nilfs_transaction_info *ti,  			    int vacancy_check)  { -	struct nilfs_sb_info *sbi;  	struct the_nilfs *nilfs;  	int ret = nilfs_prepare_segment_lock(ti); @@ -191,10 +189,9 @@ int nilfs_transaction_begin(struct super_block *sb,  	if (ret > 0)  		return 0; -	vfs_check_frozen(sb, SB_FREEZE_WRITE); +	sb_start_intwrite(sb); -	sbi = NILFS_SB(sb); -	nilfs = sbi->s_nilfs; +	nilfs = sb->s_fs_info;  	down_read(&nilfs->ns_segctor_sem);  	if (vacancy_check && nilfs_near_disk_full(nilfs)) {  		up_read(&nilfs->ns_segctor_sem); @@ -208,6 +205,7 @@ int nilfs_transaction_begin(struct super_block *sb,  	current->journal_info = ti->ti_save;  	if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)  		kmem_cache_free(nilfs_transaction_cachep, ti); +	sb_end_intwrite(sb);  	return ret;  } @@ -225,8 +223,7 @@ int nilfs_transaction_begin(struct super_block *sb,  int nilfs_transaction_commit(struct super_block *sb)  {  	struct nilfs_transaction_info *ti = current->journal_info; -	struct nilfs_sb_info *sbi; -	struct nilfs_sc_info *sci; +	struct the_nilfs *nilfs = sb->s_fs_info;  	int err = 0;  	BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); @@ -235,46 +232,47 @@ int nilfs_transaction_commit(struct super_block *sb)  		ti->ti_count--;  		return 0;  	} -	sbi = NILFS_SB(sb); -	sci = NILFS_SC(sbi); -	if (sci != NULL) { +	if (nilfs->ns_writer) { +		struct nilfs_sc_info *sci = nilfs->ns_writer; +  		if (ti->ti_flags & NILFS_TI_COMMIT)  			nilfs_segctor_start_timer(sci); -		if (atomic_read(&sbi->s_nilfs->ns_ndirtyblks) > -		    sci->sc_watermark) +		if (atomic_read(&nilfs->ns_ndirtyblks) > sci->sc_watermark)  			nilfs_segctor_do_flush(sci, 0);  	} -	up_read(&sbi->s_nilfs->ns_segctor_sem); +	up_read(&nilfs->ns_segctor_sem);  	current->journal_info = ti->ti_save;  	if (ti->ti_flags & NILFS_TI_SYNC)  		err = nilfs_construct_segment(sb);  	if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)  		kmem_cache_free(nilfs_transaction_cachep, ti); +	sb_end_intwrite(sb);  	return err;  }  void nilfs_transaction_abort(struct super_block *sb)  {  	struct nilfs_transaction_info *ti = current->journal_info; +	struct the_nilfs *nilfs = sb->s_fs_info;  	BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);  	if (ti->ti_count > 0) {  		ti->ti_count--;  		return;  	} -	up_read(&NILFS_SB(sb)->s_nilfs->ns_segctor_sem); +	up_read(&nilfs->ns_segctor_sem);  	current->journal_info = ti->ti_save;  	if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)  		kmem_cache_free(nilfs_transaction_cachep, ti); +	sb_end_intwrite(sb);  }  void nilfs_relax_pressure_in_lock(struct super_block *sb)  { -	struct nilfs_sb_info *sbi = NILFS_SB(sb); -	struct nilfs_sc_info *sci = NILFS_SC(sbi); -	struct the_nilfs *nilfs = sbi->s_nilfs; +	struct the_nilfs *nilfs = sb->s_fs_info; +	struct nilfs_sc_info *sci = nilfs->ns_writer;  	if (!sci || !sci->sc_flush_request)  		return; @@ -294,11 +292,13 @@ void nilfs_relax_pressure_in_lock(struct super_block *sb)  	downgrade_write(&nilfs->ns_segctor_sem);  } -static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, +static void nilfs_transaction_lock(struct super_block *sb,  				   struct nilfs_transaction_info *ti,  				   int gcflag)  {  	struct nilfs_transaction_info *cur_ti = current->journal_info; +	struct the_nilfs *nilfs = sb->s_fs_info; +	struct nilfs_sc_info *sci = nilfs->ns_writer;  	WARN_ON(cur_ti);  	ti->ti_flags = NILFS_TI_WRITER; @@ -309,30 +309,31 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi,  	current->journal_info = ti;  	for (;;) { -		down_write(&sbi->s_nilfs->ns_segctor_sem); -		if (!test_bit(NILFS_SC_PRIOR_FLUSH, &NILFS_SC(sbi)->sc_flags)) +		down_write(&nilfs->ns_segctor_sem); +		if (!test_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags))  			break; -		nilfs_segctor_do_immediate_flush(NILFS_SC(sbi)); +		nilfs_segctor_do_immediate_flush(sci); -		up_write(&sbi->s_nilfs->ns_segctor_sem); +		up_write(&nilfs->ns_segctor_sem);  		yield();  	}  	if (gcflag)  		ti->ti_flags |= NILFS_TI_GC;  } -static void nilfs_transaction_unlock(struct nilfs_sb_info *sbi) +static void nilfs_transaction_unlock(struct super_block *sb)  {  	struct nilfs_transaction_info *ti = current->journal_info; +	struct the_nilfs *nilfs = sb->s_fs_info;  	BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);  	BUG_ON(ti->ti_count > 0); -	up_write(&sbi->s_nilfs->ns_segctor_sem); +	up_write(&nilfs->ns_segctor_sem);  	current->journal_info = ti->ti_save;  	if (!list_empty(&ti->ti_garbage)) -		nilfs_dispose_list(sbi, &ti->ti_garbage, 0); +		nilfs_dispose_list(nilfs, &ti->ti_garbage, 0);  }  static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci, @@ -430,7 +431,8 @@ static void nilfs_segctor_begin_finfo(struct nilfs_sc_info *sci,  	nilfs_segctor_map_segsum_entry(  		sci, &sci->sc_binfo_ptr, sizeof(struct nilfs_finfo)); -	if (inode->i_sb && !test_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags)) +	if (NILFS_I(inode)->i_root && +	    !test_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags))  		set_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags);  	/* skip finfo */  } @@ -504,17 +506,6 @@ static int nilfs_segctor_add_file_block(struct nilfs_sc_info *sci,  	return err;  } -static int nilfs_handle_bmap_error(int err, const char *fname, -				   struct inode *inode, struct super_block *sb) -{ -	if (err == -EINVAL) { -		nilfs_error(sb, fname, "broken bmap (inode=%lu)\n", -			    inode->i_ino); -		err = -EIO; -	} -	return err; -} -  /*   * Callback functions that enumerate, mark, and collect dirty blocks   */ @@ -524,9 +515,8 @@ static int nilfs_collect_file_data(struct nilfs_sc_info *sci,  	int err;  	err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); -	if (unlikely(err < 0)) -		return nilfs_handle_bmap_error(err, __func__, inode, -					       sci->sc_super); +	if (err < 0) +		return err;  	err = nilfs_segctor_add_file_block(sci, bh, inode,  					   sizeof(struct nilfs_binfo_v)); @@ -539,13 +529,7 @@ static int nilfs_collect_file_node(struct nilfs_sc_info *sci,  				   struct buffer_head *bh,  				   struct inode *inode)  { -	int err; - -	err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); -	if (unlikely(err < 0)) -		return nilfs_handle_bmap_error(err, __func__, inode, -					       sci->sc_super); -	return 0; +	return nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh);  }  static int nilfs_collect_file_bmap(struct nilfs_sc_info *sci, @@ -588,9 +572,8 @@ static int nilfs_collect_dat_data(struct nilfs_sc_info *sci,  	int err;  	err = nilfs_bmap_propagate(NILFS_I(inode)->i_bmap, bh); -	if (unlikely(err < 0)) -		return nilfs_handle_bmap_error(err, __func__, inode, -					       sci->sc_super); +	if (err < 0) +		return err;  	err = nilfs_segctor_add_file_block(sci, bh, inode, sizeof(__le64));  	if (!err) @@ -675,17 +658,14 @@ static size_t nilfs_lookup_dirty_data_buffers(struct inode *inode,  		if (unlikely(page->index > last))  			break; -		if (mapping->host) { -			lock_page(page); -			if (!page_has_buffers(page)) -				create_empty_buffers(page, -						     1 << inode->i_blkbits, 0); -			unlock_page(page); -		} +		lock_page(page); +		if (!page_has_buffers(page)) +			create_empty_buffers(page, 1 << inode->i_blkbits, 0); +		unlock_page(page);  		bh = head = page_buffers(page);  		do { -			if (!buffer_dirty(bh)) +			if (!buffer_dirty(bh) || buffer_async_write(bh))  				continue;  			get_bh(bh);  			list_add_tail(&bh->b_assoc_buffers, listp); @@ -719,7 +699,8 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode,  		for (i = 0; i < pagevec_count(&pvec); i++) {  			bh = head = page_buffers(pvec.pages[i]);  			do { -				if (buffer_dirty(bh)) { +				if (buffer_dirty(bh) && +						!buffer_async_write(bh)) {  					get_bh(bh);  					list_add_tail(&bh->b_assoc_buffers,  						      listp); @@ -732,7 +713,7 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode,  	}  } -static void nilfs_dispose_list(struct nilfs_sb_info *sbi, +static void nilfs_dispose_list(struct the_nilfs *nilfs,  			       struct list_head *head, int force)  {  	struct nilfs_inode_info *ii, *n; @@ -740,7 +721,7 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,  	unsigned nv = 0;  	while (!list_empty(head)) { -		spin_lock(&sbi->s_inode_lock); +		spin_lock(&nilfs->ns_inode_lock);  		list_for_each_entry_safe(ii, n, head, i_dirty) {  			list_del_init(&ii->i_dirty);  			if (force) { @@ -751,14 +732,14 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,  			} else if (test_bit(NILFS_I_DIRTY, &ii->i_state)) {  				set_bit(NILFS_I_QUEUED, &ii->i_state);  				list_add_tail(&ii->i_dirty, -					      &sbi->s_dirty_files); +					      &nilfs->ns_dirty_files);  				continue;  			}  			ivec[nv++] = ii;  			if (nv == SC_N_INODEVEC)  				break;  		} -		spin_unlock(&sbi->s_inode_lock); +		spin_unlock(&nilfs->ns_inode_lock);  		for (pii = ivec; nv > 0; pii++, nv--)  			iput(&(*pii)->vfs_inode); @@ -776,9 +757,8 @@ static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs,  		ret++;  	if (nilfs_mdt_fetch_dirty(nilfs->ns_sufile))  		ret++; -	if (ret || nilfs_doing_gc()) -		if (nilfs_mdt_fetch_dirty(nilfs_dat_inode(nilfs))) -			ret++; +	if ((ret || nilfs_doing_gc()) && nilfs_mdt_fetch_dirty(nilfs->ns_dat)) +		ret++;  	return ret;  } @@ -792,34 +772,33 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci)  static int nilfs_segctor_confirm(struct nilfs_sc_info *sci)  { -	struct nilfs_sb_info *sbi = sci->sc_sbi; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	int ret = 0; -	if (nilfs_test_metadata_dirty(sbi->s_nilfs, sci->sc_root)) +	if (nilfs_test_metadata_dirty(nilfs, sci->sc_root))  		set_bit(NILFS_SC_DIRTY, &sci->sc_flags); -	spin_lock(&sbi->s_inode_lock); -	if (list_empty(&sbi->s_dirty_files) && nilfs_segctor_clean(sci)) +	spin_lock(&nilfs->ns_inode_lock); +	if (list_empty(&nilfs->ns_dirty_files) && nilfs_segctor_clean(sci))  		ret++; -	spin_unlock(&sbi->s_inode_lock); +	spin_unlock(&nilfs->ns_inode_lock);  	return ret;  }  static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci)  { -	struct nilfs_sb_info *sbi = sci->sc_sbi; -	struct the_nilfs *nilfs = sbi->s_nilfs; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	nilfs_mdt_clear_dirty(sci->sc_root->ifile);  	nilfs_mdt_clear_dirty(nilfs->ns_cpfile);  	nilfs_mdt_clear_dirty(nilfs->ns_sufile); -	nilfs_mdt_clear_dirty(nilfs_dat_inode(nilfs)); +	nilfs_mdt_clear_dirty(nilfs->ns_dat);  }  static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)  { -	struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	struct buffer_head *bh_cp;  	struct nilfs_checkpoint *raw_cp;  	int err; @@ -831,7 +810,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)  		/* The following code is duplicated with cpfile.  But, it is  		   needed to collect the checkpoint even if it was not newly  		   created */ -		nilfs_mdt_mark_buffer_dirty(bh_cp); +		mark_buffer_dirty(bh_cp);  		nilfs_mdt_mark_dirty(nilfs->ns_cpfile);  		nilfs_cpfile_put_checkpoint(  			nilfs->ns_cpfile, nilfs->ns_cno, bh_cp); @@ -843,8 +822,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)  static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci)  { -	struct nilfs_sb_info *sbi = sci->sc_sbi; -	struct the_nilfs *nilfs = sbi->s_nilfs; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	struct buffer_head *bh_cp;  	struct nilfs_checkpoint *raw_cp;  	int err; @@ -858,9 +836,9 @@ static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci)  	raw_cp->cp_snapshot_list.ssl_next = 0;  	raw_cp->cp_snapshot_list.ssl_prev = 0;  	raw_cp->cp_inodes_count = -		cpu_to_le64(atomic_read(&sci->sc_root->inodes_count)); +		cpu_to_le64(atomic64_read(&sci->sc_root->inodes_count));  	raw_cp->cp_blocks_count = -		cpu_to_le64(atomic_read(&sci->sc_root->blocks_count)); +		cpu_to_le64(atomic64_read(&sci->sc_root->blocks_count));  	raw_cp->cp_nblk_inc =  		cpu_to_le64(sci->sc_nblk_inc + sci->sc_nblk_this_inc);  	raw_cp->cp_create = cpu_to_le64(sci->sc_seg_ctime); @@ -912,23 +890,26 @@ static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci,  {  	struct buffer_head *bh_sr;  	struct nilfs_super_root *raw_sr; -	unsigned isz = nilfs->ns_inode_size; +	unsigned isz, srsz;  	bh_sr = NILFS_LAST_SEGBUF(&sci->sc_segbufs)->sb_super_root;  	raw_sr = (struct nilfs_super_root *)bh_sr->b_data; +	isz = nilfs->ns_inode_size; +	srsz = NILFS_SR_BYTES(isz); -	raw_sr->sr_bytes = cpu_to_le16(NILFS_SR_BYTES); +	raw_sr->sr_bytes = cpu_to_le16(srsz);  	raw_sr->sr_nongc_ctime  		= cpu_to_le64(nilfs_doing_gc() ?  			      nilfs->ns_nongc_ctime : sci->sc_seg_ctime);  	raw_sr->sr_flags = 0; -	nilfs_write_inode_common(nilfs_dat_inode(nilfs), (void *)raw_sr + +	nilfs_write_inode_common(nilfs->ns_dat, (void *)raw_sr +  				 NILFS_SR_DAT_OFFSET(isz), 1);  	nilfs_write_inode_common(nilfs->ns_cpfile, (void *)raw_sr +  				 NILFS_SR_CPFILE_OFFSET(isz), 1);  	nilfs_write_inode_common(nilfs->ns_sufile, (void *)raw_sr +  				 NILFS_SR_SUFILE_OFFSET(isz), 1); +	memset((void *)raw_sr + srsz, 0, nilfs->ns_blocksize - srsz);  }  static void nilfs_redirty_inodes(struct list_head *head) @@ -977,8 +958,8 @@ static int nilfs_segctor_apply_buffers(struct nilfs_sc_info *sci,   dispose_buffers:  	while (!list_empty(listp)) { -		bh = list_entry(listp->next, struct buffer_head, -				b_assoc_buffers); +		bh = list_first_entry(listp, struct buffer_head, +				      b_assoc_buffers);  		list_del_init(&bh->b_assoc_buffers);  		brelse(bh);  	} @@ -1068,8 +1049,7 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci,  static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)  { -	struct nilfs_sb_info *sbi = sci->sc_sbi; -	struct the_nilfs *nilfs = sbi->s_nilfs; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	struct list_head *head;  	struct nilfs_inode_info *ii;  	size_t ndone; @@ -1179,7 +1159,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)  		sci->sc_stage.scnt++;  /* Fall through */  	case NILFS_ST_DAT:   dat_stage: -		err = nilfs_segctor_scan_file(sci, nilfs_dat_inode(nilfs), +		err = nilfs_segctor_scan_file(sci, nilfs->ns_dat,  					      &nilfs_sc_dat_ops);  		if (unlikely(err))  			break; @@ -1460,17 +1440,19 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,  		nilfs_clear_logs(&sci->sc_segbufs); -		err = nilfs_segctor_extend_segments(sci, nilfs, nadd); -		if (unlikely(err)) -			return err; -  		if (sci->sc_stage.flags & NILFS_CF_SUFREED) {  			err = nilfs_sufile_cancel_freev(nilfs->ns_sufile,  							sci->sc_freesegs,  							sci->sc_nfreesegs,  							NULL);  			WARN_ON(err); /* do not happen */ +			sci->sc_stage.flags &= ~NILFS_CF_SUFREED;  		} + +		err = nilfs_segctor_extend_segments(sci, nilfs, nadd); +		if (unlikely(err)) +			return err; +  		nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA);  		sci->sc_stage = prev_stage;  	} @@ -1524,10 +1506,7 @@ nilfs_segctor_update_payload_blocknr(struct nilfs_sc_info *sci,  			nblocks = le32_to_cpu(finfo->fi_nblocks);  			ndatablk = le32_to_cpu(finfo->fi_ndatablk); -			if (buffer_nilfs_node(bh)) -				inode = NILFS_BTNC_I(bh->b_page->mapping); -			else -				inode = NILFS_AS_I(bh->b_page->mapping); +			inode = bh->b_page->mapping->host;  			if (mode == SC_LSEG_DSYNC)  				sc_op = &nilfs_sc_dsync_ops; @@ -1563,7 +1542,6 @@ nilfs_segctor_update_payload_blocknr(struct nilfs_sc_info *sci,  	return 0;   failed_bmap: -	err = nilfs_handle_bmap_error(err, __func__, inode, sci->sc_super);  	return err;  } @@ -1581,88 +1559,30 @@ static int nilfs_segctor_assign(struct nilfs_sc_info *sci, int mode)  	return 0;  } -static int -nilfs_copy_replace_page_buffers(struct page *page, struct list_head *out) -{ -	struct page *clone_page; -	struct buffer_head *bh, *head, *bh2; -	void *kaddr; - -	bh = head = page_buffers(page); - -	clone_page = nilfs_alloc_private_page(bh->b_bdev, bh->b_size, 0); -	if (unlikely(!clone_page)) -		return -ENOMEM; - -	bh2 = page_buffers(clone_page); -	kaddr = kmap_atomic(page, KM_USER0); -	do { -		if (list_empty(&bh->b_assoc_buffers)) -			continue; -		get_bh(bh2); -		page_cache_get(clone_page); /* for each bh */ -		memcpy(bh2->b_data, kaddr + bh_offset(bh), bh2->b_size); -		bh2->b_blocknr = bh->b_blocknr; -		list_replace(&bh->b_assoc_buffers, &bh2->b_assoc_buffers); -		list_add_tail(&bh->b_assoc_buffers, out); -	} while (bh = bh->b_this_page, bh2 = bh2->b_this_page, bh != head); -	kunmap_atomic(kaddr, KM_USER0); - -	if (!TestSetPageWriteback(clone_page)) -		account_page_writeback(clone_page); -	unlock_page(clone_page); - -	return 0; -} - -static int nilfs_test_page_to_be_frozen(struct page *page) -{ -	struct address_space *mapping = page->mapping; - -	if (!mapping || !mapping->host || S_ISDIR(mapping->host->i_mode)) -		return 0; - -	if (page_mapped(page)) { -		ClearPageChecked(page); -		return 1; -	} -	return PageChecked(page); -} - -static int nilfs_begin_page_io(struct page *page, struct list_head *out) +static void nilfs_begin_page_io(struct page *page)  {  	if (!page || PageWriteback(page))  		/* For split b-tree node pages, this function may be called  		   twice.  We ignore the 2nd or later calls by this check. */ -		return 0; +		return;  	lock_page(page);  	clear_page_dirty_for_io(page);  	set_page_writeback(page);  	unlock_page(page); - -	if (nilfs_test_page_to_be_frozen(page)) { -		int err = nilfs_copy_replace_page_buffers(page, out); -		if (unlikely(err)) -			return err; -	} -	return 0;  } -static int nilfs_segctor_prepare_write(struct nilfs_sc_info *sci, -				       struct page **failed_page) +static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci)  {  	struct nilfs_segment_buffer *segbuf;  	struct page *bd_page = NULL, *fs_page = NULL; -	struct list_head *list = &sci->sc_copied_buffers; -	int err; -	*failed_page = NULL;  	list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) {  		struct buffer_head *bh;  		list_for_each_entry(bh, &segbuf->sb_segsum_buffers,  				    b_assoc_buffers) { +			set_buffer_async_write(bh);  			if (bh->b_page != bd_page) {  				if (bd_page) {  					lock_page(bd_page); @@ -1676,6 +1596,7 @@ static int nilfs_segctor_prepare_write(struct nilfs_sc_info *sci,  		list_for_each_entry(bh, &segbuf->sb_payload_buffers,  				    b_assoc_buffers) { +			set_buffer_async_write(bh);  			if (bh == segbuf->sb_super_root) {  				if (bh->b_page != bd_page) {  					lock_page(bd_page); @@ -1687,11 +1608,7 @@ static int nilfs_segctor_prepare_write(struct nilfs_sc_info *sci,  				break;  			}  			if (bh->b_page != fs_page) { -				err = nilfs_begin_page_io(fs_page, list); -				if (unlikely(err)) { -					*failed_page = fs_page; -					goto out; -				} +				nilfs_begin_page_io(fs_page);  				fs_page = bh->b_page;  			}  		} @@ -1702,11 +1619,7 @@ static int nilfs_segctor_prepare_write(struct nilfs_sc_info *sci,  		set_page_writeback(bd_page);  		unlock_page(bd_page);  	} -	err = nilfs_begin_page_io(fs_page, list); -	if (unlikely(err)) -		*failed_page = fs_page; - out: -	return err; +	nilfs_begin_page_io(fs_page);  }  static int nilfs_segctor_write(struct nilfs_sc_info *sci, @@ -1719,24 +1632,6 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci,  	return ret;  } -static void __nilfs_end_page_io(struct page *page, int err) -{ -	if (!err) { -		if (!nilfs_page_buffers_clean(page)) -			__set_page_dirty_nobuffers(page); -		ClearPageError(page); -	} else { -		__set_page_dirty_nobuffers(page); -		SetPageError(page); -	} - -	if (buffer_nilfs_allocated(page_buffers(page))) { -		if (TestClearPageWriteback(page)) -			dec_zone_page_state(page, NR_WRITEBACK); -	} else -		end_page_writeback(page); -} -  static void nilfs_end_page_io(struct page *page, int err)  {  	if (!page) @@ -1763,39 +1658,19 @@ static void nilfs_end_page_io(struct page *page, int err)  		return;  	} -	__nilfs_end_page_io(page, err); -} - -static void nilfs_clear_copied_buffers(struct list_head *list, int err) -{ -	struct buffer_head *bh, *head; -	struct page *page; - -	while (!list_empty(list)) { -		bh = list_entry(list->next, struct buffer_head, -				b_assoc_buffers); -		page = bh->b_page; -		page_cache_get(page); -		head = bh = page_buffers(page); -		do { -			if (!list_empty(&bh->b_assoc_buffers)) { -				list_del_init(&bh->b_assoc_buffers); -				if (!err) { -					set_buffer_uptodate(bh); -					clear_buffer_dirty(bh); -					clear_buffer_nilfs_volatile(bh); -				} -				brelse(bh); /* for b_assoc_buffers */ -			} -		} while ((bh = bh->b_this_page) != head); - -		__nilfs_end_page_io(page, err); -		page_cache_release(page); +	if (!err) { +		if (!nilfs_page_buffers_clean(page)) +			__set_page_dirty_nobuffers(page); +		ClearPageError(page); +	} else { +		__set_page_dirty_nobuffers(page); +		SetPageError(page);  	} + +	end_page_writeback(page);  } -static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page, -			     int err) +static void nilfs_abort_logs(struct list_head *logs, int err)  {  	struct nilfs_segment_buffer *segbuf;  	struct page *bd_page = NULL, *fs_page = NULL; @@ -1807,6 +1682,7 @@ static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page,  	list_for_each_entry(segbuf, logs, sb_list) {  		list_for_each_entry(bh, &segbuf->sb_segsum_buffers,  				    b_assoc_buffers) { +			clear_buffer_async_write(bh);  			if (bh->b_page != bd_page) {  				if (bd_page)  					end_page_writeback(bd_page); @@ -1816,6 +1692,7 @@ static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page,  		list_for_each_entry(bh, &segbuf->sb_payload_buffers,  				    b_assoc_buffers) { +			clear_buffer_async_write(bh);  			if (bh == segbuf->sb_super_root) {  				if (bh->b_page != bd_page) {  					end_page_writeback(bd_page); @@ -1825,8 +1702,6 @@ static void nilfs_abort_logs(struct list_head *logs, struct page *failed_page,  			}  			if (bh->b_page != fs_page) {  				nilfs_end_page_io(fs_page, err); -				if (fs_page && fs_page == failed_page) -					return;  				fs_page = bh->b_page;  			}  		} @@ -1845,12 +1720,11 @@ static void nilfs_segctor_abort_construction(struct nilfs_sc_info *sci,  	list_splice_tail_init(&sci->sc_write_logs, &logs);  	ret = nilfs_wait_on_logs(&logs); -	nilfs_abort_logs(&logs, NULL, ret ? : err); +	nilfs_abort_logs(&logs, ret ? : err);  	list_splice_tail_init(&sci->sc_segbufs, &logs);  	nilfs_cancel_segusage(&logs, nilfs->ns_sufile);  	nilfs_free_incomplete_logs(&logs, nilfs); -	nilfs_clear_copied_buffers(&sci->sc_copied_buffers, err);  	if (sci->sc_stage.flags & NILFS_CF_SUFREED) {  		ret = nilfs_sufile_cancel_freev(nilfs->ns_sufile, @@ -1878,7 +1752,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)  {  	struct nilfs_segment_buffer *segbuf;  	struct page *bd_page = NULL, *fs_page = NULL; -	struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	int update_sr = false;  	list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { @@ -1888,6 +1762,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)  				    b_assoc_buffers) {  			set_buffer_uptodate(bh);  			clear_buffer_dirty(bh); +			clear_buffer_async_write(bh);  			if (bh->b_page != bd_page) {  				if (bd_page)  					end_page_writeback(bd_page); @@ -1909,6 +1784,8 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)  				    b_assoc_buffers) {  			set_buffer_uptodate(bh);  			clear_buffer_dirty(bh); +			clear_buffer_async_write(bh); +			clear_buffer_delay(bh);  			clear_buffer_nilfs_volatile(bh);  			clear_buffer_nilfs_redirected(bh);  			if (bh == segbuf->sb_super_root) { @@ -1943,8 +1820,6 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)  	nilfs_end_page_io(fs_page, 0); -	nilfs_clear_copied_buffers(&sci->sc_copied_buffers, 0); -  	nilfs_drop_collected_inodes(&sci->sc_dirty_files);  	if (nilfs_doing_gc()) @@ -1981,30 +1856,30 @@ static int nilfs_segctor_wait(struct nilfs_sc_info *sci)  	return ret;  } -static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, -					struct nilfs_sb_info *sbi) +static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci, +					     struct the_nilfs *nilfs)  {  	struct nilfs_inode_info *ii, *n;  	struct inode *ifile = sci->sc_root->ifile; -	spin_lock(&sbi->s_inode_lock); +	spin_lock(&nilfs->ns_inode_lock);   retry: -	list_for_each_entry_safe(ii, n, &sbi->s_dirty_files, i_dirty) { +	list_for_each_entry_safe(ii, n, &nilfs->ns_dirty_files, i_dirty) {  		if (!ii->i_bh) {  			struct buffer_head *ibh;  			int err; -			spin_unlock(&sbi->s_inode_lock); +			spin_unlock(&nilfs->ns_inode_lock);  			err = nilfs_ifile_get_inode_block(  				ifile, ii->vfs_inode.i_ino, &ibh);  			if (unlikely(err)) { -				nilfs_warning(sbi->s_super, __func__, +				nilfs_warning(sci->sc_super, __func__,  					      "failed to get inode block.\n");  				return err;  			} -			nilfs_mdt_mark_buffer_dirty(ibh); +			mark_buffer_dirty(ibh);  			nilfs_mdt_mark_dirty(ifile); -			spin_lock(&sbi->s_inode_lock); +			spin_lock(&nilfs->ns_inode_lock);  			if (likely(!ii->i_bh))  				ii->i_bh = ibh;  			else @@ -2014,21 +1889,20 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci,  		clear_bit(NILFS_I_QUEUED, &ii->i_state);  		set_bit(NILFS_I_BUSY, &ii->i_state); -		list_del(&ii->i_dirty); -		list_add_tail(&ii->i_dirty, &sci->sc_dirty_files); +		list_move_tail(&ii->i_dirty, &sci->sc_dirty_files);  	} -	spin_unlock(&sbi->s_inode_lock); +	spin_unlock(&nilfs->ns_inode_lock);  	return 0;  } -static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, -					  struct nilfs_sb_info *sbi) +static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, +					     struct the_nilfs *nilfs)  {  	struct nilfs_transaction_info *ti = current->journal_info;  	struct nilfs_inode_info *ii, *n; -	spin_lock(&sbi->s_inode_lock); +	spin_lock(&nilfs->ns_inode_lock);  	list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) {  		if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) ||  		    test_bit(NILFS_I_DIRTY, &ii->i_state)) @@ -2037,10 +1911,9 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,  		clear_bit(NILFS_I_BUSY, &ii->i_state);  		brelse(ii->i_bh);  		ii->i_bh = NULL; -		list_del(&ii->i_dirty); -		list_add_tail(&ii->i_dirty, &ti->ti_garbage); +		list_move_tail(&ii->i_dirty, &ti->ti_garbage);  	} -	spin_unlock(&sbi->s_inode_lock); +	spin_unlock(&nilfs->ns_inode_lock);  }  /* @@ -2048,15 +1921,13 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,   */  static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)  { -	struct nilfs_sb_info *sbi = sci->sc_sbi; -	struct the_nilfs *nilfs = sbi->s_nilfs; -	struct page *failed_page; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	int err;  	sci->sc_stage.scnt = NILFS_ST_INIT;  	sci->sc_cno = nilfs->ns_cno; -	err = nilfs_segctor_check_in_files(sci, sbi); +	err = nilfs_segctor_collect_dirty_files(sci, nilfs);  	if (unlikely(err))  		goto out; @@ -2105,11 +1976,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)  		nilfs_segctor_update_segusage(sci, nilfs->ns_sufile);  		/* Write partial segments */ -		err = nilfs_segctor_prepare_write(sci, &failed_page); -		if (err) { -			nilfs_abort_logs(&sci->sc_segbufs, failed_page, err); -			goto failed_to_write; -		} +		nilfs_segctor_prepare_write(sci);  		nilfs_add_checksums_on_logs(&sci->sc_segbufs,  					    nilfs->ns_crc_seed); @@ -2134,7 +2001,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)  	} while (sci->sc_stage.scnt != NILFS_ST_DONE);   out: -	nilfs_segctor_check_out_files(sci, sbi); +	nilfs_segctor_drop_written_files(sci, nilfs);  	return err;   failed_to_write: @@ -2187,8 +2054,8 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *sci, int bn)   */  void nilfs_flush_segment(struct super_block *sb, ino_t ino)  { -	struct nilfs_sb_info *sbi = NILFS_SB(sb); -	struct nilfs_sc_info *sci = NILFS_SC(sbi); +	struct the_nilfs *nilfs = sb->s_fs_info; +	struct nilfs_sc_info *sci = nilfs->ns_writer;  	if (!sci || nilfs_doing_construction())  		return; @@ -2277,8 +2144,8 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err)   */  int nilfs_construct_segment(struct super_block *sb)  { -	struct nilfs_sb_info *sbi = NILFS_SB(sb); -	struct nilfs_sc_info *sci = NILFS_SC(sbi); +	struct the_nilfs *nilfs = sb->s_fs_info; +	struct nilfs_sc_info *sci = nilfs->ns_writer;  	struct nilfs_transaction_info *ti;  	int err; @@ -2315,8 +2182,8 @@ int nilfs_construct_segment(struct super_block *sb)  int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,  				  loff_t start, loff_t end)  { -	struct nilfs_sb_info *sbi = NILFS_SB(sb); -	struct nilfs_sc_info *sci = NILFS_SC(sbi); +	struct the_nilfs *nilfs = sb->s_fs_info; +	struct nilfs_sc_info *sci = nilfs->ns_writer;  	struct nilfs_inode_info *ii;  	struct nilfs_transaction_info ti;  	int err = 0; @@ -2324,33 +2191,33 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,  	if (!sci)  		return -EROFS; -	nilfs_transaction_lock(sbi, &ti, 0); +	nilfs_transaction_lock(sb, &ti, 0);  	ii = NILFS_I(inode);  	if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) || -	    nilfs_test_opt(sbi, STRICT_ORDER) || +	    nilfs_test_opt(nilfs, STRICT_ORDER) ||  	    test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) || -	    nilfs_discontinued(sbi->s_nilfs)) { -		nilfs_transaction_unlock(sbi); +	    nilfs_discontinued(nilfs)) { +		nilfs_transaction_unlock(sb);  		err = nilfs_segctor_sync(sci);  		return err;  	} -	spin_lock(&sbi->s_inode_lock); +	spin_lock(&nilfs->ns_inode_lock);  	if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&  	    !test_bit(NILFS_I_BUSY, &ii->i_state)) { -		spin_unlock(&sbi->s_inode_lock); -		nilfs_transaction_unlock(sbi); +		spin_unlock(&nilfs->ns_inode_lock); +		nilfs_transaction_unlock(sb);  		return 0;  	} -	spin_unlock(&sbi->s_inode_lock); +	spin_unlock(&nilfs->ns_inode_lock);  	sci->sc_dsync_inode = ii;  	sci->sc_dsync_start = start;  	sci->sc_dsync_end = end;  	err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC); -	nilfs_transaction_unlock(sbi); +	nilfs_transaction_unlock(sb);  	return err;  } @@ -2406,8 +2273,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err)   */  static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)  { -	struct nilfs_sb_info *sbi = sci->sc_sbi; -	struct the_nilfs *nilfs = sbi->s_nilfs; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	struct nilfs_super_block **sbp;  	int err = 0; @@ -2425,11 +2291,12 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)  		    nilfs_discontinued(nilfs)) {  			down_write(&nilfs->ns_sem);  			err = -EIO; -			sbp = nilfs_prepare_super(sbi, +			sbp = nilfs_prepare_super(sci->sc_super,  						  nilfs_sb_will_flip(nilfs));  			if (likely(sbp)) {  				nilfs_set_log_cursor(sbp[0], nilfs); -				err = nilfs_commit_super(sbi, NILFS_SB_COMMIT); +				err = nilfs_commit_super(sci->sc_super, +							 NILFS_SB_COMMIT);  			}  			up_write(&nilfs->ns_sem);  		} @@ -2454,6 +2321,8 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head)  		if (!test_bit(NILFS_I_UPDATED, &ii->i_state))  			continue;  		list_del_init(&ii->i_dirty); +		truncate_inode_pages(&ii->vfs_inode.i_data, 0); +		nilfs_btnode_cache_clear(&ii->i_btnode_cache);  		iput(&ii->vfs_inode);  	}  } @@ -2461,16 +2330,15 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head)  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); -	struct the_nilfs *nilfs = sbi->s_nilfs; +	struct the_nilfs *nilfs = sb->s_fs_info; +	struct nilfs_sc_info *sci = nilfs->ns_writer;  	struct nilfs_transaction_info ti;  	int err;  	if (unlikely(!sci))  		return -EROFS; -	nilfs_transaction_lock(sbi, &ti, 1); +	nilfs_transaction_lock(sb, &ti, 1);  	err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);  	if (unlikely(err)) @@ -2498,14 +2366,14 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,  		set_current_state(TASK_INTERRUPTIBLE);  		schedule_timeout(sci->sc_interval);  	} -	if (nilfs_test_opt(sbi, DISCARD)) { +	if (nilfs_test_opt(nilfs, DISCARD)) {  		int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs,  						 sci->sc_nfreesegs);  		if (ret) {  			printk(KERN_WARNING  			       "NILFS warning: error %d on discard request, "  			       "turning discards off for the device\n", ret); -			nilfs_clear_opt(sbi, DISCARD); +			nilfs_clear_opt(nilfs, DISCARD);  		}  	} @@ -2513,16 +2381,15 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,  	sci->sc_freesegs = NULL;  	sci->sc_nfreesegs = 0;  	nilfs_mdt_clear_shadow_map(nilfs->ns_dat); -	nilfs_transaction_unlock(sbi); +	nilfs_transaction_unlock(sb);  	return err;  }  static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode)  { -	struct nilfs_sb_info *sbi = sci->sc_sbi;  	struct nilfs_transaction_info ti; -	nilfs_transaction_lock(sbi, &ti, 0); +	nilfs_transaction_lock(sci->sc_super, &ti, 0);  	nilfs_segctor_construct(sci, mode);  	/* @@ -2533,7 +2400,7 @@ static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode)  	if (test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags))  		nilfs_segctor_start_timer(sci); -	nilfs_transaction_unlock(sbi); +	nilfs_transaction_unlock(sci->sc_super);  }  static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *sci) @@ -2579,7 +2446,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci)  static int nilfs_segctor_thread(void *arg)  {  	struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg; -	struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	int timeout = 0;  	sci->sc_timer.data = (unsigned long)current; @@ -2617,7 +2484,7 @@ static int nilfs_segctor_thread(void *arg)  	if (freezing(current)) {  		spin_unlock(&sci->sc_state_lock); -		refrigerator(); +		try_to_freeze();  		spin_lock(&sci->sc_state_lock);  	} else {  		DEFINE_WAIT(wait); @@ -2690,17 +2557,17 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci)  /*   * Setup & clean-up functions   */ -static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, +static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb,  					       struct nilfs_root *root)  { +	struct the_nilfs *nilfs = sb->s_fs_info;  	struct nilfs_sc_info *sci;  	sci = kzalloc(sizeof(*sci), GFP_KERNEL);  	if (!sci)  		return NULL; -	sci->sc_sbi = sbi; -	sci->sc_super = sbi->s_super; +	sci->sc_super = sb;  	nilfs_get_root(root);  	sci->sc_root = root; @@ -2713,17 +2580,16 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi,  	INIT_LIST_HEAD(&sci->sc_segbufs);  	INIT_LIST_HEAD(&sci->sc_write_logs);  	INIT_LIST_HEAD(&sci->sc_gc_inodes); -	INIT_LIST_HEAD(&sci->sc_copied_buffers);  	init_timer(&sci->sc_timer);  	sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;  	sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ;  	sci->sc_watermark = NILFS_SC_DEFAULT_WATERMARK; -	if (sbi->s_interval) -		sci->sc_interval = sbi->s_interval; -	if (sbi->s_watermark) -		sci->sc_watermark = sbi->s_watermark; +	if (nilfs->ns_interval) +		sci->sc_interval = HZ * nilfs->ns_interval; +	if (nilfs->ns_watermark) +		sci->sc_watermark = nilfs->ns_watermark;  	return sci;  } @@ -2734,12 +2600,11 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)  	/* The segctord thread was stopped and its timer was removed.  	   But some tasks remain. */  	do { -		struct nilfs_sb_info *sbi = sci->sc_sbi;  		struct nilfs_transaction_info ti; -		nilfs_transaction_lock(sbi, &ti, 0); +		nilfs_transaction_lock(sci->sc_super, &ti, 0);  		ret = nilfs_segctor_construct(sci, SC_LSEG_SR); -		nilfs_transaction_unlock(sbi); +		nilfs_transaction_unlock(sci->sc_super);  	} while (ret && retrycount-- > 0);  } @@ -2754,10 +2619,10 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)   */  static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)  { -	struct nilfs_sb_info *sbi = sci->sc_sbi; +	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;  	int flag; -	up_write(&sbi->s_nilfs->ns_segctor_sem); +	up_write(&nilfs->ns_segctor_sem);  	spin_lock(&sci->sc_state_lock);  	nilfs_segctor_kill_thread(sci); @@ -2768,12 +2633,10 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)  	if (flag || !nilfs_segctor_confirm(sci))  		nilfs_segctor_write_out(sci); -	WARN_ON(!list_empty(&sci->sc_copied_buffers)); -  	if (!list_empty(&sci->sc_dirty_files)) { -		nilfs_warning(sbi->s_super, __func__, +		nilfs_warning(sci->sc_super, __func__,  			      "dirty file(s) after the final construction\n"); -		nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1); +		nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1);  	}  	WARN_ON(!list_empty(&sci->sc_segbufs)); @@ -2781,79 +2644,78 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)  	nilfs_put_root(sci->sc_root); -	down_write(&sbi->s_nilfs->ns_segctor_sem); +	down_write(&nilfs->ns_segctor_sem);  	del_timer_sync(&sci->sc_timer);  	kfree(sci);  }  /** - * nilfs_attach_segment_constructor - attach a segment constructor - * @sbi: nilfs_sb_info + * nilfs_attach_log_writer - attach log writer + * @sb: super block instance   * @root: root object of the current filesystem tree   * - * nilfs_attach_segment_constructor() allocates a struct nilfs_sc_info, - * initializes it, and starts the segment constructor. + * This allocates a log writer object, initializes it, and starts the + * log writer.   *   * Return Value: On success, 0 is returned. On error, one of the following   * negative error code is returned.   *   * %-ENOMEM - Insufficient memory available.   */ -int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, -				     struct nilfs_root *root) +int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root)  { +	struct the_nilfs *nilfs = sb->s_fs_info;  	int err; -	if (NILFS_SC(sbi)) { +	if (nilfs->ns_writer) {  		/*  		 * This happens if the filesystem was remounted  		 * read/write after nilfs_error degenerated it into a  		 * read-only mount.  		 */ -		nilfs_detach_segment_constructor(sbi); +		nilfs_detach_log_writer(sb);  	} -	sbi->s_sc_info = nilfs_segctor_new(sbi, root); -	if (!sbi->s_sc_info) +	nilfs->ns_writer = nilfs_segctor_new(sb, root); +	if (!nilfs->ns_writer)  		return -ENOMEM; -	err = nilfs_segctor_start_thread(NILFS_SC(sbi)); +	err = nilfs_segctor_start_thread(nilfs->ns_writer);  	if (err) { -		kfree(sbi->s_sc_info); -		sbi->s_sc_info = NULL; +		kfree(nilfs->ns_writer); +		nilfs->ns_writer = NULL;  	}  	return err;  }  /** - * nilfs_detach_segment_constructor - destroy the segment constructor - * @sbi: nilfs_sb_info + * nilfs_detach_log_writer - destroy log writer + * @sb: super block instance   * - * nilfs_detach_segment_constructor() kills the segment constructor daemon, - * frees the struct nilfs_sc_info, and destroy the dirty file list. + * This kills log writer daemon, frees the log writer object, and + * destroys list of dirty files.   */ -void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) +void nilfs_detach_log_writer(struct super_block *sb)  { -	struct the_nilfs *nilfs = sbi->s_nilfs; +	struct the_nilfs *nilfs = sb->s_fs_info;  	LIST_HEAD(garbage_list);  	down_write(&nilfs->ns_segctor_sem); -	if (NILFS_SC(sbi)) { -		nilfs_segctor_destroy(NILFS_SC(sbi)); -		sbi->s_sc_info = NULL; +	if (nilfs->ns_writer) { +		nilfs_segctor_destroy(nilfs->ns_writer); +		nilfs->ns_writer = NULL;  	}  	/* Force to free the list of dirty files */ -	spin_lock(&sbi->s_inode_lock); -	if (!list_empty(&sbi->s_dirty_files)) { -		list_splice_init(&sbi->s_dirty_files, &garbage_list); -		nilfs_warning(sbi->s_super, __func__, -			      "Non empty dirty list after the last " -			      "segment construction\n"); -	} -	spin_unlock(&sbi->s_inode_lock); +	spin_lock(&nilfs->ns_inode_lock); +	if (!list_empty(&nilfs->ns_dirty_files)) { +		list_splice_init(&nilfs->ns_dirty_files, &garbage_list); +		nilfs_warning(sb, __func__, +			      "Hit dirty file after stopped log writer\n"); +	} +	spin_unlock(&nilfs->ns_inode_lock);  	up_write(&nilfs->ns_segctor_sem); -	nilfs_dispose_list(sbi, &garbage_list, 1); +	nilfs_dispose_list(nilfs, &garbage_list, 1);  }  | 
