Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c2e52fc authored by Ryusuke Konishi's avatar Ryusuke Konishi Committed by Linus Torvalds
Browse files

nilfs2: extend nilfs_sustat ioctl struct



This adds a new argument to the nilfs_sustat structure.

The extended field allows to delete volatile active state of segments,
which was needed to protect freshly-created segments from garbage
collection but has confused code dealing with segments.  This
extension alleviates the mess and gives room for further
simplifications.

The volatile active flag is not persistent, so it's eliminable on this
occasion without affecting compatibility other than the ioctl change.

Signed-off-by: default avatarRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7a946193
Loading
Loading
Loading
Loading
+17 −15
Original line number Diff line number Diff line
@@ -416,6 +416,7 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
	struct nilfs_segment_entry *ent, *n;
	struct inode *sufile = nilfs->ns_sufile;
	__u64 segnum[4];
	time_t mtime;
	int err;
	int i;

@@ -442,9 +443,9 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,

	/*
	 * Collecting segments written after the latest super root.
	 * These are marked volatile active, and won't be reallocated in
	 * the next construction.
	 * These are marked dirty to avoid being reallocated in the next write.
	 */
	mtime = get_seconds();
	list_for_each_entry_safe(ent, n, head, list) {
		if (ent->segnum == segnum[0]) {
			list_del(&ent->list);
@@ -454,17 +455,16 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
		err = nilfs_open_segment_entry(ent, sufile);
		if (unlikely(err))
			goto failed;
		if (nilfs_segment_usage_clean(ent->raw_su)) {
			nilfs_segment_usage_set_volatile_active(ent->raw_su);
			/* Keep it open */
		} else {
			/* Removing duplicated entries */
		if (!nilfs_segment_usage_dirty(ent->raw_su)) {
			/* make the segment garbage */
			ent->raw_su->su_nblocks = cpu_to_le32(0);
			ent->raw_su->su_lastmod = cpu_to_le32(mtime);
			nilfs_segment_usage_set_dirty(ent->raw_su);
		}
		list_del(&ent->list);
		nilfs_close_segment_entry(ent, sufile);
		nilfs_free_segment_entry(ent);
	}
	}
	list_splice_init(head, nilfs->ns_used_segments.prev);

	/*
	 * The segment having the latest super root is active, and
@@ -882,10 +882,12 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi,

		if (scan_newer)
			ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED;
		else if (nilfs->ns_mount_state & NILFS_VALID_FS)
		else {
			nilfs->ns_prot_seq = ssi.seg_seq;
			if (nilfs->ns_mount_state & NILFS_VALID_FS)
				goto super_root_found;

			scan_newer = 1;
		}

		/* reset region for roll-forward */
		pseg_start += ssi.nblocks;
+9 −30
Original line number Diff line number Diff line
@@ -2229,13 +2229,6 @@ static void nilfs_segctor_reactivate_segments(struct nilfs_sc_info *sci,
		nilfs_segment_usage_set_active(ent->raw_su);
		nilfs_close_segment_entry(ent, sufile);
	}

	down_write(&nilfs->ns_sem);
	head = &nilfs->ns_used_segments;
	list_for_each_entry(ent, head, list) {
		nilfs_segment_usage_set_volatile_active(ent->raw_su);
	}
	up_write(&nilfs->ns_sem);
}

static int nilfs_segctor_deactivate_segments(struct nilfs_sc_info *sci,
@@ -2244,7 +2237,6 @@ static int nilfs_segctor_deactivate_segments(struct nilfs_sc_info *sci,
	struct nilfs_segment_buffer *segbuf, *last;
	struct nilfs_segment_entry *ent;
	struct inode *sufile = nilfs->ns_sufile;
	struct list_head *head;
	int err;

	last = NILFS_LAST_SEGBUF(&sci->sc_segbufs);
@@ -2265,22 +2257,13 @@ static int nilfs_segctor_deactivate_segments(struct nilfs_sc_info *sci,
		BUG_ON(!buffer_dirty(ent->bh_su));
	}

	head = &sci->sc_active_segments;
	list_for_each_entry(ent, head, list) {
	list_for_each_entry(ent, &sci->sc_active_segments, list) {
		err = nilfs_open_segment_entry(ent, sufile);
		if (unlikely(err))
			goto failed;
		nilfs_segment_usage_clear_active(ent->raw_su);
		BUG_ON(!buffer_dirty(ent->bh_su));
	}

	down_write(&nilfs->ns_sem);
	head = &nilfs->ns_used_segments;
	list_for_each_entry(ent, head, list) {
		/* clear volatile active for segments of older generations */
		nilfs_segment_usage_clear_volatile_active(ent->raw_su);
	}
	up_write(&nilfs->ns_sem);
	return 0;

 failed:
@@ -2304,19 +2287,15 @@ static void nilfs_segctor_bead_completed_segments(struct nilfs_sc_info *sci)
	}
}

static void
__nilfs_segctor_commit_deactivate_segments(struct nilfs_sc_info *sci,
static void nilfs_segctor_commit_deactivate_segments(struct nilfs_sc_info *sci,
						     struct the_nilfs *nilfs)

{
	struct nilfs_segment_entry *ent;

	list_splice_init(&sci->sc_active_segments,
			 nilfs->ns_used_segments.prev);
	struct nilfs_segment_entry *ent, *n;

	list_for_each_entry(ent, &nilfs->ns_used_segments, list) {
		nilfs_segment_usage_set_volatile_active(ent->raw_su);
		/* These segments are kept open */
	list_for_each_entry_safe(ent, n, &sci->sc_active_segments, list) {
		list_del(&ent->list);
		nilfs_close_segment_entry(ent, nilfs->ns_sufile);
		nilfs_free_segment_entry(ent);
	}
}

@@ -2405,8 +2384,8 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
		if (has_sr) {
			down_write(&nilfs->ns_sem);
			nilfs_update_last_segment(sbi, 1);
			__nilfs_segctor_commit_deactivate_segments(sci, nilfs);
			up_write(&nilfs->ns_sem);
			nilfs_segctor_commit_deactivate_segments(sci, nilfs);
			nilfs_segctor_commit_free_segments(sci);
			nilfs_segctor_clear_metadata_dirty(sci);
		}
+6 −2
Original line number Diff line number Diff line
@@ -446,6 +446,7 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat)
{
	struct buffer_head *header_bh;
	struct nilfs_sufile_header *header;
	struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs;
	void *kaddr;
	int ret;

@@ -460,8 +461,11 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat)
	sustat->ss_nsegs = nilfs_sufile_get_nsegments(sufile);
	sustat->ss_ncleansegs = le64_to_cpu(header->sh_ncleansegs);
	sustat->ss_ndirtysegs = le64_to_cpu(header->sh_ndirtysegs);
	sustat->ss_ctime = NILFS_MDT(sufile)->mi_nilfs->ns_ctime;
	sustat->ss_nongc_ctime = NILFS_MDT(sufile)->mi_nilfs->ns_nongc_ctime;
	sustat->ss_ctime = nilfs->ns_ctime;
	sustat->ss_nongc_ctime = nilfs->ns_nongc_ctime;
	spin_lock(&nilfs->ns_last_segment_lock);
	sustat->ss_prot_seq = nilfs->ns_prot_seq;
	spin_unlock(&nilfs->ns_last_segment_lock);
	kunmap_atomic(kaddr, KM_USER0);
	brelse(header_bh);

+3 −1
Original line number Diff line number Diff line
@@ -262,8 +262,10 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi)
		printk(KERN_ERR
		       "NILFS: unable to write superblock (err=%d)\n", err);
	else {
		nilfs_dispose_used_segments(nilfs);
		clear_nilfs_discontinued(nilfs);
		spin_lock(&nilfs->ns_last_segment_lock);
		nilfs->ns_prot_seq = le64_to_cpu(nilfs->ns_sbp->s_last_seq);
		spin_unlock(&nilfs->ns_last_segment_lock);
	}

	return err;
+0 −18
Original line number Diff line number Diff line
@@ -71,7 +71,6 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
	INIT_LIST_HEAD(&nilfs->ns_supers);
	spin_lock_init(&nilfs->ns_last_segment_lock);
	nilfs->ns_gc_inodes_h = NULL;
	INIT_LIST_HEAD(&nilfs->ns_used_segments);
	init_rwsem(&nilfs->ns_segctor_sem);

	return nilfs;
@@ -95,7 +94,6 @@ void put_nilfs(struct the_nilfs *nilfs)
	 */
	might_sleep();
	if (nilfs_loaded(nilfs)) {
		nilfs_dispose_used_segments(nilfs);
		nilfs_mdt_clear(nilfs->ns_sufile);
		nilfs_mdt_destroy(nilfs->ns_sufile);
		nilfs_mdt_clear(nilfs->ns_cpfile);
@@ -463,22 +461,6 @@ int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks)
	return err;
}

void nilfs_dispose_used_segments(struct the_nilfs *nilfs)
{
	struct nilfs_segment_entry *ent, *n;

	/* nilfs->sem must be locked by the caller. */
	if (!nilfs_loaded(nilfs))
		return;

	list_for_each_entry_safe(ent, n, &nilfs->ns_used_segments, list) {
		list_del_init(&ent->list);
		nilfs_segment_usage_clear_volatile_active(ent->raw_su);
		nilfs_close_segment_entry(ent, nilfs->ns_sufile);
		nilfs_free_segment_entry(ent);
	}
}

int nilfs_near_disk_full(struct the_nilfs *nilfs)
{
	struct inode *sufile = nilfs->ns_sufile;
Loading