Esempio n. 1
0
static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag)
{
	struct the_nilfs *nilfs = sbi->s_nilfs;
	int err;

 retry:
	set_buffer_dirty(nilfs->ns_sbh[0]);
	if (nilfs_test_opt(sbi, BARRIER)) {
		err = __sync_dirty_buffer(nilfs->ns_sbh[0],
					  WRITE_SYNC | WRITE_FLUSH_FUA);
	} else {
		err = sync_dirty_buffer(nilfs->ns_sbh[0]);
	}

	if (unlikely(err)) {
		printk(KERN_ERR
		       "NILFS: unable to write superblock (err=%d)\n", err);
		if (err == -EIO && nilfs->ns_sbh[1]) {
			/*
			 * sbp[0] points to newer log than sbp[1],
			 * so copy sbp[0] to sbp[1] to take over sbp[0].
			 */
			memcpy(nilfs->ns_sbp[1], nilfs->ns_sbp[0],
			       nilfs->ns_sbsize);
			nilfs_fall_back_super_block(nilfs);
			goto retry;
		}
	} else {
		struct nilfs_super_block *sbp = nilfs->ns_sbp[0];

		nilfs->ns_sbwcount++;

		/*
		 * The latest segment becomes trailable from the position
		 * written in superblock.
		 */
		clear_nilfs_discontinued(nilfs);

		/* update GC protection for recent segments */
		if (nilfs->ns_sbh[1]) {
			if (flag == NILFS_SB_COMMIT_ALL) {
				set_buffer_dirty(nilfs->ns_sbh[1]);
				if (sync_dirty_buffer(nilfs->ns_sbh[1]) < 0)
					goto out;
			}
			if (le64_to_cpu(nilfs->ns_sbp[1]->s_last_cno) <
			    le64_to_cpu(nilfs->ns_sbp[0]->s_last_cno))
				sbp = nilfs->ns_sbp[1];
		}

		spin_lock(&nilfs->ns_last_segment_lock);
		nilfs->ns_prot_seq = le64_to_cpu(sbp->s_last_seq);
		spin_unlock(&nilfs->ns_last_segment_lock);
	}
 out:
	return err;
}
Esempio n. 2
0
static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
{
	struct the_nilfs *nilfs = sbi->s_nilfs;
	int err;
	int barrier_done = 0;

	if (nilfs_test_opt(sbi, BARRIER)) {
		set_buffer_ordered(nilfs->ns_sbh[0]);
		barrier_done = 1;
	}
 retry:
	set_buffer_dirty(nilfs->ns_sbh[0]);
	err = sync_dirty_buffer(nilfs->ns_sbh[0]);
	if (err == -EOPNOTSUPP && barrier_done) {
		nilfs_warning(sbi->s_super, __func__,
			      "barrier-based sync failed. "
			      "disabling barriers\n");
		nilfs_clear_opt(sbi, BARRIER);
		barrier_done = 0;
		clear_buffer_ordered(nilfs->ns_sbh[0]);
		goto retry;
	}
	if (unlikely(err)) {
		printk(KERN_ERR
		       "NILFS: unable to write superblock (err=%d)\n", err);
		if (err == -EIO && nilfs->ns_sbh[1]) {
			nilfs_fall_back_super_block(nilfs);
			goto retry;
		}
	} else {
		struct nilfs_super_block *sbp = nilfs->ns_sbp[0];

		/*
		 * The latest segment becomes trailable from the position
		 * written in superblock.
		 */
		clear_nilfs_discontinued(nilfs);

		/* update GC protection for recent segments */
		if (nilfs->ns_sbh[1]) {
			sbp = NULL;
			if (dupsb) {
				set_buffer_dirty(nilfs->ns_sbh[1]);
				if (!sync_dirty_buffer(nilfs->ns_sbh[1]))
					sbp = nilfs->ns_sbp[1];
			}
		}
		if (sbp) {
			spin_lock(&nilfs->ns_last_segment_lock);
			nilfs->ns_prot_seq = le64_to_cpu(sbp->s_last_seq);
			spin_unlock(&nilfs->ns_last_segment_lock);
		}
	}

	return err;
}
Esempio n. 3
0
static int nilfs_sync_super(struct super_block *sb, int flag)
{
	struct the_nilfs *nilfs = sb->s_fs_info;
	int err;
#if HAVE_BH_ORDERED
	int barrier_done = 0;

	if (nilfs_sb_barrier(nilfs)) {
		set_buffer_ordered(nilfs->ns_sbh[0]);
		barrier_done = 1;
	}
 retry:
	set_buffer_dirty(nilfs->ns_sbh[0]);
	err = sync_dirty_buffer(nilfs->ns_sbh[0]);
	if (err == -EOPNOTSUPP && barrier_done) {
		nilfs_warning(sb, __func__, "barrier-based sync failed. "
			      "disabling barriers for superblock\n");
		clear_nilfs_sb_barrier(nilfs);
		barrier_done = 0;
		clear_buffer_ordered(nilfs->ns_sbh[0]);
		goto retry;
	}
#else
 retry:
	set_buffer_dirty(nilfs->ns_sbh[0]);
	if (nilfs_sb_barrier(nilfs)) {
 #if HAVE_BIO_BARRIER
		err = __sync_dirty_buffer(nilfs->ns_sbh[0],
					  WRITE_SYNC | WRITE_BARRIER);
		if (err == -EOPNOTSUPP) {
			nilfs_warning(sb, __func__,
				      "barrier-based sync failed. "
				      "disabling barriers for superblock\n");
			clear_nilfs_sb_barrier(nilfs);
			goto retry;
		}
 #else
		err = __sync_dirty_buffer(nilfs->ns_sbh[0],
					  WRITE_SYNC | WRITE_FLUSH_FUA);
 #endif /* HAVE_BIO_BARRIER */
	} else {
		err = sync_dirty_buffer(nilfs->ns_sbh[0]);
	}
#endif /* HAVE_BH_ORDERED */

	if (unlikely(err)) {
		printk(KERN_ERR
		       "NILFS: unable to write superblock (err=%d)\n", err);
		if (err == -EIO && nilfs->ns_sbh[1]) {
			/*
			 * sbp[0] points to newer log than sbp[1],
			 * so copy sbp[0] to sbp[1] to take over sbp[0].
			 */
			memcpy(nilfs->ns_sbp[1], nilfs->ns_sbp[0],
			       nilfs->ns_sbsize);
			nilfs_fall_back_super_block(nilfs);
			goto retry;
		}
	} else {
		struct nilfs_super_block *sbp = nilfs->ns_sbp[0];

		nilfs->ns_sbwcount++;

		/*
		 * The latest segment becomes trailable from the position
		 * written in superblock.
		 */
		clear_nilfs_discontinued(nilfs);

		/* update GC protection for recent segments */
		if (nilfs->ns_sbh[1]) {
			if (flag == NILFS_SB_COMMIT_ALL) {
				set_buffer_dirty(nilfs->ns_sbh[1]);
				if (sync_dirty_buffer(nilfs->ns_sbh[1]) < 0)
					goto out;
			}
			if (le64_to_cpu(nilfs->ns_sbp[1]->s_last_cno) <
			    le64_to_cpu(nilfs->ns_sbp[0]->s_last_cno))
				sbp = nilfs->ns_sbp[1];
		}

		spin_lock(&nilfs->ns_last_segment_lock);
		nilfs->ns_prot_seq = le64_to_cpu(sbp->s_last_seq);
		spin_unlock(&nilfs->ns_last_segment_lock);
	}
 out:
	return err;
}