Re: [PATCH] nilfs2: sync super blokcs in turns

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
On Thu, 27 May 2010 16:27:22 +0900, Jiro SEKIBA wrote:
> Hi,
> 
> This is a proposed patch to sync super blocks by turn.
> It still require recovery action when super root is not found,

Arh, right.  We need some extension to retry the search with the older
super block.  It looks a bit complicate.

Ok, I'll take a moment to solve this issue.

> but it works at least to mount with valid fs with the patch:
> 
>  nilfs2: use checkpoint number instead of timestamp to select super block
>  9f6c75b4c354939f0a8aefc19eb6a9334ef58a89
> 
> This will sync super blocks by turn instead of syncing duplicate
> super blocks at the time.  This will help searching valid super root when
> super block is written into disk before log is written, which is happen when
> barrier-less block devices are unmounted uncleanly.
> In the stiation, old super block likely points valid log.
> 
> Signed-off-by: Jiro SEKIBA <jir@xxxxxxxxx>
> ---
>  fs/nilfs2/nilfs.h     |    2 +-
>  fs/nilfs2/segment.c   |    3 +--
>  fs/nilfs2/super.c     |   32 ++++++++++++++++----------------
>  fs/nilfs2/the_nilfs.c |    2 +-
>  4 files changed, 19 insertions(+), 20 deletions(-)
> 
> diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
> index 8723e5b..ec644c5 100644
> --- a/fs/nilfs2/nilfs.h
> +++ b/fs/nilfs2/nilfs.h
> @@ -270,7 +270,7 @@ extern struct nilfs_super_block *
>  nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **);
>  extern int nilfs_store_magic_and_option(struct super_block *,
>  					struct nilfs_super_block *, char *);
> -extern int nilfs_commit_super(struct nilfs_sb_info *, int);
> +extern int nilfs_commit_super(struct nilfs_sb_info *);
>  extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64);
>  extern void nilfs_detach_checkpoint(struct nilfs_sb_info *);
>  
> diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
> index 6a7dbd8..b48de1f 100644
> --- a/fs/nilfs2/segment.c
> +++ b/fs/nilfs2/segment.c
> @@ -2490,8 +2490,7 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
>  		if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) &&
>  		    nilfs_discontinued(nilfs)) {
>  			down_write(&nilfs->ns_sem);
> -			err = nilfs_commit_super(
> -				sbi, nilfs_altsb_need_update(nilfs));
> +			err = nilfs_commit_super(sbi);
>  			up_write(&nilfs->ns_sem);
>  		}
>  	}
> diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
> index 48145f5..4894e07 100644
> --- a/fs/nilfs2/super.c
> +++ b/fs/nilfs2/super.c
> @@ -101,7 +101,7 @@ void nilfs_error(struct super_block *sb, const char *function,
>  			nilfs->ns_mount_state |= NILFS_ERROR_FS;
>  			nilfs->ns_sbp[0]->s_state |=
>  				cpu_to_le16(NILFS_ERROR_FS);
> -			nilfs_commit_super(sbi, 1);
> +			nilfs_commit_super(sbi);
>  		}
>  		up_write(&nilfs->ns_sem);
>  
> @@ -200,7 +200,7 @@ static void nilfs_clear_inode(struct inode *inode)
>  	nilfs_btnode_cache_clear(&ii->i_btnode_cache);
>  }
>  
> -static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
> +static int nilfs_sync_super(struct nilfs_sb_info *sbi)
>  {
>  	struct the_nilfs *nilfs = sbi->s_nilfs;
>  	int err;
> @@ -226,6 +226,9 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
>  		printk(KERN_ERR
>  		       "NILFS: unable to write superblock (err=%d)\n", err);
>  		if (err == -EIO && nilfs->ns_sbh[1]) {
> +			memcpy(nilfs->ns_sbp[1], nilfs->ns_sbp[0],
> +			       nilfs->ns_sbsize);
> +			nilfs->ns_sbwtime[1] = nilfs->ns_sbwtime[0];
>  			nilfs_fall_back_super_block(nilfs);
>  			goto retry;
>  		}
> @@ -240,11 +243,12 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
>  
>  		/* update GC protection for recent segments */
>  		if (nilfs->ns_sbh[1]) {
> +			int flip_bits = (nilfs->ns_cno & 0x0FL);
>  			sbp = NULL;
> -			if (dupsb) {
> -				set_buffer_dirty(nilfs->ns_sbh[1]);
> -				if (!sync_dirty_buffer(nilfs->ns_sbh[1]))
> -					sbp = nilfs->ns_sbp[1];
> +			/* flip super block 9 to 7 ratio */
> +			if ((flip_bits == 0x08) || flip_bits == 0x0F) {
> +				sbp = nilfs->ns_sbp[1];
> +				nilfs_swap_super_block(nilfs);
>  			}
>  		}
>  		if (sbp) {
> @@ -257,7 +261,7 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
>  	return err;
>  }
>  
> -int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
> +int nilfs_commit_super(struct nilfs_sb_info *sbi)
>  {
>  	struct the_nilfs *nilfs = sbi->s_nilfs;
>  	struct nilfs_super_block **sbp = nilfs->ns_sbp;
> @@ -294,12 +298,8 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
>  	sbp[0]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed,
>  					     (unsigned char *)sbp[0],
>  					     nilfs->ns_sbsize));
> -	if (dupsb && sbp[1]) {
> -		memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
> -		nilfs->ns_sbwtime[1] = t;
> -	}
>  	clear_nilfs_sb_dirty(nilfs);
> -	return nilfs_sync_super(sbi, dupsb);
> +	return nilfs_sync_super(sbi);
>  }
>  
>  static void nilfs_put_super(struct super_block *sb)
> @@ -314,7 +314,7 @@ static void nilfs_put_super(struct super_block *sb)
>  	if (!(sb->s_flags & MS_RDONLY)) {
>  		down_write(&nilfs->ns_sem);
>  		nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
> -		nilfs_commit_super(sbi, 1);
> +		nilfs_commit_super(sbi);
>  		up_write(&nilfs->ns_sem);
>  	}
>  	down_write(&nilfs->ns_super_sem);
> @@ -343,7 +343,7 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
>  
>  	down_write(&nilfs->ns_sem);
>  	if (nilfs_sb_dirty(nilfs))
> -		nilfs_commit_super(sbi, 1);
> +		nilfs_commit_super(sbi);
>  	up_write(&nilfs->ns_sem);
>  
>  	return err;
> @@ -657,7 +657,7 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi)
>  	sbp->s_mnt_count = cpu_to_le16(mnt_count + 1);
>  	sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS);
>  	sbp->s_mtime = cpu_to_le64(get_seconds());
> -	return nilfs_commit_super(sbi, 1);
> +	return nilfs_commit_super(sbi);
>  }
>  
>  struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb,
> @@ -901,7 +901,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
>  		    (nilfs->ns_mount_state & NILFS_VALID_FS))
>  			sbp->s_state = cpu_to_le16(nilfs->ns_mount_state);
>  		sbp->s_mtime = cpu_to_le64(get_seconds());
> -		nilfs_commit_super(sbi, 1);
> +		nilfs_commit_super(sbi);
>  		up_write(&nilfs->ns_sem);
>  	} else {
>  		/*
> diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
> index a756168..f779363 100644
> --- a/fs/nilfs2/the_nilfs.c
> +++ b/fs/nilfs2/the_nilfs.c
> @@ -327,7 +327,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
>  	down_write(&nilfs->ns_sem);
>  	nilfs->ns_mount_state |= NILFS_VALID_FS;
>  	nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
> -	err = nilfs_commit_super(sbi, 1);
> +	err = nilfs_commit_super(sbi);
>  	up_write(&nilfs->ns_sem);
>  
>  	if (err) {
> -- 
> 1.5.6.5


Well, the basic idea looks OK.

But, this patch has an issue.

When the filesystem is mounted, nilfs updates super blocks to drop
their VALID_FS flags, and this state continues until the partition
will be unmounted.

The point is that the checkpoint number does not change when the
VALID_FS flags are set or unset.

If the system goes down while the VALID_FS flag on the secondary super
block is still on, it may prevent roll-forward recovery because the
VALID_FS flag forces to skip the recovery.

So, we still have to drop the VALID_FS flag together from both super
blocks.

Or, we may as well stop using the VALID_FS flag.  Nilfs can know
whether the recovery is needed or not by scanning logs without the
VALID_FS flag.

> +			/* flip super block 9 to 7 ratio */
> +			if ((flip_bits == 0x08) || flip_bits == 0x0F) {
> +				sbp = nilfs->ns_sbp[1];
> +				nilfs_swap_super_block(nilfs);
>  			}

This twist looks well thought out.  But, one comment.  From the coding
style viewpoint, it should be as follows:

> +			if (flip_bits == 0x08 || flip_bits == 0x0F) {

Thanks,
Ryusuke Konishi
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux BTRFS]     [Linux CIFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux